fln 1.1.2 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/README.md +335 -179
  2. package/dist/api/fln.d.ts +1 -1
  3. package/dist/api/fln.js +69 -32
  4. package/dist/api/index.d.ts +2 -2
  5. package/dist/api/index.js +2 -2
  6. package/dist/api/types.d.ts +12 -1
  7. package/dist/cli/commandLine.js +73 -23
  8. package/dist/cli/help.d.ts +1 -1
  9. package/dist/cli/help.js +21 -9
  10. package/dist/cli/index.js +1 -1
  11. package/dist/cli/output/components/breakdown.js +2 -2
  12. package/dist/cli/output/components/errors.js +1 -1
  13. package/dist/cli/output/components/index.d.ts +4 -5
  14. package/dist/cli/output/components/index.js +4 -5
  15. package/dist/cli/output/components/summary.js +2 -2
  16. package/dist/cli/output/components/warnings.js +1 -1
  17. package/dist/cli/output/index.d.ts +4 -4
  18. package/dist/cli/output/index.js +4 -4
  19. package/dist/cli/output/renderer.d.ts +3 -5
  20. package/dist/cli/output/renderer.js +4 -7
  21. package/dist/cli/output/styles.d.ts +7 -7
  22. package/dist/config/defaults.d.ts +1 -1
  23. package/dist/config/defaults.js +1 -1
  24. package/dist/config/index.d.ts +6 -5
  25. package/dist/config/index.js +6 -5
  26. package/dist/config/initTemplate.d.ts +1 -0
  27. package/dist/config/initTemplate.js +32 -0
  28. package/dist/config/loader.d.ts +7 -2
  29. package/dist/config/loader.js +10 -4
  30. package/dist/config/resolver.d.ts +6 -3
  31. package/dist/config/resolver.js +32 -22
  32. package/dist/config/types.d.ts +19 -8
  33. package/dist/config/utils.d.ts +5 -2
  34. package/dist/config/utils.js +54 -48
  35. package/dist/core/ignoreMatcher.d.ts +4 -3
  36. package/dist/core/ignoreMatcher.js +32 -34
  37. package/dist/core/index.d.ts +7 -7
  38. package/dist/core/index.js +7 -7
  39. package/dist/core/renderOutput.d.ts +2 -2
  40. package/dist/core/renderOutput.js +50 -49
  41. package/dist/core/renderTree.d.ts +1 -1
  42. package/dist/core/scanTree.d.ts +2 -2
  43. package/dist/core/scanTree.js +48 -71
  44. package/dist/core/size.js +6 -20
  45. package/dist/core/statsCollector.d.ts +1 -1
  46. package/dist/core/types.d.ts +6 -6
  47. package/dist/index.d.ts +1 -3
  48. package/dist/index.js +1 -3
  49. package/dist/infra/datetime.js +8 -6
  50. package/dist/infra/deprecate.d.ts +2 -0
  51. package/dist/infra/deprecate.js +14 -0
  52. package/dist/infra/gitDiff.d.ts +2 -0
  53. package/dist/infra/gitDiff.js +33 -0
  54. package/dist/infra/index.d.ts +8 -6
  55. package/dist/infra/index.js +8 -6
  56. package/dist/infra/logger.d.ts +2 -2
  57. package/dist/infra/logger.js +15 -18
  58. package/dist/infra/outputWriter.d.ts +1 -1
  59. package/dist/infra/outputWriter.js +22 -4
  60. package/dist/infra/terminal.d.ts +4 -32
  61. package/dist/infra/terminal.js +26 -54
  62. package/dist/path/canonical.d.ts +1 -0
  63. package/dist/path/canonical.js +13 -0
  64. package/dist/path/ignoreSafe.d.ts +1 -0
  65. package/dist/path/ignoreSafe.js +15 -0
  66. package/dist/path/index.d.ts +6 -0
  67. package/dist/path/index.js +6 -0
  68. package/dist/path/normalize.d.ts +2 -0
  69. package/dist/path/normalize.js +9 -0
  70. package/dist/path/output.d.ts +4 -0
  71. package/dist/path/output.js +12 -0
  72. package/dist/path/posix.d.ts +1 -0
  73. package/dist/path/posix.js +4 -0
  74. package/dist/path/resolve.d.ts +1 -0
  75. package/dist/path/resolve.js +6 -0
  76. package/dist/pattern/index.d.ts +1 -0
  77. package/dist/pattern/index.js +1 -0
  78. package/dist/pattern/normalize.d.ts +2 -0
  79. package/dist/pattern/normalize.js +43 -0
  80. package/dist/version.d.ts +1 -1
  81. package/dist/version.js +1 -1
  82. package/package.json +7 -3
  83. package/dist/cli/output/components/progressBar.d.ts +0 -6
  84. package/dist/cli/output/components/progressBar.js +0 -38
package/README.md CHANGED
@@ -2,124 +2,190 @@
2
2
 
3
3
  [![CI](https://github.com/nesvet/fln/actions/workflows/ci.yaml/badge.svg)](https://github.com/nesvet/fln/actions/workflows/ci.yaml)
4
4
  [![npm](https://img.shields.io/npm/v/fln)](https://www.npmjs.com/package/fln)
5
+ [![npm downloads](https://img.shields.io/npm/dm/fln)](https://www.npmjs.com/package/fln)
5
6
  [![license](https://img.shields.io/npm/l/fln)](LICENSE)
6
7
 
7
- **Your entire codebase → One AI-ready file.**
8
+ **Your entire codebase → one AI-ready file.**
8
9
 
9
10
  Stop wrestling with file pickers and attachment limits — feed your whole project to any LLM in one shot.
10
11
 
11
12
  ```bash
12
- fln .
13
- ```
14
-
15
- Or run instantly:
16
-
17
- ```bash
18
- npx fln . -o codebase.md
13
+ npx fln
19
14
  ```
20
15
 
21
16
  Works with **Claude**, **ChatGPT**, **Gemini**, **Grok**, **Cursor**, **Copilot**, and *any* AI tool.
22
17
 
23
- **`fln`** (short for *flatten*) is **language-agnostic** by design: TypeScript, Python, Java, Go, Rust, Bash, SQL, mixed monorepos — it treats everything as plain text, detects project metadata from common manifests (`package.json`, `pyproject.toml`, `pom.xml`, `go.mod`, `Cargo.toml`, `CMakeLists.txt`, `vcpkg.json`), respects `.gitignore`, and skips binaries by default.
18
+ **`fln`** (short for *flatten*) is language-agnostic by design: TypeScript, Python, Rust, Go, Java, mixed monorepos — it treats everything as plain text, auto-detects project metadata from ecosystem manifests, respects `.gitignore`, and skips binaries automatically.
19
+
20
+ ---
24
21
 
25
22
  ## Why fln exists
26
23
 
27
- If you use LLMs for real projects, youve hit these limits:
24
+ If you use LLMs for real projects, you've hit these limits:
28
25
 
29
- - **Context windows** — large projects dont fit.
30
- - **Upload friction** — selecting dozens of files for every session.
31
- - **Partial understanding** — AI sees fragments, not the architecture.
32
- - **Manual prep** — repeating the same setup context again and again.
26
+ - **Context windows** — large projects don't fit
27
+ - **Upload friction** — selecting dozens of files for every session
28
+ - **Partial understanding** — AI sees fragments, not the architecture
29
+ - **Manual prep** — repeating the same setup context again and again
33
30
 
34
31
  **`fln` removes that overhead.**
35
32
  It turns your project into a single, structured snapshot that LLMs can actually reason about.
36
33
 
34
+ ---
35
+
37
36
  ## What fln enables
38
37
 
39
38
  **→ Full-context refactoring**
40
- Ask architectural questions that are impossible file-by-file:
41
- > Where is the real coupling here?”
42
- > What should be split into modules?”
39
+ Ask architectural questions impossible file-by-file:
40
+ > "Where is the real coupling here?"
41
+ > "What should be split into modules?"
43
42
 
44
43
  **→ Instant onboarding**
45
- One markdown file instead of start by opening these 12 folders”. Perfect for reading code on a tablet or onboarding new developers without an IDE.
44
+ One Markdown file instead of "start by opening these 12 folders." Perfect for reading code on a tablet or onboarding new developers without an IDE.
46
45
 
47
46
  **→ Project-level code reviews**
48
- Let AI detect patterns, inconsistencies, and risks across the entire codebase.
47
+ Detect patterns, inconsistencies, and risks across the entire codebase at once.
49
48
 
50
- **→ Auditable Snapshots**
51
- Create a single, clean artifact of your codebase state for security reviews, compliance audits, or legal records without granting full repo access.
49
+ **→ Auditable snapshots**
50
+ A single, clean artifact of your codebase state for security reviews, compliance audits, or legal records without granting full repo access.
52
51
 
53
- **→ Dataset Preparation**
52
+ **→ Dataset preparation**
54
53
  Generate clean, formatted data for RAG pipelines and fine-tuning custom models.
55
54
 
56
55
  **→ LLM-friendly diffs**
57
- Flatten → commit → flatten again. See how the *whole project* changed structurally.
56
+ Flatten → commit → flatten again. See how the whole project changed structurally.
57
+
58
+ ---
59
+
60
+ ## Instant clipboard
61
+
62
+ ```bash
63
+ fln --stdout | pbcopy # macOS
64
+ fln --stdout | wl-copy # Linux (Wayland)
65
+ fln --stdout | xclip -selection clipboard # Linux (X11)
66
+ ```
67
+
68
+ One command — your entire codebase is in the clipboard. Open any AI chat, paste, ask.
69
+
70
+ ---
71
+
72
+ ## Pipe directly to a CLI LLM tool
58
73
 
59
- ## Compatible with your AI workflow
74
+ ```bash
75
+ fln --stdout | llm "What are the biggest architecture issues here?"
76
+ fln --stdout | aichat "Write a CHANGELOG entry for the latest changes"
77
+ fln --stdout | sgpt "Suggest a refactoring plan for this codebase"
78
+ ```
79
+
80
+ ---
81
+
82
+ ## Only changed files — perfect for code review
83
+
84
+ ```bash
85
+ # Everything changed since the last commit
86
+ fln --since HEAD~1
87
+
88
+ # Everything that differs from main
89
+ fln --since main
60
90
 
61
- - **Claude** ideal for large architectural prompts (200K+ tokens).
62
- - **Gemini** push massive codebases into 1M token windows.
63
- - **ChatGPT** — single-shot analysis without attachments.
64
- - **Cursor / Windsurf** — reference the full project in prompts.
65
- - **GitHub Copilot** better context better suggestions.
66
- - **Local LLMs** — datasets for RAG and fine-tuning.
91
+ # Only changed TypeScript files (intersection, not union)
92
+ fln --since main --ext ts,tsx
93
+ ```
94
+
95
+ `--since` calls `git diff --name-only` under the hood. Zero config.
96
+
97
+ ---
98
+
99
+ ## Only the file types you care about
100
+
101
+ ```bash
102
+ fln --ext ts,tsx # TypeScript only — dramatically reduces token count
103
+ fln --ext py # Python only
104
+ fln --ext rs # Rust only
105
+ fln --ext go # Go only
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Embed a custom prompt right into the snapshot
111
+
112
+ Put your system prompt in a file — it will be prepended to the output and excluded from the directory tree:
113
+
114
+ ```bash
115
+ fln --banner-file .prompt.md
116
+ ```
117
+
118
+ ```markdown
119
+ <!-- .prompt.md -->
120
+ You are a senior engineer reviewing a production codebase.
121
+ Identify architecture issues, suggest improvements, point out any bugs.
122
+ ```
123
+
124
+ Or inline:
125
+
126
+ ```bash
127
+ fln --banner "Review this codebase for security vulnerabilities."
128
+ ```
129
+
130
+ Same for footers: `--footer-file` / `--footer`.
131
+
132
+ ---
67
133
 
68
134
  ## Built for real projects
69
135
 
70
- - ⚡ **Fast parallel scanning** — thousands of files in seconds.
71
- - 🎯 **Smart filtering** — respects `.gitignore`, excludes binaries, configurable size limits.
72
- - 📁 **Intentional file order** — entry points and configs first, not alphabetical noise.
73
- - 🔄 **Auto-detection** — skips files previously generated by `fln`.
74
- - 📐 **Deterministic output** — same input same snapshot.
75
- - 🧠 **Project metadata detection** — name & version from ecosystem-native manifests.
76
- - 🛠️ **Developer-friendly** — `Markdown` for humans, `JSON` for tooling, `--dry-run` mode for safety.
77
- - 🔒 **No surprises** — runs locally, no data leaves your machine.
136
+ - ⚡ **Fast parallel scanning** — thousands of files in seconds
137
+ - 🎯 **Smart filtering** — respects `.gitignore`, skips binaries and lock files, configurable size limits
138
+ - 📁 **Intentional file order** — `README`, entry points, and configs first; `LICENSE`, `CHANGELOG` last. LLMs see the most important context first
139
+ - 📊 **Token count upfront** — every run reports estimated tokens so you know what you're sending before you hit send
140
+ - 🔍 **Extension breakdown** — `--verbose` shows token distribution by file type, so you know exactly what's eating your context window
141
+ - 🔄 **Self-aware** — skips files previously generated by `fln`, never recurses into its own output
142
+ - 🛡️ **Backtick-safe** — if a file contains ` ``` `, fln automatically uses longer fences so the Markdown never breaks
143
+ - 📐 **Deterministic output** — same input same snapshot
144
+ - 🧠 **Project metadata detection** — output named `my-app-1.2.0.md` automatically from `package.json`, `Cargo.toml`, `pyproject.toml`, `pom.xml`, `go.mod`, `vcpkg.json`, `CMakeLists.txt`
145
+ - 🛠️ **Two output formats** — `md` for humans, `json` for tooling
146
+ - 🔒 **Fully local** — zero telemetry, zero network calls, no data leaves your machine
78
147
 
79
- Zero dependencies on external services. Zero tracking. Just a tool that does its job.
148
+ ---
80
149
 
81
150
  ## Install
82
151
 
83
- ##### npm
152
+ ##### npm / Bun
84
153
  ```bash
154
+ npx fln # run once without installing
155
+ bunx fln
156
+
85
157
  npm install -g fln
158
+ bun add -g fln
86
159
  ```
87
160
 
88
- ##### Linux & macOS ([view install script](./install.sh))
161
+ ##### macOS / Linux native binary, no Node.js required
89
162
  ```bash
90
163
  curl -fsSL https://fln.nesvet.dev/install | sh
91
164
  ```
92
165
 
93
- ##### Windows ([view install script](./install.ps1))
94
- ```bash
166
+ ##### Windows native binary, no Node.js required
167
+ ```powershell
95
168
  powershell -c "irm fln.nesvet.dev/install.ps1 | iex"
96
169
  ```
97
170
 
98
- ##### Or just run without installing
99
- ```bash
100
- npx fln . -o codebase.md
101
- ```
102
-
103
171
  <details>
104
172
  <summary>More installation options</summary>
105
173
 
106
- ### One-line installer options (macOS/Linux)
107
-
108
- Pin a version or custom install directory:
174
+ **Pin a specific version or install to a custom directory (macOS/Linux):**
109
175
 
110
176
  ```bash
111
- curl -fsSL "https://fln.nesvet.dev/install" | FLN_VERSION="<version>" INSTALL_DIR="$HOME/.local/bin" sh
177
+ curl -fsSL https://fln.nesvet.dev/install | FLN_VERSION="<version>" INSTALL_DIR="$HOME/.local/bin" sh
112
178
  ```
113
179
 
114
- ### One-line installer options (Windows PowerShell)
180
+ **Windows PowerShell:**
115
181
 
116
182
  ```powershell
117
183
  $env:FLN_VERSION = "<version>"
118
- $env:INSTALL_DIR = "$env:LOCALAPPDATA\\fln\\bin"
184
+ $env:INSTALL_DIR = "$env:LOCALAPPDATA\fln\bin"
119
185
  powershell -c "irm fln.nesvet.dev/install.ps1 | iex"
120
186
  ```
121
187
 
122
- ### Manual download (GitHub Releases)
188
+ **Manual download from GitHub Releases:**
123
189
 
124
190
  ```bash
125
191
  curl -L "https://github.com/nesvet/fln/releases/latest/download/fln-macos-x64.tar.gz" | tar -xz -C /usr/local/bin
@@ -128,74 +194,160 @@ chmod +x /usr/local/bin/fln
128
194
 
129
195
  </details>
130
196
 
197
+ ---
198
+
131
199
  ## Usage
132
200
 
133
201
  ```bash
134
- fln [directory] [options]
202
+ fln [directory] [...flags]
203
+ fln init [--overwrite]
135
204
  ```
136
205
 
137
- Examples:
138
-
139
206
  ```bash
140
- # Flatten entire project
141
- fln .
207
+ # Flatten the current directory → my-app-1.2.0.md
208
+ fln
209
+
210
+ # Specify input and output
211
+ fln . -o context.md
212
+
213
+ # Scan src/, save output to the project root
214
+ fln src -o .
215
+
216
+ # Source files only — no tests, no fixtures
217
+ fln -e "*.test.ts" -e "*.spec.ts" -e "fixtures/"
218
+
219
+ # Include all source files but exclude markdown — except README
220
+ fln -e "*.md" -e '!README.md'
142
221
 
143
- # Exclude tests and fixtures
144
- fln src -e "**/*.test.ts" -e "fixtures/"
222
+ # TypeScript source only
223
+ fln --ext ts,tsx
145
224
 
146
- # Force include a file (even if ignored)
147
- fln . -i "dist/output.md"
225
+ # Changed files since last commit
226
+ fln --since HEAD~1
148
227
 
149
- # Generate JSON for tooling
150
- fln . --no-contents --format json
228
+ # Tree only no file contents
229
+ fln --no-contents
151
230
 
152
- # Preview without writing
153
- fln . --dry-run
231
+ # Force-include a file that's in .gitignore
232
+ fln -i "src/generated/schema.ts"
154
233
 
155
- # Overwrite output file instead of creating codebase-1.md
156
- fln . -o codebase.md -w
234
+ # Preview what would be included, with per-extension breakdown
235
+ fln --dry-run --verbose
236
+
237
+ # Overwrite instead of creating codebase-1.md
238
+ fln -o codebase.md -w
239
+
240
+ # JSON output for programmatic use
241
+ fln --format json -o snapshot.json
157
242
  ```
158
243
 
159
244
  <details>
160
- <summary>All CLI options</summary>
161
-
162
- - `-o, --output <path>` Output file or directory
163
- - `-w, --overwrite` Overwrite output file instead of adding numeric suffix
164
- - `-e, --exclude <glob>` Exclude patterns (repeatable)
165
- - `-i, --include <glob>` Force include patterns
166
- - `--include-hidden` Include hidden files and directories
167
- - `--no-gitignore` Ignore `.gitignore`
168
- - `--max-size <size>` Max file size (`10mb`, `512kb`)
169
- - `--max-total-size <size>` Max total included size
170
- - `--no-contents` Exclude file contents
171
- - `--no-tree` Exclude directory tree
172
- - `--format <md|json>` Output format
173
- - `--dry-run` Scan without writing output
174
- - `--follow-symlinks` Follow symlinks
175
- - `--no-ansi` Disable ANSI colors
176
- - `--no-sponsor-message` Hide support message (also: `FLN_NO_SPONSOR=1`)
177
- - `--generated-date <date>` Use this date in the “Generated” header (format: `YYYY-MM-DD HH:mm`)
178
- - `--banner <text>` Add text at the beginning
179
- - `--footer <text>` Add text at the end of the output
180
- - `-q, --quiet` Minimal output
181
- - `-V, --verbose` Verbose output with breakdown
182
- - `--debug` Debug output with file list
183
- - `-v, --version` Show version
184
- - `-h, --help` Show help
245
+ <summary>All CLI flags</summary>
246
+
247
+ **Output**
248
+
249
+ | Flag | Description |
250
+ |---|---|
251
+ | `-o, --output <path>` | Output file or directory. Adds `.md`/`.json` if no extension given. Default: `<n>-<version>.md` |
252
+ | `-w, --overwrite` | Overwrite instead of adding numeric suffix |
253
+ | `--stdout` | Write to stdout instead of file (implies `--quiet`) |
254
+ | `--format <md\|json>` | Output format (default: `md`) |
255
+ | `--dry-run` | Scan and report without writing anything |
256
+
257
+ **Filtering**
258
+
259
+ | Flag | Description |
260
+ |---|---|
261
+ | `-e, --exclude <glob>` | Exclude pattern — repeatable |
262
+ | `-i, --include <glob>` | Whitelist mode only matching files are included, repeatable |
263
+ | `--ext <ext>` | Include only these extensions, e.g. `ts,tsx,js` |
264
+ | `--since <ref>` | Only files changed since git ref, e.g. `HEAD~1`, `main` |
265
+ | `--include-hidden` | Include hidden files and directories |
266
+ | `--no-gitignore` | Ignore `.gitignore` rules |
267
+ | `--max-size <size>` | Max individual file size, e.g. `10mb`, `512kb` |
268
+ | `--max-total-size <size>` | Max total size of all included files |
269
+ | `--follow-symlinks` | Follow symlinks while scanning |
270
+
271
+ **Content**
272
+
273
+ | Flag | Description |
274
+ |---|---|
275
+ | `--no-contents` | Exclude file contents (tree only) |
276
+ | `--no-tree` | Exclude directory tree |
277
+ | `--banner <text>` | Prepend text after the header |
278
+ | `--banner-file <path>` | Prepend file contents — relative to input, excluded from tree |
279
+ | `--footer <text>` | Append text at the end |
280
+ | `--footer-file <path>` | Append file contents — relative to input, excluded from tree |
281
+ | `--date <YYYY-MM-DD HH:mm>` | Fix the Generated date (useful for reproducible output) |
282
+
283
+ **Logging & other**
284
+
285
+ | Flag | Description |
286
+ |---|---|
287
+ | `-q, --quiet` | Minimal output |
288
+ | `-V, --verbose` | Verbose output with per-extension token breakdown |
289
+ | `--debug` | Debug output with full file list |
290
+ | `--no-ansi` | Disable colors |
291
+ | `--no-sponsor-message` | Hide support message (also: `FLN_NO_SPONSOR=1`) |
292
+ | `-v, --version` | Show version |
293
+ | `-h, --help` | Show help |
294
+
295
+ > **Note:** Quote glob patterns to prevent shell expansion — `"*.test.ts"`, not `*.test.ts`.
296
+ > To un-exclude a specific file, use negation in `--exclude`: `-e "*.md" -e '!README.md'`.
185
297
 
186
298
  </details>
187
299
 
188
- ## CI/CD & Automation
300
+ ---
301
+
302
+ ## Config file
303
+
304
+ ```bash
305
+ fln init
306
+ ```
189
307
 
190
- Integrate `fln` into your pipeline to keep your codebase “AI-ready” automatically.
308
+ Generates `.fln.json` with full IntelliSense support in VS Code, WebStorm, and any editor with JSON Schema — autocomplete and validation out of the box, no extensions needed.
191
309
 
192
- ### GitHub Actions: Auto-generate Snapshots
310
+ <details>
311
+ <summary>.fln.json reference</summary>
193
312
 
194
- Generate a fresh `codebase.md` artifact on every push. Download it anytime to chat with LLMs about the *exact* state of your main branch or a specific PR without manual scanning.
313
+ ```json
314
+ {
315
+ "$schema": "https://fln.nesvet.dev/schema",
316
+ "output": "snapshot.md",
317
+ "overwrite": false,
318
+ "excludePatterns": [ "dist/", "**/*.snap" ],
319
+ "includePatterns": [],
320
+ "includeHidden": false,
321
+ "gitignore": true,
322
+ "maxFileSize": "10mb",
323
+ "maxTotalSize": "0",
324
+ "includeTree": true,
325
+ "includeContents": true,
326
+ "format": "md",
327
+ "followSymlinks": false,
328
+ "logLevel": "normal",
329
+ "date": "2026-02-20 12:00",
330
+ "banner": "You are reviewing a production codebase.",
331
+ "bannerFile": ".prompt.md",
332
+ "footer": "End of snapshot.",
333
+ "footerFile": "docs/footer.md"
334
+ }
335
+ ```
336
+
337
+ **Pattern format:** gitignore-style globs relative to the input directory. Leading `./` is normalized. Use `!` for negation (`*.log` + `!important.log`). Trailing slash `src/` matches directories only. CLI flags always override the config file.
195
338
 
196
- Create `.github/workflows/codebase-snapshot.yaml`:
339
+ </details>
340
+
341
+ ---
342
+
343
+ ## CI/CD & Automation
344
+
345
+ ### GitHub Actions — auto-generate snapshots
346
+
347
+ Fresh `codebase.md` on every push. Download it anytime to chat with LLMs about the exact state of your main branch or a specific PR:
197
348
 
198
349
  ```yaml
350
+ # .github/workflows/codebase-snapshot.yaml
199
351
  name: Snapshot Codebase
200
352
 
201
353
  on:
@@ -206,136 +358,140 @@ on:
206
358
  jobs:
207
359
  snapshot:
208
360
  runs-on: ubuntu-latest
209
- permissions:
210
- contents: read
211
361
  steps:
212
362
  - uses: actions/checkout@v6
213
-
214
- - name: Generate Snapshot
215
- # Generates codebase.md without installing fln globally
363
+ - name: Generate snapshot
216
364
  run: npx fln . -o codebase.md -w --no-ansi
217
-
218
- - name: Upload Artifact
219
- uses: actions/upload-artifact@v6
365
+ - uses: actions/upload-artifact@v6
220
366
  with:
221
367
  name: codebase-snapshot
222
368
  path: codebase.md
223
369
  retention-days: 7
224
370
  ```
225
371
 
226
- ### Git Hooks: Pre-commit Context Guard
372
+ ### Pre-commit context guard
227
373
 
228
- Prevent accidental “context bloat” (e.g., committing large datasets or wrong lockfiles) by failing commits if the flattened codebase exceeds a specific size. This ensures your project always fits within LLM context windows.
229
-
230
- Add to your pre-commit hook (e.g., via `husky` or `lint-staged`):
374
+ Fail the commit if the flattened codebase exceeds a size limit ensures the project always fits in LLM context windows:
231
375
 
232
376
  ```bash
233
- # Fails the commit if the flattened codebase exceeds 5MB (configurable)
234
- # --dry-run ensures no files are written to disk
377
+ # .husky/pre-commit
235
378
  npx fln . --dry-run --max-total-size 5mb
236
379
  ```
237
380
 
238
- ## JavaScript API
381
+ ---
382
+
383
+ ## API
384
+
385
+ ```bash
386
+ npm install fln
387
+ ```
239
388
 
240
389
  ```typescript
241
390
  import { fln } from "fln";
242
391
 
243
392
  const result = await fln({
244
- rootDirectory: "./src",
245
- outputFile: "output.md",
246
- overwrite: true,
393
+ input: "./src",
394
+ output: "snapshot.md",
247
395
  excludePatterns: [ "*.test.ts", "fixtures/" ],
248
- format: "md",
249
396
  onProgress: (current, total) => {
250
- console.log(`Progress: ${current}/${total}`);
397
+ process.stdout.write(`\r${current}/${total} files`);
251
398
  }
252
399
  });
253
400
 
254
- console.log(`Processed ${result.files} files`);
255
- console.log(`Output: ${result.outputPath}`);
256
- console.log(`Tokens: ${result.outputTokenCount}`);
401
+ console.log(`${result.files} files → ${result.outputPath}`);
402
+ console.log(`~${result.outputTokenCount.toLocaleString()} tokens`);
257
403
  ```
258
404
 
259
- All CLI options are available via `FlnOptions`.
260
-
261
-
262
- ## Advanced
263
-
264
405
  <details>
265
- <summary>Configuration file (.fln.json)</summary>
406
+ <summary>Full API reference</summary>
407
+
408
+ **Options**
409
+
410
+ | Option | Type | Default | Description |
411
+ |---|---|---|---|
412
+ | `input` | `string` | `process.cwd()` | Directory to flatten |
413
+ | `output` | `string` | auto | Output file path or directory. `"-"` for stdout |
414
+ | `overwrite` | `boolean` | `false` | Overwrite instead of numeric suffix |
415
+ | `excludePatterns` | `string[]` | `[]` | Glob patterns to exclude |
416
+ | `includePatterns` | `string[]` | `[]` | Glob patterns to force include |
417
+ | `includeHidden` | `boolean` | `false` | Include hidden files/dirs |
418
+ | `gitignore` | `boolean` | `true` | Respect `.gitignore` rules |
419
+ | `maxFileSize` | `number \| string` | `"10mb"` | Max individual file size |
420
+ | `maxTotalSize` | `number \| string` | `0` | Max total size (0 = unlimited) |
421
+ | `includeContents` | `boolean` | `true` | Include file contents |
422
+ | `includeTree` | `boolean` | `true` | Include directory tree |
423
+ | `format` | `"md" \| "json"` | `"md"` | Output format |
424
+ | `followSymlinks` | `boolean` | `false` | Follow symlinks |
425
+ | `date` | `string` | current | Fixed `YYYY-MM-DD HH:mm` for Generated header |
426
+ | `banner` | `string` | — | Text prepended after header |
427
+ | `bannerFile` | `string` | — | File prepended (relative to input) |
428
+ | `footer` | `string` | — | Text appended at end |
429
+ | `footerFile` | `string` | — | File appended (relative to input) |
430
+ | `logLevel` | `"silent" \| "normal" \| "verbose" \| "debug"` | `"silent"` | Log level |
431
+ | `ansi` | `boolean` | `false` | ANSI colors in log output |
432
+ | `onProgress` | `(current, total) => void` | — | Progress callback |
433
+
434
+ **Result**
266
435
 
267
- ```json
268
- {
269
- "outputFile": "output.md",
270
- "overwrite": false,
271
- "excludePatterns": [
272
- "dist/",
273
- "**/*.snap"
274
- ],
275
- "includePatterns": [],
276
- "includeHidden": false,
277
- "useGitignore": true,
278
- "maximumFileSizeBytes": "10mb",
279
- "maximumTotalSizeBytes": "0",
280
- "includeTree": true,
281
- "includeContents": true,
282
- "format": "md",
283
- "followSymlinks": false,
284
- "logLevel": "normal",
285
- "generatedDate": "2026-02-09 12:00",
286
- "banner": "This is a snapshot of the codebase.",
287
- "footer": "End of snapshot."
288
- }
436
+ ```typescript
437
+ type FlnResult = {
438
+ projectName: string; // from package.json, pom.xml, Cargo.toml, etc.
439
+ files: number; // files included
440
+ directories: number; // directories scanned
441
+ binary: number; // binary files (shown as [BINARY FILE: X kb] in output)
442
+ skipped: number; // skipped — too large, generated by fln, or read errors
443
+ errors: number; // read errors
444
+ totalSizeBytes: number; // total input size
445
+ outputSizeBytes: number; // output file size
446
+ outputTokenCount: number; // estimated token count
447
+ outputPath: string; // absolute path ("-" for stdout)
448
+ };
289
449
  ```
290
450
 
291
451
  </details>
292
452
 
293
- <details>
294
- <summary>Output naming & formats</summary>
453
+ ---
295
454
 
296
- - Uses project name + version if available (`package.json`, `pyproject.toml`, `pom.xml`, `go.mod`, `Cargo.toml`, `CMakeLists.txt` or `vcpkg.json`)
297
- - `md` includes tree + contents
298
- - `json` includes `rootDirectory`, `tree`, `stats`
455
+ ## Preview
299
456
 
300
- </details>
457
+ Real outputs from [`examples/`](examples/):
458
+
459
+ - [TypeScript](examples/ts-app.md)
460
+ - [Python](examples/python-app.md)
461
+ - [Go](examples/go-app.md)
462
+ - [Rust](examples/rust-app.md)
463
+ - [Java](examples/java-app.md)
464
+
465
+ ---
301
466
 
302
467
  <details>
303
468
  <summary>Runtime compatibility</summary>
304
469
 
305
- **Node.js**
306
- - Requires Node.js `>=18.3`
307
- - ESM-only package (`"type": "module"`)
308
- - CLI works via `npm i -g fln` or `npx fln`
470
+ **Node.js** — requires `>=18.3.0`, ESM-only (`"type": "module"`). Install via `npm i -g fln` or run with `npx`.
309
471
 
310
- **Bun**
311
- - Requires Bun `>=1.0.0`
312
- - CLI works via `bun install -g fln` or `bunx fln`
472
+ **Bun** — requires `>=1.0.0`. Install via `bun add -g fln` or run with `bunx`.
313
473
 
314
- </details>
474
+ **Standalone binary** — no runtime required. Install via the `curl` / PowerShell one-liner above.
315
475
 
316
- ## Preview
476
+ </details>
317
477
 
318
- Full real outputs are provided below. Each example is a compact project in [`examples/`](examples/). `fln` outputs the directory tree and file contents with **entry points and configs first** (intentional file order):
319
-
320
- - [TypeScript](examples/ts-app.md)
321
- - [Python](examples/python-app.md)
322
- - [Java](examples/java-app.md)
323
- - [Go](examples/go-app.md)
324
- - [Rust](examples/rust-app.md)
478
+ ---
325
479
 
326
480
  ## Support this project
327
481
 
328
- **fln is free, open-source, and maintained by one developer.**
482
+ **`fln` is free, open-source, and maintained by one developer.**
329
483
 
330
484
  If it saves you time or improves your AI workflow:
331
- - ⭐️ Star the repo — it genuinely helps discoverability
332
- - 💙 Support on [Patreon](https://www.patreon.com/nesvet)priority features & long-term maintenance
485
+
486
+ - ⭐️ **Star the repo**it genuinely helps discoverability
487
+ - 💙 **[Support on Patreon](https://www.patreon.com/nesvet)** — keeps development going
488
+
489
+ ---
333
490
 
334
491
  ## Contributing
335
492
 
336
- PRs and issues are welcome.
337
- See [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup and guidelines.
493
+ PRs and issues are welcome. See [`CONTRIBUTING.md`](CONTRIBUTING.md) for setup and guidelines.
338
494
 
339
495
  ## License
340
496
 
341
- MIT
497
+ MIT © [Eugene Nesvetaev](https://nesvet.dev)