minicode is a small, opinionated CLI that mirrors Claude Code’s interaction model: an agent sits on top of explicit tools, with a visible task queue, strict edit lifecycles, and session persistence. If you are curious about how Claude Code keeps long-running work coherent, this repo is a compact, readable model. It is also inspired by nanocode.
- Visible work state: a shared todo queue is printed every prompt, so the agent’s plan is never implicit.
- Deterministic edits: tools operate on exact strings, not AST magic, reducing “surprise diffs.”
- Session continuity: history and metadata are persisted, so long jobs survive restarts.
- Bounded tools: tool calls time out by default to keep the CLI responsive.
- Composable automation: hooks let you graft in policy checks or prompts at lifecycle events.
Think of minicode as a loop that keeps state explicit. The todo queue and session files are the backbone; everything else reads or writes through them.
User input
|
v
CLI prompt --> Session manager (history + todos) --> Agent loop --> Tool runner
| | |
v v v
Renderer (queue + output) Hooks Filesystem
If you only read one section, start here and then jump to the module you care about below.
- Install dependencies (Python 3.11+):
uv syncThis installs runtime dependencies including pyyaml, which is used to parse YAML frontmatter in skills.
- Run:
python minicode.py- You will see the todo queue panel and prompt. Just start typing a task.
Note: if you edit
AGENTS.md, restart the CLI to reload instructions.
Below is a guided tour of each major subsystem and how they connect. Think of it as the mental model for how a single prompt flows through the CLI.
minicode keeps a per-session queue stored inside .minicode/.sessions/{uuid}/session.json. It reloads on startup and prints before every prompt:
- Items marked
in_progressshow anactiveForm-style hint. - When all items reach
completed, the queue auto-clears and the JSON file is emptied. - Agents sync via
todo_write(Claude Code’sTodoWriteequivalent); users can reprint with/listtodos.
Status labels normalize into pending, in_progress, completed, or blocked, including common variants
in multiple languages, so the UI stays consistent and auto-clear still triggers correctly.
Relationship notes:
- Session manager owns persistence; the queue is stored inside each
session.json. - Agent loop updates it via
todo_write, and the renderer prints it before every prompt.
Each run writes to .minicode/.sessions/{uuid}/session.json and the CLI exposes a full session workflow:
/sessionopens a picker (use arrow keys)./session lastrestores the most recent session./session listshows saved session ids./session <uuid>switches to a specific session./session newcreates and activates a new session.
History replay:
/historyreplays the current session./history 20limits the number of messages shown.
Each session.json stores the todo snapshot so the queue restores on session load.
Relationship notes:
- Todo queue is embedded inside each session file.
- History replay and compact both read from the same session archive.
When the serialized conversation reaches 95% of the model context length, minicode auto-compacts:
- The conversation is replaced by a concise summary.
- The full transcript is archived in
.minicode/.sessions/{uuid}/deprecated_history.json.
Tuning knobs:
AUTO_COMPACT_ENABLED=true|falseAUTO_COMPACT_THRESHOLD=0.95AUTO_COMPACT_FALLBACK_TOKENS=131072
Relationship notes:
- Session manager swaps the live transcript for a summary and archives the full history.
- Hooks can observe
PreCompactif you want auditing or custom prompts.
minicode exposes two edit tools that deliberately avoid implicit transformations:
edit: one exact string replacement; requires a uniqueold_stringmatch.multiedit: multiple sequential replacements within a single file.
Both follow the same lifecycle: read → exact match → replace, and they verify file mtime before writing to avoid stomping concurrent edits.
Relationship notes:
- Hooks can gate edits using
PreToolUse/PostToolUse. - Rendering shows tool results and errors in the transcript.
Hooks allow scripts or prompt-based checks to run at key lifecycle events:
- Events:
SessionStart,SessionEnd,UserPromptSubmit,PreToolUse,PostToolUse,PermissionRequest,PreCompact,Stop - Types:
command/prompt - Defaults:
HOOK_CALL_TIMEOUT=60s,HOOK_PROMPT_TIMEOUT=30s
Config sources (merged by priority):
${CODEX_HOME}/managed_settings.json${CODEX_HOME}/settings.json.minicode/settings.json.minicode/settings.local.json(not for git)
Example:
{
"hooks": {
"PreToolUse": [
{
"matcher": "edit",
"matcherType": "exact",
"hooks": [
{"type": "command", "command": "python scripts/check_edit.py", "timeout": 10}
]
}
]
}
}Relationship notes:
- Agent loop emits lifecycle events that trigger hooks.
- Tool system enforces timeouts independently from hook timeouts.
All tool calls time out after 60 seconds by default to avoid stalled sessions:
error: tool '<name>' timed out after <seconds> seconds
Adjust with:
TOOL_CALL_TIMEOUT=90
Relationship notes:
- Tool runner enforces the timeout and reports the error back into the transcript.
- Hooks remain separately controlled by
HOOK_CALL_TIMEOUT.
- Built-in Markdown rendering for Claude Code–style readability.
bashoutput is collapsed by default; setBASH_OUTPUT_MODE=streamfor live output.- While waiting on the agent, a spinner and elapsed timer keep latency visible.
Relationship notes:
- Renderer pulls from the active session and todo queue on every prompt.
- Tool runner streams or collapses output based on
BASH_OUTPUT_MODE.
Common CLI commands:
/listtodos: reprint the todo queue/historyor/history N: replay messages/session: interactive session picker/session last//session list//session <uuid>//session new/clearor/new: clear the conversation, saved session, and current session todo queue/compactor/compact <focus>: manually compact the conversation/hooks//hooks reload: view or reload hooks
Unknown / commands error instead of being forwarded to the agent.
On startup, minicode loads AGENTS-style instructions and appends them to the system prompt:
- Global scope:
$CODEX_HOME/AGENTS.override.mdfirst, otherwiseAGENTS.md - Project scope: from repo root down to cwd, taking the first non-empty of
AGENTS.override.md,AGENTS.md, then anyAGENTS_FALLBACKentries
Aggregation stops once PROJECT_DOC_MAX_BYTES (default 32 KiB) would be exceeded.
Skills live under skills/, each with a SKILL.md. They are loaded only when invoked to keep context lean.
Common variables:
TOOL_CALL_TIMEOUT: tool timeout (seconds)AUTO_COMPACT_ENABLED: enable auto-compactAUTO_COMPACT_THRESHOLD: trigger thresholdAUTO_COMPACT_FALLBACK_TOKENS: fallback context lengthBASH_OUTPUT_MODE: setstreamfor live outputHOOK_CALL_TIMEOUT/HOOK_PROMPT_TIMEOUT/HOOK_PROMPT_MODEL
We recommend keeping these in .env for consistency.
- Studying Claude Code’s “agent + tools + visible queue” design in a small codebase
- Long-running, multi-step tasks where explicit state matters
- Teams that want verifiable, string-level edits over opaque refactors
- Integrating custom policy checks via hooks
If you change todo queue behavior, CLI prompts, skill activation, or tool semantics, update this README so the agent experience stays accurately documented.
Want a tour of a specific subsystem (todo queue, sessions, hooks, edit lifecycle)? Tell me which part to dive deeper on.