Monkdev
A coding methodology for LLM agents. Measure. Prove. Cut.
Monkdev is two things. A toolkit, an MCP server that gives your agent token-aware codebase ingestion, symbol search, dependency mapping, and stealth web browsing. And a persona, CLAUDE.md, which keeps the agent simple, honest, and frugal with tokens. The monk serves the architecture, not the ego.
Install
curl -fsSL https://raw.githubusercontent.com/oeo/monkdev/master/scripts/install.sh | bash
This clones to ~/.monkdev, runs bun install, registers the MCP server, and
merges the monk directives into your global agent prompt between markers. It
never touches your own content outside them. Works with Claude Code, OpenCode,
and pi. Run the same line again to upgrade. Needs Bun and git.
The script edits your global agent prompt, so skim
scripts/install.sh first.
Prefer to install by hand, or on another scaffold? Follow
INSTALL.md, or tell your agent:
Fetch https://raw.githubusercontent.com/oeo/monkdev/master/INSTALL.md and follow it.
Optional setup: brave-search needs BRAVE_API_KEY in .env. fetch-url and
screenshot-url need Chrome or Chromium installed (set MONK_CHROME to
override detection). Everything else works out of the box.
Tools
| Tool | What it does |
|---|---|
tree |
Maps the project, ranked by importance, with token estimates. |
context |
Packs directories into XML for deep ingestion. Filter by --min score or --max-tokens budget. |
catfiles |
Reads batches of files with path and LOC headers. |
outline |
Extracts classes and functions, drops the bodies. |
deps |
Maps dependency graphs (Node, Rust, Go, Python). |
symbol |
Finds definitions across languages. |
canon |
Clusters facts restated in more than one language: candidate drift. |
brave-search |
Searches the web via the Brave API. |
fetch-url |
Renders and extracts web pages through stealth Chrome. |
screenshot-url |
Captures a PNG of a rendered page. |
The tools document themselves from the CLI:
./bin/monk list # list all tools
./bin/monk describe <tool> # show a tool's args
./bin/monk tree # map the architecture
Directives
Directives are keywords you type to drive the workflow. All take the #
prefix and compose with | for pipes.
| Directive | What it does |
|---|---|
#meditate [topic|deeply|N] |
Ingest context before acting. Target a topic, go deep, or set an importance threshold. |
#do_research <topic> |
Parallel web searches plus page reads, then synthesize. |
#update_docs |
Align docs with the current code truth. |
#make_skill [scope] |
Preview a durable project skill from current-session work, then write it only after approval. |
#reflect |
Record session wisdom as a git commit. |
#recall [N|topic|all] |
Search past reflection commits. |
#spawn N <desc> |
Run N sub-agents on scoped tasks in parallel. |
#cur / #cur done |
Read or update the cur.md task list. |
#attack [N] |
N sub-agents meditate, then attack your plan before you build. |
#audit <cmd> |
Codebase under oath: gate, debt, smell, split, sec, perf, bugs, mod, arch, drift, all. |
#canon [path] |
Find facts written down in several languages, name the canonical home for each. |
#audit drift [path] |
Find one fact declared at two versions across manifests and config. |
#plan |
Plan mode. Checkbox steps, confidence scores, net LOC per phase. |
#dev |
Detect and start the local dev environment. |
#version |
Report the installed toolkit version. |
#help |
Print all commands as a man page. |
Full ritual semantics live in CLAUDE.md under Explicit Command Directives.
Working Effectively
The tools are cheap. The mistakes are expensive. Each recipe below exists because the shortcut it replaces costs more tokens or returns worse answers.
Land in an unfamiliar repo. Shape first, then gauge, then ingest.
monk tree # ranked map; read the histogram in the footer
monk context . --stats-only # what a given --min would actually cost
monk context . --min 7 # writes to a temp file above ~10k tokens
Take --min from the printed histogram, never from memory. Scores are relative
to the scan root, so a threshold read at the root does not transfer to a
subtree, and the scale turns rank-percentile once a repo passes 100 files.
Higher --min means fewer files, so --min 10 is the narrowest view there is,
not an overview. For shape, use tree.
Chase a defect. Go straight to the definition, then read whole files.
monk symbol handleAuth # cross-language definitions
monk catfiles src/a.ts src/b.ts # one call, whole files, LOC headers
monk outline src/big.ts # signatures only, when shape is enough
Scope a refactor. Budget the ingest instead of guessing a threshold.
monk tree packages/api --min 6
monk context packages/api --max-tokens 60000 # packs top-scored files that fit
monk deps packages/api # dev and indirect listed apart
Find the source of truth. canon clusters facts restated across languages.
monk canon packages/api # narrow by path
monk canon . --max-files 100 # parallel implementations of one contract
Narrow by path rather than raising --min. A high --min keeps only manifests
and entry points, which share generic vocabulary and lower precision. Raise
--max-files when several services or SDKs restate one model, because there
the shared fact is the widest thing in the repo. Output is a candidate list.
Read the copies before calling anything drift.
Prove the change helped. Record a baseline, change one thing, compare.
bun run bench --save # before
bun run bench # after, with deltas
Habits that pay for themselves:
| Instead of | Use | Why |
|---|---|---|
cat / head / tail |
catfiles |
One call, whole files, no slicing blind |
grep for a definition |
symbol |
Finds it across languages, ranked by importance |
Dumping context to the terminal |
Let it write a file, then read it | Terminals truncate; the file does not |
Raising --min to cut canon noise |
Narrowing by path | High --min lowers canon precision |
| Asserting a change worked | bun run bench |
Wall time lies; the token and count columns do not |
Prompting the Agent
The recipes above are what the agent runs. These are what you type. Directives compose, and the order matters more than the wording.
Refactor without breaking things. Ingest, plan, attack, then build.
#meditate 6 on packages/auth
#plan consolidate the three token validators into one
#attack 3
#plan emits checkbox steps carrying a confidence score each and a net LOC
delta per phase, and any refactor plan must end with a cleanup phase. #attack
spawns adversaries that meditate before criticizing, each returning a confidence
score and the single largest risk. A third #plan leaves plan mode and
executes.
Ask for subtraction in the prompt, or you will get addition:
#plan remove the adapter layer in src/http and inline its two call sites.
Net LOC must be negative. If it cannot be, say why and stop.
Distill repeatable work. Preview a project skill before adding it:
#make_skill browser verification
The command writes nothing until you approve the complete SKILL.md preview.
Remove dead code. Audit first, then reference findings by ID.
#audit debt smell packages/api
fix h1 m3
One caveat decides whether this is safe. Monk finds definitions, not callers.
symbol answers "where is this defined" across languages, and no tool here
answers "who calls this". For deletion, the second question is the one that
matters, so plain grep is correct for call sites. The directive banning grep
bans it for definitions only.
#meditate on packages/api
List every exported symbol. For each, take the definition from monk_symbol and
the call sites from grep. Report only those with no caller outside their own
file, with counts. Delete nothing until I confirm the list.
Collapse duplicated truth. Findings name where the fact should live.
#canon packages/api
fix c1 c2
Each finding names a canonical home and the generation or import path that keeps the other copies honest. Where no such path exists, the agent proposes a check that fails loudly instead.
#canon covers a fact restated across languages. Its sibling covers the same
fact restated across manifests in one language, which canon cannot see:
#audit drift .
fix h1 h2
Reading every manifest in a large polyglot repo costs under 10k tokens, so this
runs on the whole tree rather than a sample. Most of its value is knowing what
is not drift: Cargo workspace inheritance, path and catalog: specifiers,
peer dependency ranges, and semver-equal spellings like ^19 and ^19.0.0.
Habits inside the scaffold.
| Habit | Why it pays |
|---|---|
Open non-trivial work with #meditate <target> |
The pre-flight loads project skills, AGENTS.md, and recent reflections before anything is proposed |
#recall <topic> before re-reading source |
Past decisions and their reasoning live in commit bodies, far cheaper than re-ingesting the repo |
#spawn N <task> for scoped parallel work |
Sub-agents inherit the directives and are handed a contract that makes them meditate before acting |
#attack before any non-trivial build |
Losing an argument to five adversaries is cheaper than shipping the plan |
#reflect at the end of a session |
The next session starts with this one's reasoning, not just its diff |
Two phrases change the answer you get:
- root cause. The agent must emit
root cause: <file:symbol> | fix lands: <file:symbol>before editing. Two different places means it is patching a symptom, and it has to say so. - net LOC. Forces a plan to account for what it adds rather than only for what it delivers.
Ignore Rules
tree and context honor .gitignore at every directory level. A built-in
blacklist drops what is never source: package stores, build output, caches,
lockfiles, minified artifacts, and files over 500KB.
A .monkignore file (same syntax) fogs paths from general meditation. context
drops them, tree still lists them with a (monk-omit) tag, and you can always
target a fogged folder explicitly.
Benchmarks
bun run bench # defaults to the current directory
bun run bench /path/to/repo # one baseline per target
bun run bench --save # re-record the baseline
bun run bench --watch # re-measure on every save under src/
bench records median wall time, output tokens, and result counts for each tool
against a real repo, then prints the delta against your local baseline. Tokens
and counts are deterministic. Wall time carries a few percent of noise within a
run and more across sessions, so treat anything under 5% as flat and distrust
cross-session comparisons. Baselines are gitignored because timings are
machine-specific.
bun run corpus # fetch the pinned evaluation corpus
bun run efficacy # score canon recall and noise against it
corpus fetches five implementations of one API spec in four languages, pinned
by SHA. Because the spec defines which facts are restated, efficacy can score
recall objectively. Its precision figure is a proxy: it penalizes known
vocabulary only, so it cannot catch novel noise.
Extending
Tools are built with citty. To add one:
- Create the command in
src/tools/. - Export it in
src/tools/index.ts. - Write an integration test in
tests/(enforced byconventions.test.ts).
No comments yet
Be the first to share your take.