README
ΒΆ
β‘ SigMap
Zero-dependency AI context engine β 97% token reduction
Every coding agent session starts with full codebase context at under 4K tokens.
No npm install. No setup. Runs on any machine with Node.js 18+.
Table of contents
| What it does | Token reduction table, pipeline overview |
| Quick start | Get running in 60 seconds |
| VS Code extension | Status bar, stale alerts, commands |
| Languages supported | 21 languages |
| Context strategies | full / per-module / hot-cold |
| MCP server | 7 on-demand tools |
| CLI reference | All flags |
| Configuration | Config file + .contextignore |
| Observability | Health score, reports, CI |
| Testing | Run the test suite |
| Project structure | File-by-file map |
| Principles | Design decisions |
π New to SigMap? Read the Complete Getting Started Guide β token savings walkthrough, every command, VS Code plugin, and CI setup.
π What it does
SigMap scans your source files and extracts only the function and class signatures β no bodies, no imports, no comments β then writes a compact context file that Copilot, Claude, Cursor, and Windsurf read automatically. Every session starts with full codebase awareness at a fraction of the token cost.
Your codebase
β
βΌ
gen-context.js βββΊ extracts signatures from 21 languages
β
βΌ
.github/copilot-instructions.md βββ auto-read by Copilot / Claude / Cursor
β
βΌ
AI agent session starts with full context
Token reduction at every stage
| Stage | Tokens | Reduction |
|---|---|---|
| Raw source files | ~80,000 | β |
| Repomix compressed | ~8,000 | 90% |
| SigMap signatures | ~4,000 | 95% |
SigMap + MCP (hot-cold) |
~200 | 99.75% |
97% fewer tokens. The same codebase understanding.
π Quick start
No install required β just Node.js 18+.
# 1. Copy gen-context.js into your project root
curl -O https://raw.githubusercontent.com/manojmallick/sigmap/main/gen-context.js
# 2. Generate your context file
node gen-context.js
# 3. Output: .github/copilot-instructions.md
# That file is auto-read by GitHub Copilot in VS Code
Or via npm (globally):
npx sigmap # run once without installing
npm install -g sigmap # install globally
sigmap # then use anywhere
Common workflows
node gen-context.js # generate once and exit
node gen-context.js --watch # regenerate on every file save
node gen-context.js --setup # generate + install git hook + start watcher
node gen-context.js --diff # context for git-changed files only (PR mode)
node gen-context.js --diff --staged # staged files only (pre-commit check)
node gen-context.js --health # show context health score (grade AβD)
node gen-context.js --mcp # start MCP server on stdio
Companion tool: Repomix
SigMap and Repomix are complementary, not competing:
| Tool | When to use |
|---|---|
| SigMap | Always-on, git hooks, daily signature index (~4K tokens) |
| Repomix | On-demand deep sessions, full file content, broader language support |
node gen-context.js --setup # always-on context
npx repomix --compress # deep dive sessions
"SigMap for daily always-on context; Repomix for deep one-off sessions β use both."
π§© VS Code extension
Introduced in v1.5 β zero runtime npm dependencies.
The vscode-extension/ directory contains a first-party VS Code extension that keeps you informed without any manual commands.
| Feature | Detail |
|---|---|
| Status bar item | Shows health grade (A/B/C/D) + time since last regen; refreshes every 60 s |
| Stale notification | Warns when copilot-instructions.md is > 24 h old; one-click regeneration |
| Regenerate command | SigMap: Regenerate Context β runs node gen-context.js in the integrated terminal |
| Open context command | SigMap: Open Context File β opens .github/copilot-instructions.md |
| Script path setting | contextforge.scriptPath β override when gen-context.js is not at the project root |
Activate on startup (onStartupFinished) β loads within 3 s, never blocks editor startup.
π Languages supported
21 languages. All implemented with zero external dependencies β pure regex + Node built-ins.
Show all 21 languages
| Language | Extensions | Extracts |
|---|---|---|
| TypeScript | .ts .tsx |
interfaces, classes, functions, types, enums |
| JavaScript | .js .jsx .mjs .cjs |
classes, functions, exports |
| Python | .py .pyw |
classes, methods, functions |
| Java | .java |
classes, interfaces, methods |
| Kotlin | .kt .kts |
classes, data classes, functions |
| Go | .go |
structs, interfaces, functions |
| Rust | .rs |
structs, impls, traits, functions |
| C# | .cs |
classes, interfaces, methods |
| C/C++ | .cpp .c .h .hpp .cc |
classes, functions, templates |
| Ruby | .rb .rake |
classes, modules, methods |
| PHP | .php |
classes, interfaces, functions |
| Swift | .swift |
classes, structs, protocols, functions |
| Dart | .dart |
classes, mixins, functions |
| Scala | .scala .sc |
objects, classes, traits, functions |
| Vue | .vue |
<script> functions and components |
| Svelte | .svelte |
<script> functions and exports |
| HTML | .html .htm |
custom elements and script functions |
| CSS/SCSS | .css .scss .sass .less |
custom properties and keyframes |
| YAML | .yml .yaml |
top-level keys and pipeline jobs |
| Shell | .sh .bash .zsh .fish |
function declarations |
| Dockerfile | Dockerfile Dockerfile.* |
stages and key instructions |
π Context strategies
Introduced in v1.1. Reduce always-injected tokens by 70β90%.
Set "strategy" in gen-context.config.json:
| Strategy | Always-injected | Context lost? | Needs MCP? | Best for |
|---|---|---|---|---|
full |
~4,000 tokens | No | No | Starting out, cross-module work |
per-module |
~100β300 tokens | No | No | Large codebases, module-focused sessions |
hot-cold |
~200β800 tokens | Cold files only | Yes | Claude Code / Cursor with MCP enabled |
full β default, works everywhere
{ "strategy": "full" }
One file, all signatures, always injected on every question.
per-module β 70% fewer injected tokens, zero context loss
{ "strategy": "per-module" }
One .github/context-<module>.md per top-level source directory, plus a tiny overview table. Load the relevant module file for focused sessions. No MCP required.
.github/copilot-instructions.md β overview table, ~117 tokens (always-on)
.github/context-server.md β server/ signatures, ~2,140 tokens
.github/context-web.md β web/ signatures, ~335 tokens
.github/context-desktop.md β desktop/ signatures, ~1,583 tokens
hot-cold β 90% fewer injected tokens, requires MCP
{ "strategy": "hot-cold", "hotCommits": 10 }
Recently committed files are hot (auto-injected). Everything else is cold (on-demand via MCP). Best reduction available β ~200 tokens always-on.
π Full guide: docs/CONTEXT_STRATEGIES.md β decision tree, scenario comparisons, migration steps.
π MCP server
Introduced in v0.3, expanded to 7 tools through v1.4.
Start the MCP server on stdio:
node gen-context.js --mcp
Available tools
| Tool | Input | Output |
|---|---|---|
read_context |
{ module?: string } |
Signatures for one module or entire codebase |
search_signatures |
{ query: string } |
Matching signatures with file paths |
get_map |
{ type: "imports"|"classes"|"routes" } |
Structural section from PROJECT_MAP.md |
explain_file |
{ path: string } |
Signatures + imports + reverse callers for one file |
list_modules |
β | Token-count table of all top-level module directories |
create_checkpoint |
{ summary: string } |
Write a session checkpoint to .context/ |
get_routing |
β | Full model routing table |
Reads files on every call β no stale state, no restart needed.
π Setup guide: docs/MCP_SETUP.md
βοΈ CLI reference
All flags live in v1.5. See CHANGELOG.md for when each shipped.
node gen-context.js Generate once and exit
node gen-context.js --watch Generate and watch for file changes
node gen-context.js --setup Generate + install git hook + start watcher
node gen-context.js --diff Generate context for git-changed files only
node gen-context.js --diff --staged Staged files only (pre-commit check)
node gen-context.js --mcp Start MCP server on stdio
node gen-context.js --report Token reduction stats
node gen-context.js --report --json Structured JSON report (exits 1 if over budget)
node gen-context.js --report --history Usage log summary
node gen-context.js --report --history --json Usage history as JSON
node gen-context.js --health Composite health score (0β100, grade AβD)
node gen-context.js --health --json Machine-readable health JSON
node gen-context.js --suggest-tool "<task>" Recommend model tier for a task
node gen-context.js --suggest-tool "<task>" --json Machine-readable tier recommendation
node gen-context.js --monorepo Per-package context for monorepos
node gen-context.js --routing Include model routing hints in output
node gen-context.js --format cache Write Anthropic prompt-cache JSON
node gen-context.js --track Append run metrics to .context/usage.ndjson
node gen-context.js --init Write config + .contextignore scaffold
node gen-context.js --version Version string
node gen-context.js --help Usage information
Task classification β --suggest-tool
node gen-context.js --suggest-tool "security audit of the auth module"
# tier : powerful
# models : claude-opus-4-6, gpt-5-4, gemini-2-5-pro
node gen-context.js --suggest-tool "fix a typo in the yaml config" --json
# {"tier":"fast","label":"Fast (low-cost)","models":"claude-haiku-4-5, ...","costHint":"~$0.0008 / 1K tokens"}
Tiers: fast (config/markup/typos) Β· balanced (features/tests/debug) Β· powerful (architecture/security/multi-file)
π Security scanning
SigMap automatically redacts secrets from all extracted signatures. Ten patterns are checked on every file:
| Pattern | Example match |
|---|---|
| AWS Access Key | AKIA... |
| AWS Secret Key | 40-char base64 |
| GCP API Key | AIza... |
| GitHub Token | ghp_... gho_... |
| JWT | eyJ... |
| DB Connection String | postgres://user:pass@... |
| SSH Private Key | -----BEGIN ... PRIVATE KEY----- |
| Stripe Key | sk_live_... sk_test_... |
| Twilio Key | SK[32 hex chars] |
| Generic secret | password = "...", api_key: "..." |
If a match is found, the signature is replaced with [REDACTED β {pattern} detected in {file}]. The run continues β no silent failures.
βοΈ Configuration
Copy gen-context.config.json.example to gen-context.config.json:
{
"srcDirs": ["src", "app", "lib"],
"maxTokens": 6000,
"outputs": ["copilot"],
"secretScan": true,
"strategy": "full",
"watchDebounce": 300,
"tracking": false
}
Exclusions go in .contextignore (gitignore syntax). Also reads .repomixignore if present.
# .contextignore
node_modules/
dist/
build/
*.generated.*
test/fixtures/
Run node gen-context.js --init to scaffold both files in one step.
Output targets
| Key | Output file | Read by |
|---|---|---|
"copilot" |
.github/copilot-instructions.md |
GitHub Copilot |
"claude" |
CLAUDE.md (appends below marker) |
Claude Code |
"cursor" |
.cursorrules |
Cursor |
"windsurf" |
.windsurfrules |
Windsurf |
π Observability
# Append run metrics to .context/usage.ndjson
node gen-context.js --track
# Structured JSON report for CI (exits 1 if over budget)
node gen-context.js --report --json
# { "version": "1.5.0", "finalTokens": 3200, "reductionPct": 92.4, "overBudget": false }
# Composite health score
node gen-context.js --health
# score: 95/100 (grade A) | reduction: 91.2% | 1 day since regen | 47 runs
Self-healing CI
Copy examples/self-healing-github-action.yml to .github/workflows/ to auto-regenerate context when:
- Context file is more than 7 days old (always active)
- Copilot acceptance rate drops below 30% (requires
COPILOT_API_TOKENβ GitHub Enterprise)
- name: SigMap health check
run: node gen-context.js --health --json
- name: Regenerate context
run: node gen-context.js
π Full guide: docs/ENTERPRISE_SETUP.md
Prompt caching β 60% API cost reduction
node gen-context.js --format cache
# Writes: .github/copilot-instructions.cache.json
# Format: { type: 'text', text: '...', cache_control: { type: 'ephemeral' } }
π Full guide: docs/REPOMIX_CACHE.md
π§ͺ Testing
# All 21 language extractors
node test/run.js
# Single language
node test/run.js typescript
# Regenerate expected outputs after extractor changes
node test/run.js --update
# Full integration suite (253 tests across 16 test files)
for f in test/integration/*.test.js; do node "$f"; done
Validation gates
# Gate 1 β all tests pass
node test/run.js
# Expected: 21/21 PASS
# Gate 2 β zero external dependencies
grep "require(" gen-context.js | grep -v "^.*//.*require"
# Expected: only fs, path, assert, os, crypto, child_process, readline
# Gate 3 β MCP server responds correctly
echo '{"jsonrpc":"2.0","method":"tools/list","id":1}' | node gen-context.js --mcp
# Expected: valid JSON with 7 tools
# Gate 4 β npm artifact is clean
npm pack --dry-run
# Expected: no test/, docs/, vscode-extension/ in output
π Project structure
sigmap/
β
βββ gen-context.js β PRIMARY ENTRY POINT β single file, zero deps
βββ gen-project-map.js β import graph, class hierarchy, route table
β
βββ src/
β βββ extractors/ β 21 language extractors (one file per language)
β βββ mcp/ β MCP stdio server β 7 tools
β βββ security/ β secret scanner β 10 patterns
β βββ routing/ β model routing hints
β βββ tracking/ β NDJSON usage logger
β βββ health/ β composite health scorer
β βββ format/ β Anthropic prompt-cache formatter
β βββ config/ β config loader + defaults
β
βββ vscode-extension/ β VS Code extension (v1.5)
β βββ package.json β manifest β commands, settings, activation
β βββ src/extension.js β status bar, stale notification, commands
β
βββ test/
β βββ fixtures/ β one source file per language
β βββ expected/ β expected extractor output
β βββ run.js β zero-dep test runner
β βββ integration/ β 16 integration test files (253 tests)
β
βββ docs/ β documentation site (GitHub Pages)
β βββ index.html β homepage
β βββ quick-start.html
β βββ strategies.html
β βββ languages.html
β βββ roadmap.html
β βββ repomix.html
β
βββ scripts/
β βββ ci-update.sh β CI pipeline helper
β βββ inject-search.py β one-time: add search to docs HTML pages
β
βββ examples/
β βββ self-healing-github-action.yml
β βββ gen-context.config.json β full annotated config
β
βββ .npmignore β excludes docs/, test/, vscode-extension/ from publish
βββ .contextignore.example β exclusion template
βββ gen-context.config.json.example β annotated config reference
π Principles
| Principle | Implementation |
|---|---|
| Zero npm dependencies | node gen-context.js on a blank machine with Node 18+ β nothing else required |
| Never throw | All extractors return [] on any error β the run always completes |
| Deterministic | No AI or LLM involved in extraction β only regex + Node built-ins |
| Repomix is a companion | Use both tools; SigMap never replaces Repomix |
| No telemetry | Never phones home; all state is files in your repo |
| Local-first | No cloud service, no database, no accounts |
π¦ Publishing to npm
Releases are published automatically via GitHub Actions whenever a version tag is pushed.
One-time setup
-
Create an npm account at npmjs.com (if you haven't already).
-
Generate an npm access token:
- npmjs.com β Account β Access Tokens β Generate New Token β Granular Access Token (or Classic Automation token)
- Scope:
sigmappackage, permission: Read and Write
-
Add the secret to GitHub:
GitHub repo β Settings β Secrets and variables β Actions β New repository secret Name: NPM_TOKEN Value: <paste token>
Releasing a new version
# 1. Bump version in package.json
npm version patch # or minor / major
# 2. Push the commit AND the new tag
git push && git push --tags
The npm-publish workflow will:
- Run the full test suite
- Verify
package.jsonversion matches the pushed tag - Publish to npm with provenance attestation
- Create a GitHub Release with auto-generated notes
Backfilling historical versions
Tags that existed before the workflow was set up can be published retroactively:
# Dry run first β see what would be published
./scripts/backfill-npm.sh
# Actually publish all historical tags
export NPM_TOKEN=npm_xxxxxxxxxxxx
./scripts/backfill-npm.sh --publish
# Start from a specific tag
./scripts/backfill-npm.sh --publish --from v0.5.0
The script assigns dist-tag: legacy to all versions except v1.5.0 (which gets latest), so npm install sigmap always resolves to the current release.
π€ Contributing
See CONTRIBUTING.md for how to add a language extractor or new feature.
Every extractor follows the same contract:
module.exports = { extract };
function extract(src) { // src: string β string[]
if (!src || typeof src !== 'string') return [];
// ... regex extraction only β no external dependencies ...
return sigs.slice(0, 25); // never more than 25 signatures per file
}
π License
MIT Β© 2026 Manoj Mallick