{"slug": "maki-the-efficient-coder", "title": "Maki, the efficient coder", "summary": "Maki, a Rust-based coding agent, parses 15 languages into structural skeletons via tree-sitter, costing 59 tokens per turn while saving 224 tokens on reads, according to the project's documentation. Maki also runs a sandboxed Python interpreter where tools are async functions, and hides Datadog's MCP server's more than 100 tool definitions behind a single search tool that loads only what the model requests. The agent ships as a native binary with a 60 FPS Rust TUI, a Lua plugin API, and tree-sitter-parsed bash permissions that flag both git and rm in chained commands.", "body_md": "## Where tokens go\n\n[index](#index)\nParses 15 languages into skeletons: imports, type defs, function signatures with their line ranges.\n\nCosts 59 tok/turn, saves 224 on reads. Reads were ~65% of my tokens, so this one is big.\n\n[code_execution](#exec)\nA sandboxed Python interpreter where every tool is an `async` function.\n\nThe model gathers 50 reads, greps them, prints the 3 lines that matter. The rest never touches your context.\n\n[tool_search](https://maki.sh/docs/mcp/#tool-search)\nDatadog's MCP server has over 100 tools. Every definition sits in your context on every request, used or not.\n\nMaki hides them behind one search tool and loads what the model asks for.\n\n**task**\n\nThe model picks weak, medium, or strong for each subagent. Haiku-tier for grep-heavy research, opus-tier for architecture.\n\nYou get a summary, not the transcript.\n\n**compaction**\n\nLong sessions get compacted: images and thinking blocks go first, then old turns get summarized.\n\nThe system prompt and tool descriptions are short too.\n\n## index: read less, know more\n\nInstead of reading full files, `index` parses with tree-sitter and returns a compact skeleton.\n\nThe model sees the structure, then reads only the lines it needs.\n\n**main.rs** hover to restore\n\n```\nuse std::fs;use clap::Parser;use color_eyre::Result; #[derive(Parser)]struct Args {    paths: Vec<PathBuf>,    #[arg(short, long)]    lines: bool,} fn count_words(text: &str) -> usize {    text.split_whitespace().count()} fn count_lines(text: &str) -> usize {    text.lines().count()} fn main() -> Result<()> {    let args = Args::parse();    for path in &args.paths {        let text = fs::read_to_string(path)?;        let n = if args.lines {            count_lines(&text)        } else {            count_words(&text)        };        println!(\"{}: {n}\", path.display());    }    Ok(())}\n```\n\n**maki index main.rs** skeleton\n\n```\nimports: [1-3]\n  clap::Parser, color_eyre::Result, std::fs\n\ntypes:\n  #[derive(Parser)]\n  struct Args [5-9]\n    paths: Vec<PathBuf>\n    lines: bool\n\nfns:\n  count_words(text: &str) -> usize [11-13]\n  count_lines(text: &str) -> usize [15-17]\n  main() -> Result<()> [19-29]\n```\n\n## code_execution: think inside the sandbox\n\nTools are exposed as `async` Python functions.\n\nThe model writes a script, runs it sandboxed, and only the `print()` output enters your context.\n\n**script** python\n\n```\n# find dead exports in a TS repo\nfiles = await glob(pattern='src/**/*.ts')\nsrcs = await asyncio.gather(\n    *[read(path=f) for f in files]\n)\n\nexports = {}\nimports = set()\nfor f, src in zip(files, srcs):\n    for m in re.finditer(r'^export \\w+ (\\w+)', src, re.M):\n        exports[m.group(1)] = f\n    for m in re.finditer(r'import\\s*\\{([^}]+)\\}', src):\n        imports.update(n.strip() for n in m.group(1).split(','))\n\nfor name, f in exports.items():\n    if name not in imports:\n        print(f'{f}  {name}')\n```\n\n**output** 3 lines\n\n```\nsrc/lib/csv.ts       parseCsvLegacysrc/auth/jwt.ts      signV1src/utils/phone.ts   formatE164\n```\n\n## What you get\n\n[Lua plugins](#lua)\nExtend maki in Lua with a Neovim-style plugin API: add tools, slash commands, keymaps, and UI.\n\nAnything maki does out of the box, your plugins can do too.\n\n**Rust TUI, 60 FPS**\n\nNative binary. No javascript runtime, no react. Even the splash screen animation uses SIMD.\n\nSyntax highlighting runs on a background thread pool so it never blocks your input.\n\n**Full visibility**\n\nPhilosophy: don't hide anything. Token count, cost, and model are always in the status bar.\n\nEach subagent gets its own chat window you can flip through with `/tasks` (Ctrl-X). Ctrl-F for fuzzy search.\n\n`/btw` runs a side query without touching the current session. `!` runs shell commands, `!!` runs them silently.\n\n**Sensible permissions**\n\nBash commands are parsed with tree-sitter so maki knows what's actually being run.\n\n`git diff && rm -rf /` correctly flags both `git` and `rm`. Most agents only see `git`. Handles subshells, command substitution, pipes.\n\nPer-tool allow/deny rules, or `--yolo` to skip it all.\n\nAlso in there: parallel sessions you can switch away from, long-term memory, double-Escape to rewind, plan mode, MCP over stdio or HTTP, skills, ACP, opt-in [OpenTelemetry](https://maki.sh/docs/telemetry/), 26 themes, image paste, and `--print` for headless.\n\n## Lua plugins: hackable all the way down\n\nEvery built-in tool, `read`, `bash`, `edit`, even `batch`, is itself a Lua plugin. Read them in [`./plugins`](https://github.com/tontinton/maki/tree/main/plugins).\n\nThe [API](https://maki.sh/docs/lua-api/) mirrors Neovim (`maki.fs`, `maki.uv`, `maki.keymap`, `maki.treesitter`), so it feels familiar.\n\nDrop a file in `~/.config/maki/plugins/` to add tools, slash commands, keymaps, or UI.\n\n**add a ci_status tool: the model checks CI itself**\n\n```\nmaki.api.register_tool({\n  name = \"ci_status\",\n  description = \"Latest CI run for this branch\",\n  schema = { type = \"object\", properties = {} },\n  handler = function()\n    local res, err = maki.net.request(\n      \"https://ci.internal/runs/json?branch=main\")\n    if err then\n      return { llm_output = err, is_error = true }\n    end\n    local buf = maki.ui.buf()\n    buf:lines(maki.ui.highlight(res.body, \"json\"))\n    return { llm_output = res.body, body = buf }\n  end,\n})\n```\n\n**add /standup: show yesterday's commits**\n\n```\nmaki.api.register_command({\n  name = \"/standup\",\n  description = \"Yesterday's commits\",\n  handler = function()\n    local buf = maki.ui.buf()\n    local win = maki.ui.open_win(buf, { title = \"standup\" })\n    maki.fn.jobstart(\n      \"git log --since=yesterday --oneline\", {\n        on_stdout = function(_, line) buf:line(line) end,\n      })\n    repeat\n      local ev = win:recv()\n    until not ev or ev.key == \"esc\"\n    win:close()\n  end,\n})\n```\n\nAnd yes... it can even run DOOM!", "url": "https://wpnews.pro/news/maki-the-efficient-coder", "canonical_source": "https://maki.sh/", "published_at": "2026-09-22 06:01:28+00:00", "updated_at": "2026-09-22 06:23:58.940039+00:00", "lang": "en", "topics": ["ai-agents", "ai-tools", "developer-tools", "agent-protocols"], "entities": ["Maki", "tree-sitter", "Datadog", "MCP", "Lua", "Rust", "Neovim"], "alternates": {"html": "https://wpnews.pro/news/maki-the-efficient-coder", "markdown": "https://wpnews.pro/news/maki-the-efficient-coder.md", "text": "https://wpnews.pro/news/maki-the-efficient-coder.txt", "jsonld": "https://wpnews.pro/news/maki-the-efficient-coder.jsonld"}}