Repository navigation
v2.19.0
[2.19.0] — 2026-09-29
Changed
- The MCP server advertises a 20-tool core by default (#410).
tools/listsent 71 tools (34.7 KB, about 8.7k tokens on clients that load schemas eagerly), and 45 of them only read or write state files:agent_*,task_*,session_*,config_*,system_*,guidance_*,hooks_*andmcp_status. The default roster is now monograph (build, query, suggest, impact, context, neighbors),pick,org_skill_show,monomind_tool_search,knowledge_search/ingest/remove,monodesign_detect/fix/palette, and the five memory tools the generated CLAUDE.md and the KG nudge name (memory_pattern-store,memory_feedback,memory_kg_ingest,memory_kg_search,memory_kg_stats), 14.6 KB in all. Every other tool is still callable by name and found throughmonomind_tool_search;MONOMIND_MCP_FULL=1still advertises all of them.
Added
- Coder mode on every full-access runtime (#431, agent-exec protocol rev 19).
agent execnow drives claude, codex, copilot, antigravity, opencode, kimicode, grok, qwen, pi — and the new Cline, Aider and DeepSeek Harness (dsh) runners — with matchedstart/status/tool/doneevents and full-access editing/commands, instead of only claude and codex having real coverage.--effort off|low|medium|high|xhigh|max(rev 16) is now honored per runtime where the vendor CLI supports it and reported as a status notice where it is ignored.agent execretries a transient provider rate limit (HTTP 429), now its ownrate-limitedcode distinct fromquota(rev 20), up to 3 attempts with ~2s/~4s backoff and jitter or the provider'sRetry-Afterhint, each wait capped at 30s and kept inside--timeout, emitting astatusnotice before each retry. Cline turns run scoped by default (file edits inside the project only; approval-gated tools refused) unless given full access.monomind init --target agentsand--target cline/--target aiderwrite only the files those runtimes read (AGENTS.md, or nothing extra) instead of every platform's files. agent exec --access read(#388, agent-exec protocol rev 21, capabilityagent-exec-access-read). A turn that can read the project and the web but cannot edit files, run arbitrary commands or start subagents. Allowed:Read,Grep,Glob,LS,WebSearch,WebFetch,TodoWrite,Skill,ToolSearch, caller (stdio) tools, and shell commands that start withgit status|diff|log|show|blame,ls,cat,head,tail,wc,rg,greporfind(plus any--allow-bash-prefixentries) with no pipes, redirects, chaining, substitution or subshells, and nofind -exec/-delete/-fprint…,rg --preorgit --output/--ext-diff.Edit,Write,MultiEdit,NotebookEdit, other shell commands andTask/Agentare denied (tool_activityenddenied: true). Works with--settings. claude enforces it itself; codex runs--sandbox read-only(neverdanger-full-access, whatever the git level) and pi/pi-rpc run--tools read,grep,find,ls. Every other runtime, opencode included, answerserror {code:"unsupported"}.agent scan --jsonentries gainaccess_modes(e.g.["scoped","read","full"]).- Caller tools with
agent exec --access full, and parallel caller calls (#389, agent-exec protocol rev 22, capabilityagent-exec-full-access-tools).--access full --tools stdio --tools-file …is supported and tested on claude and every other runtime withfull_access: true: caller tools sit next to the native tools and use the sametool_call/tool_resultframes and--tool-timeoutas scoped mode (no monomind maximum; bounded by--timeout, and on claude by Claude Code's MCP call timeout — a 130s call was verified). When one assistant message makes several caller calls, all theirtool_callframes are sent before monomind waits for any result, and results match byidin any order (claude marks caller toolsreadOnlyHintso Claude Code runs them concurrently; fence runtimes start a round's calls together).agent scan --jsonentries gaincaller_toolsandcaller_tools_with_full_access; a runtime that cannot take caller tools in the requested mode answerserror {code:"unsupported"}instead of dropping them.--allow-bash-prefixis still rejected with--access full. agent execreports what the vendor CLI really runs with, and--sandboxpicks its own sandbox (#396, agent-exec protocol rev 23, capabilityagent-exec-sandbox). The default is unchanged: without the new flag, a non-org turn still runs codex withdanger-full-access, grok without a sandbox, and copilot, qwen, antigravity and others with approvals off. Thestartevent now says so, withnative_sandbox(read-only,workspace-write,full,none, ormonomindfor claude, where monomind enforces access itself) andapprovals(off,on,n/a), and eachagent scan --jsonentry gives the same defaults plussandbox_modes.--sandbox read-only|workspace-write|fulluses the CLI's own sandbox on codex, grok and dsh.fullmeans today's default on every runtime. Other modes on other runtimes fail withunsupported. The flag can tighten an org role's git level but never loosen it.--access readalways runs codex read-only, and--access read --sandbox fullis a usage error. Callers that don't want an unsandboxed turn (e.g. mono-agent) should pass--sandbox.
Fixed
- The per-prompt Second Brain lookup only sends the prompt to a loopback server (#402). The route hook POSTed every substantive prompt to the
urlin.monomind/control.jsonwithout checking where it pointed, so a tampered or committed control.json could send prompts to any host. The POST now happens only when that url is http(s) to127.0.0.1,localhostor::1(no credentials in the url); otherwise the hook skips it and uses the local keyword fallback. - monobrowse no longer leaves Chromium profiles in /tmp (#395). Every browser monobrowse launched got a fresh
--user-data-dirunderos.tmpdir()(monomind-browser-*,monomind-browse-*) that nothing deleted, so they piled up until /tmp ran out of quota. A profile dir monobrowse created is now deleted once its Chrome has exited: on a graceful close, on the kill fallback, onbrowse closefrom a later process (the session record carries a newownsUserDataDirflag), and when a launch fails. Every launch also sweeps dirs left by a crashed or killed process: only exact monobrowse names directly in tmpdir, real directories (never symlinks), older than 10 minutes, whose owning pid is dead and that no live Chrome still uses (/proccommand lines on Linux, the profile'sSingletonLockeverywhere). A caller-supplieduserDataDiris never deleted. - The provider API key file and memory databases are gitignored (#398).
monomind.config.json(whereproviders configure -kstores the key in plain text),.swarm/and.claude/memory.dbwere not ignored afterinit, and doctor's gitignore check still passed. Doctor now requires all three, anddoctor --fix(whichinitruns) adds any that are missing to the root.gitignore.providers configureprints where it wrote the key and warns when that file is not gitignored. mastermind-budgetsnow sets caps the org runtime enforces (#400). Itssetwrote.monomind/orgs/<org>-budgets.json, which nothing in the runtime reads, so a budget set through the skill capped nothing. It now editsroles[].budget_usd,roles[].budget_tokensandrun_config.budget_tokensin the org definition, validates it and runsmonomind org reload(the caps hot-reload with spend kept).showandalertread spend frommonomind org costs --format jsonand the run's budget events. There is no org-wide USD cap, and the skill now says so and refuses to fake one.resetis replaced byclear, which removes a role's own caps.mastermind-routinesmaps onto the orgschedule(#400). It wrote per-agent cron routines to<org>-routines.json, which the runtime never runs. It now sets or clears the org'sscheduleinterval (applied bymonomind org serveat start), pauses and resumes withorg pause/org resume, and triggers a run withorg run.listflags any entries left in the old file as not enforced.- The dashboard's Budgets data shows the enforced limits.
GET /api/org/:name/budgetstakesorg_budgetandagent_budgetsfrom the org definition (run_config.budget_tokens, each role'sbudget_usd/budget_tokensor itspolicy.maxUsd/maxTokens) instead of<org>-budgets.json. cleanup --forceno longer leaves hooks pointing at deleted helpers (#401). After a defaultinit,cleanup --force --purge-dataremoved.claude/helpers/but kept all 17 monomind hooks in.claude/settings.json, so every prompt and tool call then failed withCannot find module …/hook-handler.cjs. Cleanup now rewrites.claude/settings.jsonand.gemini/settings.jsonin place, dropping only the hook entries andstatusLinewhose command runs a helper the same plan removes (plus matcher groups and events left empty); other keys and user hooks stay, and a git-tracked settings file is still never rewritten. It also removes themonomindserver from.kimi-code/mcp.json, the[mcp_servers.monomind]table from.codex/config.tomland init'snpx monomindbash rules fromopencode.json.initnow records hashes for the converted.opencode/agent,.opencode/commandand.kimi-code/agentsfiles,.kimi-code/plugin/kimi.plugin.jsonand.gemini/helpers/statusline.sh, so cleanup can prove they are untouched installs and remove them; ones you edited are kept. The dry run lists every edit.- The SessionStart
session-restorehook no longer parses every transcript (#403). AfterquickSummary()went cache-first for #42, session-restore still calledquickSummaryData(), which re-parsed every transcript under~/.claude/projectssynchronously (tens of seconds, up to 140 s on active machines). That blocked the event loop, so the handler's own safety timer never fired and Claude Code killed the hook at 15 s.quickSummaryData()now reads the same cached totals asquickSummary()and starts the detached refresh when the cache is stale or missing, at most once per process. A cold cache writes notoken-summary.jsonon that session start. monograph_suggest task=returns the nodes relevant to the task (#406). Suggest answered only fromAMBIGUOUS/INFERREDedges (about 3% of a real graph), so most task descriptions got "No suggestions for this task. Run monograph_build first." even on a fully built index. Withtask=it now lists the toplimit(default 10) nodes ranked by the same searchmonograph_queryuses, each withfile:line, followed by the graph-topology questions about them when any exist. It says "Run monograph_build first" only when the graph has no nodes; a built graph with no match for the task says that no nodes match.- monograph no longer indexes monomind's own asset mirrors, gitignored files or anonymous closures as searchable symbols (#404). In a fresh 5-file project, 30,405 of ~30,430 nodes came from the
.agents,.gemini,.kimi-codeand.opencodetreesmonomind initwrites. The scan now skips.agents,.gemini,.kimi-code,.opencode,.codex, its own.monographcache and.mailby default, and inside a git work tree it only scans filesgit ls-files --cached --others --exclude-standardlists, so.gitignoreis honoured (tracked files stay in even if they match; a.monographignore!negation can still bring a file back; outside git the walk is unchanged). Anonymous closures (() => {,function () {) stay in the graph so calls inside them are still attributed to them, butmonograph_query/search and god-node rankings no longer return them.@monoes/monograph1.6.14. monograph_impactandmonograph_contextno longer pick one of several same-named symbols (#405). Without afilePathboth tools took whichever node namednamecame first, so asking aboutbridgeStoreEntrycould land on a test mock and report "0 callers, Risk LOW" for a function with 29 call sites. When a name matches more than one definition they now return the candidates (non-test definitions first, withnodeId, file and line) and ask you to re-run withnodeIdorfilePath, likemonograph_neighborsalready did. Both tools take the newnodeIdinput, andfilePathalso accepts a trailing path fragment. The[MONOGRAPH_HINT]grep hint still picks the first match and is left for a follow-up.monomind memory searchfinds matches with default options again (#407). The--thresholdoption defaulted to 0.7 while the memory bridge and the command's own fallback used 0.3, and correct matches from the bundled embedding model score about 0.55–0.61, so default searches returned nothing. The option default, the bridge and the sql.js fallback now share oneDEFAULT_SEARCH_THRESHOLD(0.3).monomind browse …exits as soon as its output is written (#408). Every browse subcommand left its CDP websocket open, so the process only ended at the CLI's 5 s force-exit watchdog:browse get titletook ~5.5 s against 0.3 s through the baremonobrowsebin. The command now drops its CDP connection once the subcommand finishes (also when it fails), without touching the browser, so the next command still reuses the session;get titlenow takes ~0.3 s andopen~1.6 s instead of ~5.8 s.@monoes/monobrowse1.0.28 exportsdisconnectSession()for this.[MONOGRAPH_HINT]s now reach the model, and the status line stops showing an unmeasured "$ saved" (#409). The PreToolUse pre-search and pre-bash hooks printed their hints (and the graph-gate reminder) as plain stdout, which Claude Code only shows in the transcript, never to the model. They are now one JSON document,{"hookSpecificOutput":{"hookEventName":"PreToolUse","additionalContext":…}}; stdout stays empty when there is nothing to say and on any block, whose reason is still on stderr with exit code 2. Each hint was also credited as 1,700 saved tokens, which fed the status line's 💰 dollar figure andgraph-status's "saved $". Hints no longer earn savings credit, and both displays show the hint count instead of dollars.- The fallback hook-handler's PreToolUse blocks now reach Claude Code (#446). The fallback
hook-handler.cjsthatinitwrites when the full helpers can't be copied ended with an unconditionalprocess.exit(0), overriding the exit code 2 its graph gate sets to block a command. It now exits withprocess.exitCode, so a block's exit 2 survives. - Generated MCP configs start the version that ran
initinstead ofmonomind@latest(#419)..mcp.json, Codexconfig.toml, OpenCodeopencode.json, Kimimcp.jsonand the Antigravity/Gemini entries launchednpx -y monomind@latest mcp start, which re-resolves the dist-tag on every start (3–4 s totools/list), could hang past the client's startup timeout on a cold npx cache and leave_npxbroken, and could switch versions mid-session. They now runnpx -y --package=@monoes/monomindcli@<version> monomind mcp start, and the printedclaude mcp addhints match.--pin latestor--no-pinkeepsmonomind@latest;--pin <version>still picks another version.monomind init --forcere-pins after an upgrade;monomind updatedoes not rewrite these configs. The Codex, OpenCode and Kimi entries also drop the unreadMONOMIND_MODE,MONOMIND_HOOKS_ENABLED,MONOMIND_TOPOLOGY,MONOMIND_MAX_AGENTSandMONOMIND_MEMORY_BACKENDenv vars (already gone from.mcp.json). - The per-prompt route hook is cheaper (#415). Opening the graph ran
npm root -g(a 60–250 ms spawn) on every prompt in a project without its own@monoes/monograph; the answer is now cached for 24 h in~/.monomind/cache/npm-root-g.json(or underMONOMIND_HOME), keyed by the node binary,npm_config_prefixandPATH, and asked again when the cached root is gone. A trivial reply ("ok", "yes", "continue", "thanks", fewer than three content words) now returns before any routing work — no pick, no graph, no Second Brain lookup, no banners — instead of only skipping the pick. The[PICK]line names an Org skill by its MCP call only: the(or: npx -y monomind org skills show …)suffix, ~40% of the line, is gone, since the picking sectioninitwrites into CLAUDE.md already gives that CLI fallback. - The CLAUDE.md
initwrites is 4 KB instead of 10.7 KB (#412). It is sent with every request and every subagent, and about 40% of it did not change what the model does in the project. The default (standard),minimalandsolotemplates drop the CLI command table, Monoswarm Rules, the topology/max-agents Project Config, the curated agent list, Memory Commands, Quick Setup, "Claude Code vs CLI Tools", Support, and the DDD / TDD-London / event-sourcing / "5-10+ todos" mandates; the opt-infull,securityandperformancetemplates keep their reference sections. Build & Test lists only thebuild,testandlintscripts package.json defines (with the detected package manager; thenpm initplaceholder test script does not count) and is left out when there are none. The Second Brain section appears only when thedocumentscapability is active, and the agent picking rules only when the[PICK]prompt hook is installed. When a parent directory's CLAUDE.md already carries the monomind block,initin a subdirectory no longer writes a second copy and prints a warning naming that file.init --forceover a pre-delimiter CLAUDE.md also replaces the retired sections instead of leaving them behind. monomind initno longer installs docs as slash commands or--minimalas the full catalog (#411). Claude Code registers every.mdunder.claude/commands/as a command, and its skill/command listing has a fixed budget past which descriptions are dropped. init now leaves out command-directory READMEs,_-prefixed includes andreferences/pages (20 descriptionless entries); the task-file spec the mastermind commands read moved to.claude/skills/mastermind/references/taskfile.md, and the duplicatecommands/mastermind/references/copies are gone.--minimalinstalls 23 skills instead of 83: the mastermind engineering workflows (design, plan, execute, review, receive-review, debug, research, worktree) and the pieces they read, monolean, monodesign, stop-slop, verification-quality and the memory, GitHub and browser toolkits, plus the mastermind idea, org and memory skills the platform install always writes; the org-admin mastermind skills, monoswarm, hooks-automation and the rest are a newextendedskill set, still part of the default install. The init wizard's Custom skill-set answer is now honoured (it leftskills.allon, so every skill was installed) and no longer writes into the shared presets; it also offers the extended, browser and advanced sets. Agents markeddeprecated: trueare no longer installed, and thetraining/verifycommand groups, which never existed, are gone from the command map.- Agents, skills, commands and the guidance catalog only name MCP tools and CLI commands that exist (#421). Shipped markdown referenced 43 unregistered
mcp__monomind__*tools 208 times per tree (swarm_init,memory_usage,coordination_orchestrate,hooks_pre_task, ...), the guidance catalog behindguidance_capabilities/guidance_recommendlisted 30 tools and 15 commands that do not exist, and optimization agents told the model to run inventedmonomind topology-analyze-style commands. References now point at the real tool (monoswarm_init,monoswarm_memory,task_create,hooks_pre-task,monofence_scan,performance_bottleneck, ...) or are removed where nothing equivalent exists, and the catalog is rebuilt from the live registry.scripts/lint-tool-refs.mjs(pnpm run lint:tool-refs, run in CI) fails on anymcp__monomind__<tool>missing from the full MCP registry, any catalog tool or command that does not resolve, and any unresolvedmonomind <cmd>in an agent definition. The inventedmonomind github …/monomind actions …/monomind swarm …commands in six GitHub agents (140 references per tree) are still allowlisted inKNOWN_BAD_CLI_REFS; the allowlist can only shrink. - Session start no longer rebuilds the graph in non-git directories, and builds stop writing into the repo root (#414). Without a git HEAD the SessionStart freshen hook could never see the index as fresh, so every session started a full rebuild (a non-git workspace parent grew to 3.4 GB). The hook now skips directories outside a git work tree and prints a one-line hint to run
monomind monograph buildyourself, and it starts at most one automatic build per project every 10 minutes (tracked in.monomind/graph/last-auto-build).GRAPH_REPORT.mdis now written to.monomind/GRAPH_REPORT.mdinstead of the repo root;monomind monograph build --report-path GRAPH_REPORT.md,MONOGRAPH_REPORT_PATHorbuildAsync(..., { reportPath })restore the old location. The churn cache moved from.monograph/cache/to.monomind/cache/. initno longer runsnpm install @monoes/monographin your project (#420). The code-graph step resolved@monoes/monograph/dist/src/index.js, which the package'sexportsmap does not expose (ERR_PACKAGE_PATH_NOT_EXPORTED), so it always fell back to installing monograph into the user's project: a newdependenciesentry inpackage.jsonand about 61 MB ofnode_modules. It now resolves the package's public entry from the CLI's own dependencies. The install fallback is gone; if monograph cannot be loaded, init prints one line saying to runnpx monomind monograph buildlater.init's summary counts the files it actually wrote (#420). It counted report items (a whole skill folder, an agent category) as files and labelled every skip and diagnostic "already exist", so an empty repo that received 2,060 files was told "267 created, 101 already exist". The counts now come from the disk, before and after the run, across the root files and every dot-directory init writes to (all platform trees): directories and files created, existing files updated, and existing files left unchanged.- monodesign detection no longer floods its output (#424). One failing token repeated on hundreds of elements printed one finding per element:
doc/index.htmlgave 249 findings for 17 distinct issues,monodesign_detectreturned about 41 KB, anddesign fix --dry-runprinted nearly whole files. The text report now prints one line per (rule, snippet) with its count and up to three example locations (--no-grouplists every occurrence;--jsonis unchanged).monodesign_detectreturns the same groups, 20 at a time and most severe first, with rule descriptions listed once and amorehint that names the nextoffset;verbose: truereturns the raw list. Contrast the static analyser cannot measure (translucent text or backgrounds, overlays, gradients, SVG text, or a page with no resolvable surface) is now reported as unverified and left out of the default count, with a line saying how many were held back (--include-unverified/include_unverified: trueshows them). Ondoc/design-system.htmlthat removes 99 of 102 contrast findings.fix --dry-runprints one hunk per edit with 3 lines of context instead of a single hunk from the first change to the last. - Opening the memory database no longer re-runs its dedupe repairs every time (#426).
initializeSchemaran the namespace+key dedupe and the FTS5 duplicate-row cleanup on every open. Both scan every row, which made eachknowledge_searchormemorycall wait seconds on a large store. They now run only while the database'sPRAGMA user_versionis below the schema version, which is now 4, so each existing store is repaired once more and then skips them. The namespace+key repair also runs whenever the unique index is missing, and an older release that opens the file writes its lower version back, so the next open repairs it again. On a synthetic 20k-entry, 507 MB store, a cold open fell from 3.0–4.5 s to about 10 ms. - Semantic search stays on brute force up to 100,000 entries (#426). The default
MONOMIND_HNSW_THRESHOLDwas 5,000. On the same 20k-entry store, the first search spent 78 s building the HNSW graph and wrote a 389 MB JSON cache, and later searches took 1.2 s to load that cache with about 1 GB peak RSS. Brute-force cosine answered in about 0.25 s at about 330 MB. The default is now 100,000, and setting the env var still overrides it.
Security
hooks_pre-commandno longer rates destructive compound commands as safe (#399). The MCP tool capped any command starting withecho/ls/catat low risk andgitat 0.2, soecho hi && rm -rf ~/andgit push --force origin mainreturnedshouldProceed: truewhile the PreToolUse Bash gate blocked them. It now splits the command on&&,||,;,|,&and newlines (quotes respected), checks every segment with no prefix caps, and applies the Bash gate's destructive patterns (mirrored, parity pinned by a test). Force-push to main/master, recursivermof~,$HOMEor/, piping into a shell (curl … | sh,cat x | sh),dd of=/dev/…,mkfsand fork bombs are critical andshouldProceed: false;ls -la,git statusandecho histay low.
npm: @monoes/memory@1.0.23, @monoes/monodesign@1.2.23, @monoes/monograph@1.6.15, @monoes/monobrowse@1.0.28, @monoes/monomindcli@2.19.0, monomind@2.19.0