miii-agent
v3.2.0
Published
Local AI coding agent for your terminal — an open-source, offline alternative to Claude Code, Cursor, and GitHub Copilot, powered by Ollama. Private by default, free forever.
Downloads
1,316
Maintainers
Readme
Install
ollama pull qwen2.5-coder:14b # any coding model works
curl -fsSL https://raw.githubusercontent.com/maruakshay/miii-cli/main/install.sh | sh
miiiWindows: irm https://raw.githubusercontent.com/maruakshay/miii-cli/main/install.ps1 | iex · any platform: npm i -g miii-agent · needs Node ≥ 18 and Ollama.
Then just talk to it
> refactor the auth module to use async/await
> @src/server.ts add rate limiting to all POST routes
> why are my tests failing in utils/parser.tsmiii reads your files, writes the code, runs your tests, and fixes what breaks — planning before it acts, and verifying after. Entirely on your own GPU.
Why local-first?
| | Cloud agents | miii |
|------------|-----------------------|------------------------------|
| Your code | Sent to a third party | Never leaves your machine |
| Cost | Per-token billing | Free — runs on your hardware |
| Setup | API keys, accounts | npm i -g miii-agent |
| Offline | No | Yes |
| Latency | Network + queue | Your GPU only |
Features
- 🧠 Works with small models — miii repairs the malformed tool calls a 7B model emits instead of burning a turn on each one, and sizes its own prompt to your context window so the room goes to your code.
- 🧪
miii doctor— not every local model can drive an agent. Grades your installed models on real engineering tasks. - 🖼️ Paste images —
Ctrl+Va screenshot to ask why a UI looks broken. Needs a vision model (llava,llama3.2-vision, …). - 💧 Lossless output spill — a 50K-line test log is never truncated. The full text goes to disk and the model pages through it.
- 📋 Plan mode —
shift+tab(or/plan) makes the session read-only. miii researches your code, proposes a plan, and touches nothing until you approve it. The block is enforced by the harness, not asked for in the prompt: with no write tools and only reporting commands, a model that triessed -iorcat > fileanyway gets refused. - 🔒 Permission-gated tools — you approve what the agent touches, and see the exact rule before you save it. A saved wildcard never stretches across a command boundary, so approving
npm testcan't quietly authorizenpm test && rm -rf ~. - ⌨️ Your own slash commands — drop
review.mdin.miii/commands/and/reviewis a command, in the palette, checked into the repo with everything else. - 📄
MIII.md— drop one in your repo to teach miii your conventions and commands. Same idea asCLAUDE.md, read every turn.
Picking a model: 8GB VRAM → qwen2.5-coder:7b · 16–24GB → qwen2.5-coder:14b (sweet spot) · 48GB+ → qwen2.5-coder:32b.
| Tool | Function |
|------|----------|
| read_file | Read any file in your workspace |
| write_file | Create new files |
| edit_file | Precise string-level edits, whitespace-tolerant |
| glob | Pattern-match files across the project |
| grep | Regex search across files |
| run_bash | Execute shell commands |
| write_todos | Track multi-step work as a live checklist |
File tools (read_file, write_file, edit_file) reject ../ traversal and absolute paths outside the workspace. run_bash is not path-confined — its only boundary is the permission prompt, so review commands before approving.
Answering "always" saves both the exact command and a generalized glob (npm run build → npm run *), and the prompt shows you the widest rule before you choose.
Two things are never widened: destructive programs (rm, dd, sudo, git reset, …) and compound commands, whose first token says nothing about what the rest of the line does. A saved glob also refuses to match any command containing an unquoted ; && || | > or $(…), so an approval can't be stretched past the command you actually read.
Saved rules live in .miii/permissions.json in the project — that is what "always" writes to. Approval subjects are usually project-relative (src/index.ts means a different file in every repo), so a rule that followed you everywhere would be granting far more than you agreed to. Rules in ~/.miii/permissions.json apply in every project; put the ones you really do mean globally there by hand. /permissions lists both and says which file each came from.
Gitignore .miii/permissions.json — it is a record of what you approved. .miii/commands/ is meant to be committed.
shift+tab cycles the mode; the input frame changes colour with it.
| Mode | What it does | |------|--------------| | normal | asks before writing files or running commands | | plan mode | read-only — research and a plan, approved before anything happens | | auto-accept edits | writes files without asking; commands still prompt, since a command can reach outside the workspace | | bypass permissions | runs everything without asking (red frame — for a sandbox or a throwaway tree) |
In plan mode the write tools are not offered at all and run_bash runs only commands that report — ls, cat, grep, find, git status/log/diff, one at a time, no pipes or &&. A compound command is refused however harmless its first word, because ls tells you nothing about what comes after the &&. When the research is done miii calls exit_plan_mode with the plan and you get three choices: start work, start work and stop asking about the edits, or send it back for another pass.
A Markdown file is a command. .miii/commands/review.md becomes /review:
---
description: review the staged diff
---
Review the staged diff for bugs and unhandled errors. Focus on $ARGUMENTS.$ARGUMENTS is everything typed after the command; $1…$9 are its individual words. A command that references neither gets the arguments appended, so nothing you type is silently dropped.
.miii/commands/ is project scope — check it in, and the whole team gets it. ~/.miii/commands/ is yours in every project. A project command shadows a personal one of the same name, and neither can shadow a built-in.
| Key | Action |
|-----|--------|
| Enter | Send prompt |
| / | Open the command palette |
| Shift+Tab | Cycle permission mode — normal → plan → auto-accept → bypass |
| @filename | Attach file to context |
| Ctrl+V | Paste clipboard image (needs a vision model) |
| Ctrl+T | Toggle the model's thinking |
| Ctrl+O / left click | Toggle full tool output |
| Mouse wheel | Scroll the transcript |
| PgUp / PgDn | Scroll the transcript a page at a time |
| Shift+↑ / Shift+↓ | Scroll the transcript a row at a time |
| Ctrl+A / Ctrl+E | Jump to start / end of line |
| Esc | Stop generation or tool run |
| Ctrl+Y | Copy the last reply to the clipboard |
| Ctrl+S | Hand the mouse back to the terminal, so a drag selects text |
| Ctrl+C | Quit |
| Command | Action |
|---------|--------|
| /plan | Toggle plan mode — research read-only, then approve the plan |
| /permissions | List saved approval rules and which file each lives in |
| /models | Switch model, provider (tab) and effort (←→) |
| /provider | Pick a configured provider |
| /new | Save this session and start fresh |
| /sessions | List and resume a saved session |
| /copy | Copy to the clipboard — last (default), code, tool or all |
| /compact | Summarize the conversation to free context — /compact <focus> to steer it |
| /clear | Reset conversation |
| /exit | Quit |
Settings live in ~/.miii/config.json, created on first run:
{
"model": "qwen2.5-coder:14b",
"effort": "medium",
"providers": {
"ollama": { "type": "ollama", "baseUrl": "http://localhost:11434" }
}
}effort (low | medium | high) controls temperature and the output token cap. numCtxCap (default 16384) bounds the context window miii asks for, so a model advertising a 131k window can't make Ollama size a KV cache that eats your RAM — it only ever lowers, never raises. A top-level ollamaHost still works and is folded into the ollama provider on load.
miii talks to any OpenAI-compatible local server too — llama.cpp, LM Studio, vLLM:
{
"model": "qwen2.5-coder-14b",
"provider": "llamacpp",
"providers": {
"llamacpp": { "type": "openai", "baseUrl": "http://localhost:8080" }
}
}Switch at launch with miii --provider llamacpp. Any openai-type provider on localhost counts as local — no key, no cloud.
Updates: miii checks npm on launch and pulls a newer release in the background, applied on next start. miii update to do it now, miii --version to check. Opt out with "autoUpdate": false.
Install failing on permissions? Your global npm prefix isn't writable:
npm config set prefix "$HOME/.npm-global"
export PATH="$HOME/.npm-global/bin:$PATH" # add to ~/.bashrc or ~/.zshrcWhen a tool result exceeds the inline budget (~10K bytes), the full output is written to ~/.miii/output/<id>.txt. Only a head + tail preview is inlined, with a pointer:
[This command output was long (412900 bytes), so I'm showing the start and
end. The full text is saved at ~/.miii/output/9f3a1c.txt — read it with
read_file offset/limit to see the middle.]The model pages through the middle with ranged read_file reads. Spill files are garbage-collected after 24 hours.
src/
├── agent/ # The core reasoning loop, and tool-call repair
├── tools/ # read/write/edit/bash/grep/glob/todos + output spill
├── prompt/ # System prompt and MIII.md project context
├── permissions/ # Approval rules, modes, and how they're scoped
├── commands/ # User-defined slash commands (.miii/commands/*.md)
├── llm/ # Ollama and OpenAI-compatible backends
├── session/ # Saved conversations
├── ui/ # Ink terminal UI and input handling
└── config.ts # Settings and provider resolutiongit clone https://github.com/maruakshay/miii-cli.git && cd miii-cli
npm install && npm run devnpm run build # production build
npm run typecheck # type-check src + eval
npm test # unit tests
npm run eval # regression gate (powers `miii doctor`)To run your working tree as the global miii: npm run build && npm link (restore with npm i -g miii-agent).
FAQ
Does miii work without internet? Yes. Once you've pulled a model with Ollama, miii runs fully offline — no network calls, no account, no cloud.
Is my code sent anywhere? No. Every file read, edit, and inference happens on your machine — privacy is the default, not a setting.
How is miii different from Claude Code, Cursor, or GitHub Copilot? Those are cloud services — metered, account-gated, and they ship your code to a third-party server. miii is open-source, free, and runs entirely on your hardware, with the same terminal-agent workflow.
How is it different from Continue.dev? Continue.dev is an IDE extension. miii is a standalone terminal agent — no editor required.
Which local LLM is best for coding? qwen2.5-coder at the largest size your VRAM allows. Run miii doctor to grade what you have installed.
Do I need a GPU? No, but it helps. Smaller models run on CPU; a GPU makes larger ones fast enough for real work.
Status
MVP. The core agent loop is stable; actively refining tool execution, streaming, and the permission model. PRs welcome.
License
MIT © maruakshay
