by jayminwest
Growing Expertise for Coding Agents — structured expertise files that accumulate over time, live in git, work with any agent
# Add to your Claude Code skills
git clone https://github.com/jayminwest/mulchLast scanned: 5/30/2026
{
"issues": [],
"status": "PASSED",
"scannedAt": "2026-05-30T15:06:46.330Z",
"npmAuditRan": true,
"pipAuditRan": true
}No comments yet. Be the first to share your thoughts!
30 days in the Featured rail · terms & refunds
Structured expertise management for AI agent workflows.
Agents start every session from zero. The pattern your agent discovered yesterday is forgotten today. Mulch fixes this: agents call ml record to write learnings, and ml query to read them. Expertise compounds across sessions, domains, and teammates.
Mulch is a passive layer. It does not contain an LLM. Agents use Mulch — Mulch does not use agents.
bun install -g @os-eco/mulch-cli
Or try without installing:
npx @os-eco/mulch-cli --help
git clone https://github.com/jayminwest/mulch
cd mulch
bun install
bun link # Makes 'ml' available globally
bun test # Run all tests
bun run lint # Biome check
bun run typecheck # tsc --noEmit
ml init # Create .mulch/ in your project
ml add database # Add a domain
ml record database --type convention "Use WAL mode for SQLite"
ml record database --type failure \
--description "VACUUM inside a transaction causes silent corruption" \
--resolution "Always run VACUUM outside transaction boundaries"
ml query database # See accumulated expertise
ml prime # Get full context for agent injection
ml prime database # Get context for one domain only
ml prime --files src/foo.ts # Prime only records relevant to specific files
ml prime --manifest # Domain index for monoliths (scope-load on demand)
ml prime --full --all # Skip auto-context-scope and emit every record
For large monoliths where dumping every record wastes context, set prime.default_mode: manifest in .mulch/mulch.config.yaml — ml prime then emits a quick reference + domain index, and agents scope-load with ml prime <domain> or ml prime --files <path>.
In full mode, ml prime auto-context-scopes to the agent's working set by default: git status for changed/untracked files, plus the active-work resolver chain (current branch, in-progress seeds, current GH PR, branch-parsed linear/bead IDs) matched against each record's evidence.{seeds,gh,linear,bead}. Universal records (no files / dir_anchors / tracker-anchored evidence) are always emitted. The stderr line prime: scoped to N of M records based on …; run with --all for the full corpus reports the scoping ratio so the agent sees what got dropped. Pass --all to opt out and emit the full corpus; pass an explicit --files, positional domain, --domain, or --context to scope on different signals. Auto-scope is skipped under --json (machine consumers expect deterministic output) and outside a git repo.
Every command supports --json for structured output. Global flags: -v/--version, -q/--quiet, --verbose, --timing. ANSI colors respect NO_COLOR.
| Command | Description |
|---|---|
ml init |
Initialize .mulch/ in the current project |
ml add <domain> |
Add a new expertise domain |
ml record <domain> --type <type> |
Record an expertise record (--tags, --force, --relates-to, --supersedes, --batch, --stdin, --dry-run, --evidence-bead) |
ml edit <domain> <id> |
Edit an existing record by ID or 1-based index |
ml delete <domain> [id] |
Delete records by ID, --records <ids>, or --all-except <ids> (--dry-run) |
ml delete-domain <domain> |
Remove a domain from config and delete its expertise JSONL file (--yes, --dry-run) |
ml move <domain> <id> <target> |
Transfer a record to another domain, preserving ID and cross-references (--force, --dry-run) |
ml query [domain] |
Query expertise (--all, --classification, --file, --outcome-status, --sort-by-score, --format filters) |
ml prime [domains...] |
Output AI-optimized expertise context (--manifest, --full, --all, --budget, --no-limit, --context, --files, --exclude-domain, --export, --dry-run) |
ml search [query] |
Search records across domains with BM25 ranking (--domain, --type, --tag, --classification, --file, --sort-by-score, --no-boost, --format) |
ml rank [domain] |
Rank records by confirmation-frequency score, highest first (--type, --limit, --min-score, --json) — pure score ranking with no text query, useful for context-constrained consumers |
ml compact [domain] |
Analyze compaction candidates or apply a compaction (--analyze, --auto, --apply, --dry-run, --min-group, --max-records) |
ml diff [ref] |
Show expertise changes between git refs (ml diff HEAD~3, ml diff main..feature) |
ml config <subcommand> |
Inspect and edit .mulch/mulch.config.yaml (schema, show [--path <p>], set <path> <value>, unset <path>) — atomic, schema-validated writes for warren and other config-UI consumers |
ml status |
Show expertise freshness and counts (--json for health metrics; flags rotting domains where the newest record exceeds the observational shelf life) |
ml audit |
Audit corpus health — floater rate, per-tracker evidence coverage (seeds/gh/linear/bead), convention rule-density, per-domain mix, tracker-citation status (--ci, --suggest, --domain, --ignore-domains) |
ml validate |
Schema validation across all files |
ml doctor |
Run health checks on expertise records (--fix to auto-fix) |
ml setup [provider] |
Install provider-specific hooks (built-ins: claude, cursor, codex — or any name discovered via .mulch/recipes/ or mulch-recipe-*; --list shows everything) |
ml onboard |
Generate AGENTS.md/CLAUDE.md snippet |
ml prune |
Soft-archive stale tactical/observational records to .mulch/archive/, plus tier-demote records superseded by another live record (--hard for true delete, --aggressive to collapse superseded records straight to archive, --dry-run) |
ml archive <domain> [id] |
Soft-archive a specific record without waiting for ml prune (--records for bulk, --reason required, --dry-run) — symmetric to ml restore |
ml restore <id> |
Restore a soft-archived record back to live expertise |
ml ready |
Show recently added or updated records (--since, --domain, --limit) |
ml sync |
Validate, stage, and commit .mulch/ changes |
ml outcome <domain> <id> |
Append an outcome to a record (--status, --duration, --agent, --notes), or view outcomes |
ml upgrade |
Upgrade mulch to the latest version (--check for dry run) |
ml learn |
Show changed files and suggest domains for recording learnings |
ml completions <shell> |
Output shell completion script (bash, zsh, fish) |
All record-rendering commands (ml prime, ml query, ml search) accept a global --format <markdown|compact|xml|plain> flag that selects the output formatter. xml is Claude-optimized; plain is the spawn-injection contract — clean structured prose (per-domain sections, bulleted records, no decorative title, no Session Close trailer) suitable for concatenation into another tool's system prompt; compact emits one-liner records (default for ml prime); markdown emits the full, sectioned layout. Per-command --format flags (e.g. ml query --format ids) take precedence over the global flag.
ml --format xml prime testing # XML expertise tree (Claude-friendly)
ml --format plain prime testing # plain text for system-prompt injection
ml --format compact query testing # compact one-liners
ml prime --full # alias for --format markdown
ml prime --compact # alias for --format compact
--dry-run)ml prime --dry-run emits a JSON summary of which records would be primed (id, type, domain, per-record token estimate) and how the result fits within --budget, without rendering record content. Useful for editor previews and orchestrators that want to show "would prime: N records, K tokens" before actually shelling out for the full output. Composes with --domain, --files, --budget, --no-limit, --exclude-domain. pre-prime hooks are skipped (preview must not trigger Slack posts or digest-then-confirm confirmations). When combined with --format plain the format is ignored and JSON is returned.
ml prime --dry-run # preview default prime
ml prime --dry-run --domain cli --budget 8000 # scoped preview against a specific budget
ml prime --dry-run --files src/foo.ts # what would prime --files emit?
{
"wouldPrime": [
{ "id": "mx-94901b", "type": "convention", "domain": "cli", "tokens": 240 }
],
"totalTokens": 240,
"budgetUsed": 0.03,
"budgetTotal": 8000
}
budgetUsed and budgetTotal are null when invoked with --no-limit.
Mulch stores expertise as typed JSONL records in .mulch/expertise/<domain>.jsonl — one file per domain, one record per line. Six record types (convention, pattern, failure, decision, reference, guide) with three classification tiers (foundational, tactical, observational) govern shelf life and pruning. Advisory file locks and atomic writes ensure safe concurrent access from multiple agents. Schema validation (via Ajv) enforces type-specific required fields. See CLAUDE.md for full technical details.
1. ml init → Creates .mulch/ with domain JSONL files
2. Agent reads expertise