kimandClaude Sonnet 5 4e6c0bb216 Bump to 0.2.0 and make max tool-call iterations configurable
The 8-iteration-per-turn cap was hardcoded from before this session's feature work and
too tight for genuine multi-file tasks, causing "Max tool-call iterations reached" on
legitimately multi-step work. Raised the default to 25 and made it configurable via
`locode config set maxIterations <n>` / $LOCODE_MAX_ITERATIONS, mirroring the existing
contextWindow config pattern.

Also bumps the version to 0.2.0 (package.json, --version, and the MCP client's
self-reported identity) to reflect the substantial feature additions since 0.1.0.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 18:08:49 +09:00
2026-07-06 12:41:15 +09:00
2026-07-06 12:41:15 +09:00
2026-07-06 12:41:15 +09:00
2026-07-06 12:41:15 +09:00

locode

An agentic coding CLI, in the spirit of Claude Code, for models running locally via Ollama or LM Studio. It talks to either backend's OpenAI-compatible /v1/chat/completions endpoint, so any model you can serve from either one works here.

Install

npm install
npm run build
npm link   # makes the `locode` command available globally

Quick start

Make sure Ollama (ollama serve, default http://localhost:11434) or LM Studio (with a model loaded, default http://localhost:1234) is running, then:

locode --model qwen3-coder:30b

If you omit --model, locode lists the models available from the backend and lets you pick one with the arrow keys (Enter to confirm). Your saved default (via config or $LOCODE_MODEL) is pre-highlighted.

Pass --model explicitly to skip the picker entirely. Or persist your defaults so you don't need flags every time:

locode config set backend ollama
locode config set model qwen3-coder:30b
locode

List models available from the configured backend:

locode models

Every conversation is auto-saved as you go. Resume later:

locode --continue          # resume the most recent conversation
locode --resume            # pick from a list of saved conversations
locode --resume <id>       # resume a specific one
locode sessions list       # see saved conversations (id, model, title) without starting the UI
locode sessions rm <id>    # delete a saved conversation

locode can also use tools from external MCP servers:

locode mcp add my-server --command npx --arg -y --arg @some/mcp-server   # stdio server
locode mcp add my-remote --url https://example.com/mcp                   # remote (streamable HTTP) server
locode mcp list      # see configured servers (user-level + project .mcp.json)
locode mcp remove <name>

Project-level servers can also be checked into a repo via a .mcp.json file in its root:

{
  "mcpServers": {
    "my-server": { "command": "npx", "args": ["-y", "@some/mcp-server"] }
  }
}

locode connects to every configured server on startup; their tools show up alongside the built-in ones, namespaced as mcp__<server>__<tool>.

How it works

locode is a full-screen terminal app built with Ink (the same React-for-CLI framework Claude Code itself is built with) — it needs a real interactive terminal (piped/redirected input isn't supported). It takes over the terminal's alternate screen buffer (like vim/htop) — your prior scrollback is restored when you exit. The input box is always pinned to the last row of the window; the conversation fills the space above it and old messages scroll off the top as new ones arrive. Press Ctrl+C or type /exit to quit.

  • Backends: --backend ollama (default) or --backend lmstudio, or --base-url <url> for anything else that speaks the same API.
  • Tools: read_file, list_files, grep, web_search, web_fetch, git_status run automatically. write_file, edit_file, bash, and git_commit show a diff/preview in a bordered box and ask you to pick Yes / Yes-always-this-session / No with the arrow keys before running.
  • Git: git_status covers read-only inspection (status, diff, log, show, branches) and runs automatically. git_commit covers add, commit, create_branch, checkout, and push — each shows the actual diff/status/commits it's about to affect before you confirm (e.g. a commit's preview is the staged diff plus the message, a push's preview is the list of commits it would send).
  • Sub-agents: the agent tool lets the model delegate a self-contained task to a fresh, isolated tool loop (same tools, minus agent itself — no nested sub-agents) and get back only the final answer, keeping the main conversation's context focused. It shows up as a single ⏺ Agent(description) / ⎿ Sub-agent finished (...) line — the sub-agent's own intermediate steps aren't displayed. Any mutating tool calls it makes still go through the same permission prompts as the main conversation.
  • MCP servers: locode connects to any MCP servers configured via locode mcp add or a project's .mcp.json (stdio and remote/streamable-HTTP transports), and adds their tools to every session, namespaced as mcp__<server>__<tool>. A server's tool is treated as mutating (confirmation required) unless it declares itself read-only via the MCP readOnlyHint annotation. One misconfigured server doesn't block the others — check /mcp for per-server connection status.
  • Tool-calling mode: on connect, locode probes whether the model reliably uses native OpenAI-style function calling. If not, it switches to a prompt-based fallback mode where the model is instructed to emit tool calls as fenced ```tool_call ``` JSON blocks, which locode parses itself. The result is cached per backend+model so future sessions skip the probe. Override with --tool-mode native|fallback|auto or the in-session /mode command.
  • Context tracking & compaction: the status bar shows ctx NN% — context window usage, from real usage.prompt_tokens when the backend reports it (requested via stream_options.include_usage), or a ~-prefixed char-based estimate otherwise. The window size itself is auto-detected (Ollama's /api/show, then LM Studio's /api/v0/models) and cached per backend+model; falls back to a configurable default (locode config set contextWindow <n>, or $LOCODE_CONTEXT_WINDOW) if neither responds. At 85% usage, locode automatically asks the model to summarize the conversation and replaces the history with that summary (a notice tells you when this happens) — or trigger it yourself anytime with /compact.

Note: even models with genuine native tool-calling support occasionally emit a tool call as plain text instead of a real structured call — this is model sampling variance, not a bug. If a turn seems to "describe" a tool call instead of running it, just ask again or try /mode fallback.

Slash commands

/model <name>     switch the model used for the current backend
/backend <name>   switch backend (ollama | lmstudio), keeps current model
/mode <name>      view or force tool-call mode (native | fallback)
/status           show current model, backend, tool-call mode, and cwd
/tools            list available tools
/permissions      list mutating tools allowed for the rest of this session
/sessions         list saved conversations you can resume with --resume
/mcp              show connected MCP servers and their tool counts
/compact          summarize the conversation now to free up context
/clear            clear conversation history
/help             show this help
/exit, /quit      exit

Config

Config precedence: CLI flags > env vars (LOCODE_BACKEND, LOCODE_MODEL, LOCODE_BASE_URL, LOCODE_CONTEXT_WINDOW, LOCODE_MAX_ITERATIONS) > persisted config file > defaults.

locode config set backend ollama
locode config set model qwen3-coder:30b
locode config set contextWindow 32768   # fallback size when auto-detection fails
locode config set maxIterations 40      # max tool calls per turn before locode gives up (default 25)
locode config get
locode config path

Known limitations

  • Requires a real interactive terminal (TTY) — you can't pipe input into it or run it from a non-interactive script.
  • Native tool-calling reliability varies by model and is non-deterministic even for capable models (see above).
  • No sandboxing beyond the confirmation prompts — mutating tools operate on the real filesystem/shell with the permissions of the user running locode. Only approve commands you understand.
  • Session resume replays prior user/assistant text so you can see it, but it doesn't re-display prior tool-call/tool-result lines from before the resume (the model still has that history — it's just not re-rendered).
  • No in-app scrollback — once a message scrolls off the top of the window it's gone until you resize the terminal taller (the conversation itself is still intact and sent to the model; this only affects what you can visually re-read).
  • Windows shell quoting for the bash tool has only had light testing; behavior may differ from Unix shells for complex quoting.
  • git_commit covers add/commit/create_branch/checkout/push only — no reset, stash, merge, rebase, or branch deletion. Use bash for anything beyond that.
  • MCP tool results only support text content — image/audio/resource content blocks are shown as a placeholder note rather than rendered. Remote (HTTP) MCP servers support static headers (e.g. a bearer token) but not OAuth flows.
  • Compaction (/compact or automatic at 85%) replaces history with a model-generated prose summary — it costs one extra model call and loses tool-call/tool-result detail (the model's own account of what happened survives; the raw record doesn't). The 85% threshold isn't currently configurable.
S
Description
No description provided
Readme
1.1 MiB
Languages
TypeScript 100%