Prompt modes and focus
Instruction files, @path includes and how much MendCode context each prompt mode adds.
Instruction files (AGENTS.md and friends, see instruction files) support whole @relative/path lines outside code fences. Paths resolve relative to the containing file, confined to the canonical project root including symlink targets. Cycles are deduplicated; limits are depth 8, 100 files and 64,000 characters total, plus existing per-file caps. Disable with /tier instruction_includes off.
/output-style caveman is opt-in prose compression for balanced/full, preserving exact code, paths, quantities, verification and uncertainty. No measured savings percentage is claimed.
/prompt-mode opens the project prompt selector. Up/Down selects; Tab or 1/2 changes between modes and focus families; Enter applies; c cycles; r refreshes; Esc returns. Setup and Customize open the same selector. Tab in the chat prompt only completes a slash command.
| Mode | Native model context |
|---|---|
minimal | A small MendCode boundary, the one-line docs pointer, your project and user instructions, and independently selected memories. Skills are listed by the skill tool (called with no name), not in the prompt |
focus | Native coding harness, your project and user instructions, the skill catalog (name and one-line description, at most 4,000 characters), a one-line family note, the working core (four habits, below), the model note when one matches, the capability line, boundary and memories. The lean default |
guide | Focus with the provider guide in place of the working core: the working basics every family shares and a longer guide to how the model's family uses MendCode's tools, with model notes (reasoning versus not, size variants). Costs more on every call, see below |
full | Guide plus a short operator's guide to MendCode itself (about 1,370 characters, generated from the reference cards) and family context files |
custom | Project prompt, boundary, your project and user instructions and memories; no inherited focus/full context and no skill catalog |
What the model's provider family gets in each mode
Every native model call gets guidance for the family of the model it is sent to (Claude, GPT/Codex, Gemini, DeepSeek and so on); how much depends on the mode, and so on the tier:
| Mode (tier that sets it) | Family guidance sent on every call |
|---|---|
minimal (minimalist) | None. The prompt is the same for every model |
focus (balanced) | One line, MendCode focus: <family> (auto), followed by the family's short working rules (one to three sentences); for a few models with known quirks (GPT-5.6, GPT-6 Astra, Claude Sonnet 5 and Opus 5, DeepSeek V4 and V3.2, Kimi K2.5) a short compatibility note too |
guide (no tier; /prompt-mode guide) | focus plus the provider guide: the basics every family shares, the family's full guide file (packages/daemon/prompts/focus/<family>.prompt.md) and the note for the model when one matches (reasoning or not, Flash or Pro, Opus or Haiku) |
full (full) | guide plus the family's context files from the project (for example CLAUDE.md for claude, GEMINI.md for gemini, .agents/context.md for codex and deepseek) when the instruction loader has not already sent them, and the operator guide |
custom | None; your project prompt replaces it |
So balanced does adapt to the provider, but briefly: the family's full guide is guide and full only. For the full guide on a balanced project, run /prompt-mode guide (or mendcode prompt mode guide); it costs about 560 to 690 more tokens on every call, depending on the family (see the budgets below).
- Which family: with
auto(the default) it is read from the id of the model each call goes to, so changing models changes the guidance on the next call. A model behind a gateway (openrouter/anthropic/claude-…) gets its own family, not the gateway's. A model no family claims getsneutral: a family-less line infocusand the shared basics inguide, never another vendor's text. The full matching rules are below. - Forcing a family: pick one in
/prompt-mode(Tab switches to the families) or runmendcode prompt mode --focus <family>. The choice is saved per project and wins over the model; pickingautoagain follows the model. - Not affected: the family changes only this text, never the provider, model, permissions, budgets or transport. Claude Code, Codex, ACP agents and pi build their own prompts, so this applies to native models only (
claudetherefore means Claude on the native engine with an API key).
The user's instructions (the AGENTS.md/CLAUDE.md hierarchy and the global AGENTS.md) are the user's rules, not optional chrome: every mode carries them, within the loader's caps (16,000 characters per file, 64,000 in total), and --no-context-files is the only switch that leaves them out. Before this was true only in full, so the default focus tier ignored a repository's AGENTS.md until a file under it was read. For a typical project (a 1.6 KB AGENTS.md and five skills) the prompt grows, in estimated tokens (characters over four), by 0 → 204 in minimal, 0 → 346 in focus and 346 → 346 in full; a repository without instruction files or skills adds nothing in any mode.
APPEND_SYSTEM.md (user, package or project layer, extensions) is the user's own text too, so every mode sends it after the instructions; before, only full did, and "always answer in Spanish" written there was silently dropped in the default focus. SYSTEM.md replaces the packaged base prompt where a mode sends it (focus, guide, full); minimal and custom have their own base.
A tier sets the project's mode once when applied (minimalist → minimal, balanced → focus, full → full); no tier sets guide. Modes are ordered minimal < focus < guide < full, and each one is the previous one plus more text.
Default mode is focus, default family auto. Choices are per canonical project directory in <dataDir>/prompt-context.json, saved atomically. The existing TUI promptContext value remains a default for projects without a saved choice. Changes apply to the next native model call, including after restart. External Codex/Claude Code engines retain their own prompt construction.
Custom mode reads .mendcode/prompts/custom.md inside the project: a regular file, at most 32 KiB, including UTF-8 multibyte content. Symlinks outside the project are rejected. Optional frontmatter name: or a Markdown heading names the choice; frontmatter is omitted from instructions. {{cwd}} expands to the project directory. The picker and cycle include custom only when usable. An explicitly selected custom mode with a missing, empty or unsafe source keeps the small boundary and reports the reason; it never inherits focus. Selecting a mode creates no project prompt file.
Focus families are codex (GPT and o-series), claude (only when Claude runs on the native engine with an API key), gemini, kimi, deepseek, mistral, glm (Z.ai), minimax, grok and local (open-weight models served by Ollama, LM Studio, llama.cpp or vLLM), plus auto. They select native behavior guidance and full-mode context sources, without changing provider, model, permissions, budgets or transport.
auto (the default for projects with no saved family) follows the model: on every native call the family is resolved from the session's model id, so switching the model changes the guidance on the next call. claude-*, anthropic, sonnet, opus, haiku map to claude; gpt-*, o<N>, codex, chatgpt, openai to codex (except gpt-oss, OpenAI's open-weight model, which is local); gemini-* to gemini; kimi, moonshot to kimi; deepseek to deepseek; mistral, codestral, devstral, magistral, mixtral, ministral to mistral; glm*, zhipu, z.ai/z-ai to glm; minimax to minimax; grok*, xai to grok; llama*, qwen*, gemma*, phi*, granite*, ollama, lmstudio, llamacpp, vllm, local to local. The model name is matched first (the part after the last / or :), then the provider prefix, so openrouter/anthropic/claude-3 is claude and ollama:llama3.1:8b is local. A model no family claims (unknown ids) resolves to neutral: a one-line family-less guidance (read before editing, stay in scope, verify with command output) and no other vendor's text. Choosing a family explicitly always wins over the model and is saved as before; choosing auto again returns to following it. A codex saved before auto existed was also what an untouched project saved on its first mode change, so it cannot be told apart from a deliberate choice and is kept; pick auto to follow the model. The selector, /setup, prompt status/sources and the focus section label in /context show auto → claude (the family resolved for the session's model; outside a session, for the project's main model). prompt sources reports those sources and their native behavior policy. There is no import of donor code, framework or upstream prompt snapshots. Automatic equivalence between v1 focus and v2 folder profiles remains a user decision; profiles continue to isolate memories, model roles and default permissions independently.
The provider guide (guide), budgets and the operator guide
focus is the lean default and its text is what it was before guide existed plus three parts: the docs pointer below, the working core and, when one matches the model, the family file's model note. Without those three it is byte for byte the earlier text for every family that existed before guide (pinned by packages/daemon/test/prompt-guidance.test.ts against packages/daemon/test/fixtures/prompt-focus-pre-guide.json), and glm, minimax, grok and local have a one-line note of the same size, enough for auto to resolve them. The working core is the <!-- focus --> block at the end of basics.prompt.md (373 characters, at most 600): say in one sentence what a batch of changing tool calls will do, a todo list for three or more steps (through tool_search when it is deferred), cite code as path:line, answer with the result first and then the check and what stays unverified. That diffs and whole files are not pasted is said once, by the base prompt. The core and the longest model note together stay under 1,200 characters; neither was measured with an eval. guide and full send the full basics instead of the core, never both. The longer per-family guidance is its own mode, guide, because it is sent on every model call and a fixed per-call prompt is the main input-token cost. Nothing in it is on unless you choose it (/prompt-mode guide, the setup and customize rows, or mendcode prompt mode guide).
Cost notice. Wherever a mode is chosen or shown, MendCode says what it costs: the estimated tokens the mode puts in front of every model call for the current model's family, measured on the real composed text (the packaged base prompt plus the mode's parts, characters over four, without your project instructions, skills or memory, which no mode changes). The line reads guide · +620 tokens per call (1,190 total), the part added over focus and the whole prompt (minimal and focus read focus · 570 tokens per call), and for guide and full a warning, sent with every call, follows it (a second line in the pages, after · in notices). It appears in the /prompt-mode page (under the highlighted mode) and in the notice after /prompt-mode <mode>, in the /setup and /customize prompt rows, and in mendcode prompt mode|cycle-mode|status (first line of the plain output; the JSON carries the numbers as costs: [{ mode, tokens, overFocus }]). It never blocks or asks for confirmation.
The text lives in files, not in code. packages/daemon/prompts/focus/ holds basics.prompt.md (the working basics every family shares: calls of one response run in order, so independent calls and a small edit with its check go together; edit discipline, todo, background shell, loop, task) and one <family>.prompt.md per family; a model no family claims (neutral) gets the basics alone. A family file has a header (family, provenance), a body for every model of the family, and optional model notes opened by a line <!-- model "Label" /regex/flags -->; the first note whose pattern matches the model id is sent as its own part after the family guidance (for example reasoning versus non-reasoning DeepSeek, Flash versus Pro Gemini, Opus and Haiku). The header is never sent: provenance says what the file is based on. The files are named *.prompt.md on purpose: a plain claude.md or gemini.md would collide with the CLAUDE.md and GEMINI.md instruction files on case-insensitive file systems. They are embedded in the binary and read on first use of a family.
All guidance is original MendCode text. v1 shipped vendor prompts (OpenAI Codex, Gemini CLI, Kimi CLI and Mistral Vibe, all Apache-2.0) for four families; v2 keeps only their behavioural facts, rewritten for this harness and its tools, and never reproduces a vendor's system prompt or documentation. The Claude, DeepSeek, GLM, MiniMax and Grok guidance was behaviour-only in v1 and stays so. Guidance for models newer than the author's reference material (GLM, MiniMax, Grok, Kimi K2.5, DeepSeek V4, Gemini 3, the GPT-6 and Claude 5 generations) is deliberately conservative: only widely documented traits and facts about this harness.
Budgets (characters, tokens estimated as characters over four; PROMPT_BUDGETS in packages/daemon/src/prompt-guidance.ts, enforced by packages/daemon/test/prompt-guidance.test.ts). With the packaged base prompt (cwd /project) and no project instructions, skills or memory, smallest to largest family:
| Mode | Characters (tokens) | Over focus | Ceiling (characters) |
|---|---|---|---|
minimal | 915 (229), the same for every family | -2,761 to -2,937 | 920 |
focus | 3,852 for neutral (963), 3,676 to 3,727 for a family (919 to 932), plus the model note when one matches | 0 | the core at most 600 |
guide | 4,558 for neutral (1,140), 5,538 to 6,109 for a family (1,385 to 1,528) | +706 for neutral, +1,862 to +2,382 for a family | 6,500 |
full | 6,058 for neutral (1,515), 7,038 to 7,609 for a family (1,760 to 1,903) | guide plus about 1,500 characters (+375 tokens) | 7,800 |
The base prompt's terminal rendering block (about 390 characters, sent to every engine) is in all three of focus, guide and full; it raised the full ceiling from 7,400. guide adds the basics (at most 1,100 characters), one family body (at most 3,000) and at most one model note (at most 600). Everything in it is static: no date, path, model name or counter, so a provider can cache it. The prompt parts are ordered base, instructions, skills, boundary, family note, working core or provider guide, model note, then (in full) the operator guide and family context files, then the capability line, and the memory block last, because memory is chosen per user message.
Capability line. In focus, guide and full a native session's prompt ends, before memory, with one line built from that session's tool catalogue (capabilityIndex in packages/engine-native/src/tool-discovery.ts, at most 350 characters). It names the MendCode tools a model tends to deny having, in a fixed order and only when the catalogue has them: image_gen (pictures show in MendCode), computer_* (only when computer use is enabled), remember/memory, websearch/webfetch, browser, screenshot, loop, workflow_*, lsp, secrets, threads, pr_watch, todo. Listed tools and deferred ones are named apart, and deferred ones are said to be reached through tool_search. A deferred tool stays in that list after tool_search finds it, so the line, and the cached prefix before memory, stays the same for the session until its tool set changes. Hosted provider tools (a provider's own web search or image generation) are not in the catalogue and are not named. minimal and custom do not carry it, and neither does prompt build or the costs above, which have no session catalogue.
Every mode but custom carries one line (packages/daemon/prompts/self-knowledge.md, 428 characters, at most 430): the model runs inside MendCode, whose screen (start screen, logo, sidebars, bars, prompt, footer, labels), keys, slash commands, Galaxy panel, pet, agents, models, settings and the model's own tools, hooks and system prompt are MendCode's and not the project's, and for those only it first runs mendcode docs --search <words>; a rule the user sets for later is an extension, not a promise or a one-time check. The behavior half was measured with scripts/eval-extend.ts (gpt-6-luna 3 of 15 before, 14 to 15 of 15 after). Naming the screen's parts was measured with scripts/eval-customize.ts: look requests that a shorter line let go to the project (4 of 24 runs on the eight hardest requests) went there in 1 of 24. The wording is the one gpt-6-luna followed (measurements in the comment on PROMPT_BUDGETS.selfKnowledge): naming the terminal's own parts was followed in 13 of 14 runs, and scoping the search with "for those only" stopped plain coding tasks from opening with a docs search (5 of 10 runs before, 0 of 6 after) while a footer request was still followed in 3 of 3. The same line sits right after the boundary in minimal, focus, guide and full, so it is part of the cached prefix. custom inherits nothing and does not carry it.
full adds a short operator's guide (at most 1,500 characters): the topic list of mendcode docs, where settings, extensions and packages live and in which layers, that customize_ui (found with tool_search) is how a model changes the user's terminal, that daemon settings are the user's to change, the rule never to change permissions, sandbox, trust, proxy or credentials, to read live state before changing it, and that tier, prompt mode, permission mode and process mode are four different things. It is generated, not hand-kept: packages/daemon/prompts/operator-guide.template.md is authored text with the topic list filled from packages/daemon/cards/ and bun scripts/self-knowledge.ts writes operator-guide.md. Generation fails when the template names a slash command, setting or doc file that docs/ does not contain.
Output styles (/output-style)
/output-style [default|explanatory|learning|terse|caveman] saves settings.outputStyle (absent = default) and appends a
short tone block to the native system prompt in every prompt mode, from the next message. explanatory adds brief
"why" notes while working, learning explains steps and may leave a small marked piece for you to write, terse
keeps prose to what you can act on. Styles change how answers read, never tools, permissions or verification. No
argument shows the current style. External Codex/Claude Code engines keep their own prompts. The block shows in
/context as output style.
Automation
mendcode --dir /tmp/mend-data control-plane prompt sources --json
mendcode --dir /tmp/mend-data control-plane prompt build --mode full --focus gemini --model local:test --role main --workflow edit --show-full --json
mendcode --dir /tmp/mend-data control-plane prompt mode full --focus claude
mendcode --dir /tmp/mend-data control-plane prompt cycle-mode
prompt is also accepted without control-plane. No operation means mode; no mode argument reads the current choice. mode --focus <family> sets only the family. dev-js is a compatibility alias for full. The project is the CLI working directory; --dir selects daemon data, as for other automation commands.
Build is a read-only native system-context preview, not a provider request or turn. Its overrides are never saved. Defaults are --mode focus --focus auto; auto resolves from --model (or the project's main model when none is given), and prompt sources --model <id> shows the same resolution. Model/role/workflow select applicable behavior guidance without selecting a runtime model. Review and edit/apply policies are distinct; model guidance is gated by focus family. JSON contains section bytes and bounded previews; --show-full adds assembled instructions. Credential-like values are redacted. Session memory selection and engine-added turn metadata are outside this preview. Metadata queries are allowed to read-only peers; build, set and cycle are not.
Wire commands: prompt.status, prompt.sources, prompt.build, prompt.set, prompt.cycle. Typed client helpers provide status, set and build.