Selection Markdown ExporterA VS Code extension that exports selected files and folders to a single markdown file, perfect for AI analysis and documentation generation. Features
UsageTwo commands, differing only in where the export is delivered:
Both produce the same document, and the notification afterwards says which one it went to. Context Menu (Recommended)
Both entries sit in their own section of the context menu rather than at the top of it: an export is not a navigation action, and two commands crowding the top would be worse than the one that used to. Command Palette
Selection BehaviorThe extension handles different selection scenarios:
ConfigurationAll settings are available under Output Settings
Ignore SettingsAn ignored file appears nowhere in the export: the export gives no sign it existed. That is different from a stub — see Stub Settings below. Priority Order (Strict)In increasing precedence — the last source with something to say about a path decides:
Two rules stand outside that order, because they are the tool's own rather than yours. They cannot be configured off, and — unlike everything above — picking the path in the explorer does not override them:
Explicit picks winA file you picked in the explorer is exported even when an ignore rule matches it: picking it is what you said, and a rule is only what you said by default. The override stops at what you picked. A file the walk discovers inside a folder you picked is still judged normally — otherwise picking the project root would drag in everything the rules exist to keep out.
|
| Shape | Marker |
|---|---|
AWS access key (AKIA…, ASIA…) |
[REDACTED: AWS access key] |
GitHub token (ghp_, gho_, ghu_, ghs_, ghr_, github_pat_…) |
[REDACTED: GitHub token] |
Stripe key (sk_live_, sk_test_, pk_live_, pk_test_, rk_live_, rk_test_) |
[REDACTED: Stripe key] |
OpenAI API key (sk-…) |
[REDACTED: OpenAI API key] |
Anthropic API key (sk-ant-…) |
[REDACTED: Anthropic API key] |
A JSON Web Token (eyJ….….…) |
[REDACTED: JWT] |
A database URL's password (postgres://user:password@host, and the same for postgresql, mysql, mongodb, mongodb+srv, redis, rediss, amqp, amqps) |
[REDACTED: database password] — the scheme, user and host stay visible |
A replacement always says what it removed — [REDACTED: <what>] — rather
than vanishing into an empty string a reader has no way to notice.
The count is reported. The notification shown after an export states how many Redactions happened, zero included: zero is itself the answer to whether a selection contained anything recognisable.
markdownExport.redactionEnabled: Turn Redaction off entirely (default:true). Use this for the deliberate case — exporting a fixture file built with fake keys, where masking them would misrepresent the fixture itself."markdownExport.redactionEnabled": false
Redaction is best-effort, not a guarantee
Redaction catches known shapes: the .env convention by name, and a handful
of recognisable credential formats by their fixed prefixes. It does not
understand secrets in general. A credential in a format not listed above, a
secret with no recognisable prefix, one split across a value in a way that
breaks the pattern, or one disguised deliberately, passes through unredacted.
Treat Redaction as a safety net that catches the common, recognisable cases — not as a substitute for reviewing a selection yourself before pasting it somewhere, and not as a reason to put a real secret in a file you intend to export. A safety net presented as a guarantee is worse than no safety net at all, because it invites you to stop checking.
Default Binary Extensions
The extension includes these default binary extensions:
- Images: png, jpg, jpeg, gif, bmp, webp, tif, tiff, ico, avif, heic, heif
- Videos: mp4, mov, avi, mkv, webm, mpeg, mpg, 3gp, ogv
- Documents: pdf, doc, docx, xls, xlsx, ppt, pptx
- Archives: zip, rar, 7z, gz, tar
- Executables: exe, dll, so, dylib
Output Format
The generated markdown file includes:
- File tree: the shape of the export, drawn from exactly the entries it contains — stubs included, marked with the reason their content is absent
- File sections: Each file with proper syntax highlighting
- Stubs: Files mentioned at their path with their content omitted and the reason stated
- Redactions: A likely secret inside an embedded file,
.envvalues included, replaced inline by a marker that names what was removed — see Redaction Settings
The language hint on each block is chosen by file name first and extension
second, so Dockerfile, Makefile, Gemfile and .gitignore are recognised
even though they have no extension. An extension the map does not know produces
no hint rather than a wrong one.
Example Output
# Project Code Export
## File tree
```
.
├── Dockerfile
├── assets/
│ └── logo.png (omitted: binary)
└── src/
└── index.ts
```
---
## Dockerfile
```dockerfile
FROM node:20
```
---
## src/index.ts
```typescript
export const answer = 42;
```
---
## assets/logo.png
> **Content omitted** — this file is binary.
---
Changelog
v2.0.0
- Complete rewrite of the export core as an asynchronous, streaming pipeline — large selections no longer freeze the editor or risk exhausting memory, and an export in progress can be cancelled
- New Copy as Markdown command puts the export straight on the clipboard; Export to Markdown keeps writing a timestamped file
- Every export opens with a file tree of exactly what it contains, replacing the old index whose links didn't work
- Token count reported per file and in total, with a configurable warning when an export is too big for a model's context window
- Files that shouldn't be embedded — binary, too large, unreadable — become labelled Stubs instead of being silently dropped or embedded as garbage
- A markdown file's own code fences can no longer corrupt the export that contains it
- Secret Redaction:
.envvalues and common credential shapes (API keys, tokens, database passwords) are masked before they reach the export, with a count reported and an off switch - Exclusion rules rewritten: nested
.gitignorefiles are honoured, a repository.exportignoresupports real glob patterns, and a file you pick explicitly is always exported regardless of what would otherwise exclude it .git/is never walked, and an export never includes an earlier export of its own- Packaged with esbuild, so installing the extension no longer pulls in its whole dependency tree
v1.0.9
- Changed readme
v1.0.8
- Timestamp bug fix in file generation
- Icon and banner for extension page
v1.0.7
- Mandatory timestamp appended to every export file name (cannot be disabled)
- Dynamic ignore of the exact timestamped output file prevents self-inclusion
v1.0.6
- Cleanup of duplicate scaffold and compiled JS sources
v1.0.5
- Minor internal improvements
v1.0.1
- Initial introduction of timestamp concept (now enforced by later versions)
v1.0.0
- Initial release with core functionality
- Multi-selection support
- Configurable ignore system with strict priority order
- Binary file handling with comprehensive defaults
- Clean architecture implementation
- Proper .gitignore parsing using ignore npm package
- Fixed all critical bugs from previous versions