Getting Started
Install once. Never think about it again.
Install
Run the installer from any terminal. It registers CodeCondense as a Claude Code plugin globally — all projects on this machine benefit immediately.
npx @codecondense/install
Alternatively, install via the Claude Code plugin system directly:
claude plugin add LCBO/codecondense_claude_plugin
Verify
Open a Claude Code session in any directory and run the status command:
/slim-status
You'll see your plan, version, trial usage, and which tools are active. If you see Slim active: true you're good.
Start coding
That's it. CodeCondense transparently intercepts Claude's tool calls and replaces them with optimised equivalents. You don't change prompts, workflows, or habits — costs just drop.
/slim-savings
Link your account (optional)
Generate an API key in your dashboard, then run:
/slim-login cc_your_key_here
Linking lifts free-plan call limits and enables cross-machine savings tracking in your dashboard.
How It Works
A transparent optimization layer inside Claude Code.
CodeCondense registers as an MCP (Model Context Protocol) server that Claude Code calls automatically. It exposes replacement tools under the mcp__slim__ namespace. When Claude would normally call Read five times, the plugin intercepts that pattern and issues a single mcp__slim__Investigate instead.
The replacement layer
Each CodeCondense tool is a drop-in replacement for one or more native Claude Code tools, but batches work that would otherwise require multiple round-trips:
| Native pattern | Slim replacement | Saving |
|---|---|---|
Read × N files | Search (file_paths_with_content) | 70–90% tokens |
Grep → Read → Find symbol | Investigate | 4–8× fewer calls |
Write × N files | Edit (edits[]) | N−1 round-trips |
Read → diff → Read again | Read (if_modified_since) | 80–95% re-read tokens |
What runs where
Everything runs on your machine inside the Claude Code process. No code is uploaded. No prompts are intercepted. The only outbound traffic is anonymous aggregate counters (tokens saved, calls eliminated) sent to CodeCondense servers — and even those can be disabled with telemetry: false.
Token savings explained
Claude Code sends the entire conversation context (all prior messages + tool results) with every tool call. When vanilla Claude makes 8 sequential tool calls to explore a codebase, it re-sends that growing context 8 times. A single Slim call sends it once. The token saving compounds: more calls = more re-sends = more wasted tokens. That's why savings percentages are often 70–90% even for small tasks.
Investigate
Symbol definition + usages + file map in one round-trip.
Investigate collapses the grep → read → find-definition loop into a single call. It queries three indexes simultaneously and returns a unified result:
- symbols — AST-indexed definitions: where the symbol is declared, file:line, and its type (function, class, method, interface…)
- matches — ripgrep usages: every location where the symbol is referenced across the codebase
- files — top files ranked by match density, each with a full AST symbol map (all definitions inside that file)
When to use it
Start every code exploration with Investigate instead of a Search→Read chain. Use Read or Search only for the specific file you've already identified.
// Find where "handleAuth" is defined and all callers
mcp__slim__Investigate({ query: "handleAuth" })
// Scope to a subtree
mcp__slim__Investigate({ query: "parseToken", path: "src/auth" })
// Scope to specific file types
mcp__slim__Investigate({ query: "Router", file_glob_patterns: ["**/*.ts"] })Parameters
| Parameter | Type | Description |
|---|---|---|
query | string | Symbol name, term, or regex to look up |
path | string? | Restrict search to this directory path |
file_glob_patterns | string[]? | Glob patterns to limit which files are searched |
max_files | number? | Max files to return (default 8) |
max_matches | number? | Max ripgrep matches (default 40) |
Smart Search
BM25 file discovery + grep + read in one call.
Smart Search combines file discovery, content grep, and file reading into a single call with configurable output modes. It replaces the common pattern of: find files → grep → read each file.
Output modes
| Mode | Returns | Best for |
|---|---|---|
matches (default) | Matched lines + context | Surgical greps — you know what you want |
file_paths_only | List of matching file paths | Finding files before reading |
file_paths_with_match_count | Paths ranked by BM25 relevance | Finding the most relevant files |
file_paths_with_content | Full file content per match | Reading 2+ files at once — replaces a Read chain |
// Read multiple files in one call (best pattern for exploration)
mcp__slim__Search({
file_glob_patterns: ["src/components/**/*.tsx"],
output_mode: "file_paths_with_content"
})
// Surgical grep with context
mcp__slim__Search({
content_regex: "useEffect",
file_glob_patterns: ["src/**/*.ts"],
context_lines: 4
})
// AST summary of TypeScript files (no regex needed)
mcp__slim__Search({
file_glob_patterns: ["src/lib/*.ts"],
summary: true
})Delta mode (re-reads)
When you need to re-read a file you've already read in this session, pass if_modified_since with the timestamp from the previous result. If the file hasn't changed, nothing is returned. If it has, only the diff is returned. This cuts re-read token cost by 80–95%.
// First read — save the timestamp from the result
const result = await mcp__slim__Search({ file: "src/auth.ts" });
const ts = result.timestamp;
// Later re-read — returns only changed lines
mcp__slim__Search({ file: "src/auth.ts", if_modified_since: ts })Parameters
| Parameter | Type | Description |
|---|---|---|
content_regex | string? | Grep pattern (regex). Omit to match all files |
file_glob_patterns | string[]? | Glob patterns to restrict which files are searched |
output_mode | string? | One of: matches, file_paths_only, file_paths_with_match_count, file_paths_with_content |
context_lines | number? | Lines of context around each match (default 2) |
summary | boolean? | Return TS/JS AST symbol map instead of raw content |
multiline | boolean? | Enable cross-line regex matching |
case_sensitive | boolean? | Default false |
max_results | number? | Cap on matches returned (default 100) |
if_modified_since | string? | Timestamp — enables delta mode for re-reads |
Batch Edit
All file edits in one atomic round-trip.
Batch Edit writes every change in a single call. Instead of Claude making N sequential Write calls (each re-sending the full conversation context), one Edit call carries all edits at once. A pre-write backup is created for every file touched.
Edit modes
| Mode | How to trigger | Description |
|---|---|---|
Search/replace | Provide old_string | Replace exact text match in file. Fails if old_string not unique — add more context to disambiguate |
Overwrite | overwrite: true | Replace entire file content with new_string |
Create | Omit old_string and overwrite | Creates the file if it does not exist |
Replace all | replace_all: true | Replace every occurrence of old_string (useful for renaming a variable across a file) |
Line-scope | file#100-200 syntax | Restrict the edit to a specific line range |
Jupyter cell | file#cell=N + cell_action | Edit, insert, delete, or move notebook cells |
// Create 3 files in one call
mcp__slim__Edit({
edits: [
{ file: "src/auth.ts", new_string: "export function login() { ... }" },
{ file: "src/db.ts", new_string: "export const pool = ..." },
{ file: "src/index.ts", new_string: "import './auth'; import './db';" },
]
})
// Search/replace in multiple files at once
mcp__slim__Edit({
edits: [
{ file: "src/api.ts", old_string: "const BASE = 'http'", new_string: "const BASE = 'https'" },
{ file: "src/config.ts", old_string: "port: 80", new_string: "port: 443" },
]
})Parameters (per edit)
| Field | Type | Description |
|---|---|---|
file | string | Absolute or relative file path to edit |
new_string | string | The replacement content (or full file content for overwrite/create) |
old_string | string? | Text to find and replace. Omit to create or overwrite |
overwrite | boolean? | If true, replaces entire file content |
replace_all | boolean? | Replace every occurrence of old_string |
cell_action | string? | Jupyter: insert_after, insert_before, delete, move_after, move_before |
Session Memory
Persistent, decay-scored knowledge that survives across sessions.
Session Memory gives Claude a long-term memory store. Information indexed in one session can be recalled in future sessions without re-reading files or re-explaining context. Entries decay over time so stale facts fade naturally — recent memories score higher.
How decay works
Every memory entry has a relevance score. Each day that passes, the score is multiplied by the decay rate (default: 0.95). A memory written today scores 1.0. After a week it scores 0.698. After a month, 0.215. This means actively used memories stay prominent while forgotten details fade — no manual cleanup needed.
score_today = original_score × (decay_rate ^ days_since_written) // With default decay_rate = 0.95: // Day 0: 1.000 // Day 7: 0.698 // Day 30: 0.215 // Day 90: 0.010 (effectively gone)
Memory types
| Type | Description | Example |
|---|---|---|
user | Facts about who you are — role, expertise, preferences | Senior Go dev, new to React frontend |
feedback | How Claude should behave in this project | Never mock the database in tests |
project | Ongoing work, deadlines, decisions | Auth rewrite driven by legal compliance, due June |
reference | Where to find things in external systems | Pipeline bugs tracked in Linear project "INGEST" |
convention | Code style rules, naming conventions | All API routes return { data, error } shape |
Operations
// Save a memory
mcp__slim__Memory({ op: "index", name: "db-testing-rule",
type: "feedback",
body: "Never mock the DB. Integration tests must hit a real Postgres instance.",
source: "2026-06-11 discussion" })
// Search memories semantically
mcp__slim__Memory({ op: "search", query: "database testing approach" })
// Get a specific memory by ID
mcp__slim__Memory({ op: "get", id: 42 })
// List all memories (by score, highest first)
mcp__slim__Memory({ op: "list", limit: 20 })
// Delete a memory
mcp__slim__Memory({ op: "forget", id: 42 })
// Stats: total entries, average score, decay rate
mcp__slim__Memory({ op: "stats" })What to store vs. what not to store
Store: decisions and their reasons, preferences and constraints, team conventions, external system locations, recurring patterns in the user's workflow.
Don't store: code content or architecture (read the files instead), git history (use git log), anything in CLAUDE.md files, ephemeral task state from the current session.
Model Router
Route simple tasks to cheap models, complex ones to powerful models.
The Model Router is a local proxy (port 4891) that sits between Claude Code and Anthropic's API. It inspects each request and routes it to the most cost-effective model that can handle it.
Routing logic
The router classifies each request into one of three tiers:
| Tier | Model | Used for |
|---|---|---|
Simple | Claude Haiku | Short completions, formatting, single-file reads, yes/no questions |
Standard | Claude Sonnet | Multi-file edits, medium reasoning, most coding tasks |
Complex | Claude Opus | Architecture decisions, complex debugging, large multi-step refactors |
Classification is based on: prompt length, number of tool calls in context, presence of keywords indicating complexity, and conversation depth. The routing decision is logged and visible via /slim-tail.
Enable the router
/slim-router start
Once started, Claude Code's API requests are proxied through localhost:4891. Set ANTHROPIC_BASE_URL=http://localhost:4891 in your environment or let the plugin configure it automatically.
Cost impact
In typical workloads, ~60% of requests qualify for Haiku (6× cheaper than Sonnet), ~30% for Sonnet, and ~10% for Opus. This yields an average 65–77% cost reduction on top of the token savings from the other tools.
CLI Reference
Slash commands available inside any Claude Code session.
| Command | Description |
|---|---|
/slim-status | Show plugin version, license status, plan, trial usage, and which tools are active |
/slim-stats | Show AST index stats — file count, symbol count, languages indexed, last rebuild time |
/slim-savings | Show token savings, USD savings, and call reduction for this session and all-time |
/slim-tail [N] | Stream the last N telemetry events (tool calls, routing decisions, memory ops). Default: 30 |
/slim-reindex | Force-rebuild the AST symbol index for the current project directory |
/slim-login [KEY] | Save your API key to ~/.slim/config.json and link this machine to your dashboard account |
/slim-router start | Start the local model-routing proxy on port 4891 |
/slim-router stop | Stop the routing proxy |
/slim-router status | Show proxy status, routing stats, and per-model call counts |
/slim-reset | Clear session telemetry counters |
/slim-reset --all | Wipe all local data (telemetry, config, memory store) |
/slim-update | Pull and install the latest plugin version |
Configuration
All settings live in ~/.slim/config.json
Edit the file directly or use the config flags. Changes take effect in the next Claude Code session.
{
"apiKey": "",
"telemetry": true,
"memory": {
"enabled": true,
"decayRate": 0.95
},
"router": {
"enabled": false,
"port": 4891
},
"index": {
"autoRebuild": true,
"excludePatterns": ["node_modules", "dist", ".git", "__pycache__", ".next"]
}
}All options
| Field | Type | Default | Description |
|---|---|---|---|
apiKey | string | "" | Your CodeCondense API key (from the dashboard) |
telemetry | boolean | true | Send anonymous usage counts to CodeCondense servers. Disable for full local-only mode |
memory.enabled | boolean | true | Enable the persistent memory store |
memory.decayRate | number | 0.95 | Per-day score decay factor (0–1). Lower = memories fade faster |
router.enabled | boolean | false | Enable the local model-routing proxy |
router.port | number | 4891 | Port for the routing proxy server |
index.autoRebuild | boolean | true | Automatically rebuild the AST index when files change |
index.excludePatterns | string[] | ["node_modules","dist",".git"] | Directory/file patterns to exclude from the AST index |
FAQ
Does CodeCondense send my code to any server?
No. All processing runs inside your Claude Code process. The only outbound traffic is anonymous aggregate counters (total tokens saved, total calls made) — no code, no prompts, no file names. Set telemetry: false in config to disable even those.
Will it change the quality of Claude's output?
No. CodeCondense changes how Claude gathers information, not what it does with it. The results — edits, answers, completions — are identical. The AST index and batch tools give Claude the same information with fewer round-trips.
How is the AST index built?
When CodeCondense starts in a project, it runs tree-sitter over all non-excluded files and builds an in-memory symbol index. It supports 37 language grammars including TypeScript, JavaScript, Python, Go, Rust, Java, C/C++, Ruby, and more. The index rebuilds automatically when files change (configurable).
Can I use it with a monorepo or multiple projects?
Yes. The AST index is scoped to the directory Claude Code is opened in. Each project gets its own index. The memory store is global across all projects by default — useful for cross-project conventions and user preferences.
What happens to my data if I cancel my plan?
Your local data (AST index, memory store, config) stays on your machine and keeps working. Only the dashboard analytics and account-linked features stop. The plugin itself continues to work on the free plan ($5/month savings cap).
What is the monthly savings cap?
The cap tracks how much Claude API cost the plugin has saved you — not what you pay CodeCondense. Free plan: $5/month saved. Pro plan: $100/month saved. When the cap is reached the plugin pauses until the 1st of the next month. All features are identical on both plans; only the cap differs.
How do I update to the latest version?
Run /slim-update inside any Claude Code session. Or re-run npx @codecondense/install which will pull the latest version.