100 % local agentic coding harness for Qwen 3.5 9B via Ollama — no cloud API, no per-token billing, fully owned source code.
This README covers installation and everyday usage. For the project's motivation, architecture choices, and small-model reliability engineering, see the full reference document: DOCUMENTATION.md. For a complete list of commands and keyboard shortcuts, see HELP.md.
- Node.js ≥ 22
- Ollama installed and running (see below)
- The target model pulled:
ollama pull qwen3.5
Ollama is the local model server that runs Qwen 3.5 on your machine.
macOS
# Option A: download the app from https://ollama.com/download and drag it to Applications
# Option B: Homebrew
brew install ollamaLinux
curl -fsSL https://ollama.com/install.sh | shWindows
Download and run the installer from ollama.com/download.
-
Start the server (the macOS/Windows desktop app starts it automatically; otherwise run it yourself):
ollama serve
-
Verify it is reachable — the harness talks to Ollama over HTTP on
http://localhost:11434by default:curl -s http://localhost:11434/api/version # → {"version":"..."} means the server is up -
Pull the model:
ollama pull qwen3.5
-
Check it is available:
ollama list # models on disk ollama ps # models currently loaded in memory
If Ollama runs on another machine or port, point the harness at it with --host <url> (or the host key in the config file). A quick reference of useful Ollama commands lives in HELP.md.
Clone the repo and install its dependencies (there is no build step — the project runs directly from the TypeScript sources via tsx):
git clone https://github.com/Tromset/Ollama-Code.git ollama-code
cd ollama-code
npm installThen make ollama-code available as a global terminal command:
npm linknpm link creates a symlink to ollama-code in your active Node's global bin directory (already on your PATH, no sudo needed). From now on, typing ollama-code in any directory launches the tool against that directory:
ollama-codeVerify it resolved:
which ollama-code # prints the path to the linked command
ollama-code --help # prints usageAlternatives.
npm install -g .installs a copy instead of a live symlink (rerun it after pulling updates). Or skip the global command entirely and runnpm startfrom inside the repository.
Under the hood, bin/ollama-code.js resolves tsx from the package's own node_modules and points explicitly at its own tsconfig.json (rather than letting tsx resolve one from the current directory) — so the command works correctly even when invoked from outside the repository.
Once linked, from anywhere:
ollama-codeOr, without linking, from inside the repository:
npm startollama-code Launch the TUI (interactive)
ollama-code [options]
Options:
--model <name> Ollama model (default: qwen3.5:latest)
--mode <mode> Agent mode: code | chat | vision | plan (default: code)
--num-ctx <n> Context window size (default: 32768)
--host <url> Ollama host (default: http://localhost:11434)
--permission <mode> Permission mode: plan | normal | yolo (default: normal)
--yolo Shorthand for --permission yolo (allow all except hard denies)
--plan-perms Shorthand for --permission plan (read-only)
--help, -h Show help
Examples:
ollama-code
ollama-code --mode plan --model qwen3.5:latest
npm run smoke Quick streaming smoke test, no TUI
--mode plan (the agent mode) and --plan-perms (the permission engine) are two independent settings: --mode plan changes the system prompt and restricts the exposed tools, while --plan-perms forces the permission engine into read-only regardless of the agent mode. Nothing synchronizes them automatically — combine both for the strongest guarantee during investigation.
| Mode | Exposed tools | Purpose |
|---|---|---|
code |
all 7 | full agentic coding |
vision |
3 read-only (read_file, list_files, search) |
describe/analyze images + project context |
plan |
3 read-only | investigate and propose a plan, never write |
chat |
none | plain conversation |
think (visible reasoning) is not automatically derived from the mode chosen at launch: it defaults to true for all four modes as long as no explicit value is provided (CLI/config). Only a mode change during a session via /mode forces it to false for chat/vision/plan (true only for code).
Details, guardrails, and diagrams: see DOCUMENTATION.md, "Agent modes" section.
| Command | Purpose |
|---|---|
/mode [code|chat|vision|plan] |
show or change the agent mode |
/model [name] |
pick from installed models (no arg opens an interactive picker), or set one directly |
/image <path> |
attach an image to the next message |
/clear |
clear the displayed conversation history |
/sessions |
list saved sessions (first 20) |
/permissions |
show the current permission configuration |
/help |
list commands |
Keyboard shortcuts: Enter send · Ctrl+C or Cmd+J abort the current turn (without quitting) · Ctrl+D quit · Cmd+R or Esc clear the input line · Cmd+L expand/collapse the live thinking block · y/n/a answer a permission prompt (a = always allow this exact action). Cmd combos need a terminal speaking the kitty keyboard protocol (kitty, Ghostty, WezTerm — auto-detected); elsewhere press Option+J/R/L with the terminal's "Option as Meta/Esc+" setting enabled. The full list lives in HELP.md.
| Tool | Purpose | Guardrails |
|---|---|---|
read_file |
read a file | confined to the cwd, refuses .env |
write_file |
create/overwrite | same + creates parent directories |
edit_file |
{path, old, new} replacement with progressive matching (exact → whitespace → fuzzy) |
actionable error if no unique match |
move_file |
move/rename | both paths validated |
list_files |
list by glob | skips node_modules/.git/dist, capped at 500 files |
search |
grep contents | ripgrep if available (30 s timeout), JS fallback otherwise; capped at 200 results |
bash |
shell command | 120 s default timeout, project cwd, output (stdout+stderr) truncated at 20,000 characters |
search and list_files are not protected against exposing .env files as reliably as the four file tools — see the permissions section of DOCUMENTATION.md before using this on a repository containing real secrets.
Merged with increasing precedence (no error if a file is missing):
built-in defaults ← ~/.ollama-code/config.json ← ./.ollama-code.json ← CLI options
Defaults: model qwen3.5:latest, host http://localhost:11434, numCtx 32768, maxTurns 25, sampling {temperature:1, top_p:0.95, top_k:20, presence_penalty:1.5}, think: true in code mode, permissions {mode:'normal', rules:[]}.
Sessions and the training log (finetune.jsonl) are stored in ~/.ollama-code/sessions/.
| Script | Command | Purpose |
|---|---|---|
npm start |
tsx src/index.ts |
launch the TUI |
npm run dev |
tsx watch src/index.ts |
dev with reload |
npm run typecheck |
tsc --noEmit |
type checking |
npm test |
vitest run |
unit tests |
npm run test:watch |
vitest |
tests in watch mode |
npm run smoke |
tsx scripts/smoke.ts |
streaming smoke test (no TUI) |
bin/ollama-code.js global CLI entry point (tsx wrapper)
src/index.ts argument parsing, TUI launch
src/core/ headless core: agent, Ollama client, config, context, permissions, prompts, sessions, types
src/tools/ the 7 tools + registry (validation/dispatch)
src/tui/ Ink TUI (App, slash commands, components)
src/media/ image utilities (base64, resize)
assets/ logo
scripts/smoke.ts quick streaming smoke test
docs/CONTRACTS.md TypeScript interfaces between modules (build specification)
docs/RUNTIME_API.md verified library surface (build specification)
npm test # vitest run
npm run typecheck # tsc --noEmit
npm run smoke # checks the Ollama connection + one streaming round-tripTo date, only the edit_file logic (progressive matching, src/tools/fs.ts) has unit tests (src/tools/fs.test.ts, 7 cases). The other tools, the registry, and the whole TUI/CLI layer have no automated coverage yet.
The core (client, config, permissions, context, sessions, 7 tools), the agent loop (src/core/agent.ts), and the TUI (src/tui/* + src/index.ts + bin/ollama-code.js) are implemented — the project is usable end to end. Full details, known limitations, and roadmap (test coverage, LoRA fine-tuning, web UI, video/audio multimodal): see DOCUMENTATION.md.
- HELP.md — every command and keyboard shortcut in one place.
- DOCUMENTATION.md — full reference document: motivation, architecture, small-model reliability engineering, risks and limitations.
- docs/CONTRACTS.md — TypeScript interfaces between modules (specification written before implementation).
- docs/RUNTIME_API.md — verified library surface (ollama-js, zod, ink) and per-file export contracts.