fln 1.1.3 → 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.
- package/README.md +335 -179
- package/dist/api/fln.js +67 -30
- package/dist/api/types.d.ts +12 -1
- package/dist/cli/commandLine.js +68 -18
- package/dist/cli/help.d.ts +1 -1
- package/dist/cli/help.js +20 -8
- package/dist/cli/output/components/index.d.ts +0 -1
- package/dist/cli/output/components/index.js +0 -1
- package/dist/cli/output/renderer.d.ts +1 -3
- package/dist/cli/output/renderer.js +2 -5
- package/dist/config/defaults.d.ts +1 -1
- package/dist/config/defaults.js +1 -1
- package/dist/config/index.d.ts +1 -0
- package/dist/config/index.js +1 -0
- package/dist/config/initTemplate.d.ts +1 -0
- package/dist/config/initTemplate.js +32 -0
- package/dist/config/loader.d.ts +6 -1
- package/dist/config/loader.js +10 -4
- package/dist/config/resolver.d.ts +5 -2
- package/dist/config/resolver.js +31 -21
- package/dist/config/types.d.ts +18 -7
- package/dist/config/utils.d.ts +5 -2
- package/dist/config/utils.js +54 -48
- package/dist/core/ignoreMatcher.d.ts +3 -2
- package/dist/core/ignoreMatcher.js +32 -34
- package/dist/core/renderOutput.js +46 -45
- package/dist/core/scanTree.js +47 -70
- package/dist/core/size.js +6 -20
- package/dist/core/types.d.ts +6 -6
- package/dist/index.d.ts +0 -2
- package/dist/index.js +0 -2
- package/dist/infra/datetime.js +8 -6
- package/dist/infra/deprecate.d.ts +2 -0
- package/dist/infra/deprecate.js +14 -0
- package/dist/infra/gitDiff.d.ts +2 -0
- package/dist/infra/gitDiff.js +33 -0
- package/dist/infra/index.d.ts +2 -0
- package/dist/infra/index.js +2 -0
- package/dist/infra/logger.d.ts +1 -1
- package/dist/infra/logger.js +15 -18
- package/dist/infra/outputWriter.d.ts +1 -1
- package/dist/infra/outputWriter.js +21 -3
- package/dist/infra/terminal.d.ts +4 -32
- package/dist/infra/terminal.js +26 -54
- package/dist/path/canonical.d.ts +1 -0
- package/dist/path/canonical.js +13 -0
- package/dist/path/ignoreSafe.d.ts +1 -0
- package/dist/path/ignoreSafe.js +15 -0
- package/dist/path/index.d.ts +6 -0
- package/dist/path/index.js +6 -0
- package/dist/path/normalize.d.ts +2 -0
- package/dist/path/normalize.js +9 -0
- package/dist/path/output.d.ts +4 -0
- package/dist/path/output.js +12 -0
- package/dist/path/posix.d.ts +1 -0
- package/dist/path/posix.js +4 -0
- package/dist/path/resolve.d.ts +1 -0
- package/dist/path/resolve.js +6 -0
- package/dist/pattern/index.d.ts +1 -0
- package/dist/pattern/index.js +1 -0
- package/dist/pattern/normalize.d.ts +2 -0
- package/dist/pattern/normalize.js +43 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +7 -3
- package/dist/cli/output/components/progressBar.d.ts +0 -6
- package/dist/cli/output/components/progressBar.js +0 -38
package/README.md
CHANGED
|
@@ -2,124 +2,190 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://github.com/nesvet/fln/actions/workflows/ci.yaml)
|
|
4
4
|
[](https://www.npmjs.com/package/fln)
|
|
5
|
+
[](https://www.npmjs.com/package/fln)
|
|
5
6
|
[](LICENSE)
|
|
6
7
|
|
|
7
|
-
**Your entire codebase →
|
|
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
|
|
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, you
|
|
24
|
+
If you use LLMs for real projects, you've hit these limits:
|
|
28
25
|
|
|
29
|
-
- **Context windows** — large projects don
|
|
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
|
|
41
|
-
>
|
|
42
|
-
>
|
|
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
|
|
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
|
-
|
|
47
|
+
Detect patterns, inconsistencies, and risks across the entire codebase at once.
|
|
49
48
|
|
|
50
|
-
**→ Auditable
|
|
51
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
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`,
|
|
72
|
-
- 📁 **Intentional file order** — entry points and configs first
|
|
73
|
-
-
|
|
74
|
-
-
|
|
75
|
-
-
|
|
76
|
-
-
|
|
77
|
-
-
|
|
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
|
-
|
|
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
|
|
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
|
|
94
|
-
```
|
|
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
|
-
|
|
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
|
|
177
|
+
curl -fsSL https://fln.nesvet.dev/install | FLN_VERSION="<version>" INSTALL_DIR="$HOME/.local/bin" sh
|
|
112
178
|
```
|
|
113
179
|
|
|
114
|
-
|
|
180
|
+
**Windows PowerShell:**
|
|
115
181
|
|
|
116
182
|
```powershell
|
|
117
183
|
$env:FLN_VERSION = "<version>"
|
|
118
|
-
$env:INSTALL_DIR = "$env:LOCALAPPDATA
|
|
184
|
+
$env:INSTALL_DIR = "$env:LOCALAPPDATA\fln\bin"
|
|
119
185
|
powershell -c "irm fln.nesvet.dev/install.ps1 | iex"
|
|
120
186
|
```
|
|
121
187
|
|
|
122
|
-
|
|
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] [
|
|
202
|
+
fln [directory] [...flags]
|
|
203
|
+
fln init [--overwrite]
|
|
135
204
|
```
|
|
136
205
|
|
|
137
|
-
Examples:
|
|
138
|
-
|
|
139
206
|
```bash
|
|
140
|
-
# Flatten
|
|
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
|
-
#
|
|
144
|
-
fln
|
|
222
|
+
# TypeScript source only
|
|
223
|
+
fln --ext ts,tsx
|
|
145
224
|
|
|
146
|
-
#
|
|
147
|
-
fln
|
|
225
|
+
# Changed files since last commit
|
|
226
|
+
fln --since HEAD~1
|
|
148
227
|
|
|
149
|
-
#
|
|
150
|
-
fln
|
|
228
|
+
# Tree only — no file contents
|
|
229
|
+
fln --no-contents
|
|
151
230
|
|
|
152
|
-
#
|
|
153
|
-
fln .
|
|
231
|
+
# Force-include a file that's in .gitignore
|
|
232
|
+
fln -i "src/generated/schema.ts"
|
|
154
233
|
|
|
155
|
-
#
|
|
156
|
-
fln
|
|
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
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
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
|
-
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Config file
|
|
303
|
+
|
|
304
|
+
```bash
|
|
305
|
+
fln init
|
|
306
|
+
```
|
|
189
307
|
|
|
190
|
-
|
|
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
|
-
|
|
310
|
+
<details>
|
|
311
|
+
<summary>.fln.json reference</summary>
|
|
193
312
|
|
|
194
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
372
|
+
### Pre-commit context guard
|
|
227
373
|
|
|
228
|
-
|
|
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
|
-
#
|
|
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
|
-
|
|
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
|
-
|
|
245
|
-
|
|
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
|
-
|
|
397
|
+
process.stdout.write(`\r${current}/${total} files`);
|
|
251
398
|
}
|
|
252
399
|
});
|
|
253
400
|
|
|
254
|
-
console.log(
|
|
255
|
-
console.log(
|
|
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>
|
|
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
|
-
```
|
|
268
|
-
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
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
|
-
|
|
294
|
-
<summary>Output naming & formats</summary>
|
|
453
|
+
---
|
|
295
454
|
|
|
296
|
-
|
|
297
|
-
- `md` includes tree + contents
|
|
298
|
-
- `json` includes `rootDirectory`, `tree`, `stats`
|
|
455
|
+
## Preview
|
|
299
456
|
|
|
300
|
-
|
|
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
|
-
|
|
474
|
+
**Standalone binary** — no runtime required. Install via the `curl` / PowerShell one-liner above.
|
|
315
475
|
|
|
316
|
-
|
|
476
|
+
</details>
|
|
317
477
|
|
|
318
|
-
|
|
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
|
-
|
|
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
|
-
|
|
332
|
-
-
|
|
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)
|