Skip to content

About

A context-aware, terminal-based code architect agent inspired by Claude Code. Runs locally via Ollama out of the box, with cloud API and more local model formats support on the roadmap.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

13 Commits

Folders and files

Repository files navigation

Cazagent

A context-aware terminal-living code architect agent inspired by Claude Code. Runs entirely on local hardware via Ollama — no cloud API keys required.

Cazagent ships as two complementary implementations:

Implementation Location Status Description
TypeScript Chatbot (primary) chatbot/ Active A Claude Code-style interactive terminal UI built on claude-code-kit (React + Ink).
Python CLI (legacy) legacy/ Maintenance The original single-shot CLI with sandboxed execution, persistent memory, and self-optimizing handbook.

Both share the same Ollama backend, model tiers, and routing philosophy.


Table of contents


What it does

  • Routes each request between a fast terminal-operator model (MODEL_FAST) and a heavier code-architect model (MODEL_BRAIN) using a lightweight classifier (MODEL_ROUTER).
  • Executes commands inside a restricted working directory with a dangerous-pattern blocklist, human confirmation gate, and hard timeout (Python CLI); or via tool-calling with a smart permission system (TypeScript chatbot).
  • Auto-debugs — reads command stdout/stderr/exit code and emits corrected commands in an agentic loop.
  • Persists memory across sessions in three compressed files (plan, context, history) injected into every prompt (both implementations).
  • Self-optimizes via Review Mode: when the agent fails, it analyzes the failure and rewrites its own operational handbook with a new guardrail (both implementations).
  • Ships 17 built-in tools for a full Claude Code-like agentic experience (TypeScript chatbot): file/shell (Bash, Read, Edit, Write, Glob, Grep), SubAgent delegation, parallel agents (up to 10 concurrent), task tracking (TaskCreate/Update/Get/List), web access (WebFetch, WebSearch), Jupyter notebook editing, and git worktree management.
  • Claude Code-style UI — streaming responses, tool-call cards, permission prompts, status line, and welcome screen (TypeScript chatbot).

Requirements

  • Node.js 18+ and pnpm (TypeScript chatbot)

  • Python 3.10+ (Python CLI)

  • Ollama running locally

  • The models configured in chatbot/src/config.ts or legacy/config.py:

    Constant Default model Purpose
    MODEL_ROUTER phi4-mini Classifies each prompt as FAST or BRAIN
    MODEL_FAST qwen2.5-coder:7b-instruct-q8_0 Terminal commands, git, file listing, system queries
    MODEL_BRAIN gemma-4-12B-agentic-fable5-composer2.5-v2-q6_k Code writing, refactoring, bug fixes, architecture

    Pull them via ollama pull <model>.


Installation

TypeScript chatbot

The chatbot is a pnpm workspace package that depends on the vendored claude-code-kit monorepo in lib/claude-code-kit-0.3.1.

git clone <repo-url> cazagent
cd cazagent

# Install dependencies for the library + chatbot workspace
cd lib/claude-code-kit-0.3.1
pnpm install

# Build the library packages once (generates dist/ used by the chatbot)
pnpm -r build

The chatbot's package.json references the library via workspace:* symlinks, so after pnpm install the @claude-code-kit/* packages resolve to lib/claude-code-kit-0.3.1/packages/*.

Python CLI (legacy)

git clone <repo-url> cazagent
cd cazagent
pip install -r legacy/requirements.txt

Usage

TypeScript chatbot (from source code)

Start the interactive UI from the lib/claude-code-kit-0.3.1 directory (so pnpm can resolve the workspace):

cd lib/claude-code-kit-0.3.1
pnpm --filter cazagent-chatbot start

You'll see a welcome screen, a status line at the bottom, and a prompt. Type a message and press Enter. The agent will:

  1. Route your prompt to FAST or BRAIN (if auto-router is ON).
  2. Stream the assistant's response token-by-token.
  3. Call tools as needed — 17 built-in tools across file/shell, SubAgent, parallel agents (up to 10 concurrent), task tracking, web, notebook, and git worktree. Read-only tools run automatically; write tools prompt for permission.

TypeScript chatbot (from release)

Run the precompiled binary from releases/v0.1.0/ — no install or build step required, only Node.js 18+ and a running Ollama.

cd /path/to/your/project
node /path/to/cazagent/releases/v0.1.0/cazagent.mjs

The agent operates in your current working directory, so .agent_workspace/ (the evolved handbook + memory) is created in the project you cd into — not inside the release folder. To override the working directory non-interactively, set CAZAGENT_CWD:

CAZAGENT_CWD=/path/to/your/project node /path/to/cazagent/releases/v0.1.0/cazagent.mjs

The UI, commands, status line, and model-switching behavior are identical to the from-source variant described below.

Chatbot commands

Type these in the prompt:

Command Description
/clear Clear conversation history. Type twice to confirm — the first press asks "Are you sure?", the second clears. Any other input cancels.
/model <name> Switch to a specific Ollama model. Disables auto-routing. Example: /model deepseek-coder:1.3b-instruct
/model Show the current effective model and auto-router state.
/models List all installed Ollama models (with tool-support annotation).
/router on Enable automatic FAST/BRAIN routing (default).
/router off Disable routing and use the currently selected model for all prompts.
/review [desc] Trigger Review Mode — analyze the last failure (or desc) and rewrite the handbook. Re-creates the agent with the evolved prompt.
/rollback Restore the previous handbook from instructions.bak.txt (undo a Review Mode rewrite).
/show-handbook Print the current evolved handbook to the screen.
/reset-handbook Reset the handbook to factory defaults. Type twice to confirm — same double-press flow as /clear.
/show-memory Print the plan/context/history memory files to the screen.
/reset-memory Reset memory (plan/context/history) to factory defaults. Type twice to confirm — same double-press flow as /clear.
/help Show the command list.

Note: /model <name>, /router on, and /router off all clear the conversation history (the agent is re-created with the new model/routing state).

Keyboard shortcuts:

  • Ctrl+C — cancel an in-flight response.
  • Ctrl+D — quit the chatbot.

Status line

The bottom status line reflects the current routing state. The final segment is the working directory name (WORKING_DIRECTORY_LABEL = basename(WORKING_DIRECTORY)), so it shows Cazagent only when the chatbot is launched from a directory of that name.

State Status line
Auto-route ON, before first prompt ollama · auto · <cwd-name>
Auto-route ON, tier = FAST ollama · FAST · qwen2.5-coder:7b-instruct-q8_0 · <cwd-name>
Auto-route ON, tier = BRAIN ollama · BRAIN · gemma-4-12B-... · <cwd-name>
Auto-route OFF, manual model ollama · <model> · <cwd-name>

When auto-routing is ON and no prompt has been submitted yet, no specific model is shown — the router picks one per-prompt.

How model switching works

  • Auto-router ON (default): Each prompt is classified by MODEL_ROUTER as FAST or BRAIN, and the corresponding tier model is used for that turn only.
  • /model <name>: Pins the session to a single model and turns auto-routing OFF. To return to automatic routing, run /router on.
  • /router on|off: Toggles routing without changing the selected model. Turning routing back ON resumes per-prompt classification.

Python CLI usage

# Ask a question / give a task
python legacy/main.py ask "find all large files over 100MB"

# Skip the per-command confirmation gate (autonomous loop)
python legacy/main.py ask "list files" --no-confirm

# Override the routed model (disables auto-routing)
python legacy/main.py ask "refactor this" --model gemma-4-12B-agentic-fable5-composer2.5-v2

# Run commands inside a Docker container instead of the local sandbox
python legacy/main.py ask "scan this directory" --docker

# Manual Review Mode — evolve the handbook from a known failure
python legacy/main.py review "the agent kept trying to use sudo"

# Run Review Mode with a specific model
python legacy/main.py review "looped on a bad command" --model gemma-4-12B-agentic-fable5-composer2.5-v2-q6_k

# Restore the previous handbook (undo a bad Review Mode rewrite)
python legacy/main.py rollback

# Inspect state
python legacy/main.py show-handbook
python legacy/main.py show-memory

# Reset to factory defaults
python legacy/main.py reset memory
python legacy/main.py reset handbook
python legacy/main.py reset all

At startup ask and review hit Ollama's /api/tags endpoint to confirm the server is running and the required models are installed, exiting with a friendly error (and a ollama pull hint) instead of a raw connection traceback.


Configuration

TypeScript chatbot

Edit chatbot/src/config.ts:

Constant Default Purpose
OLLAMA_BASE_URL http://localhost:11434 Ollama native API base
OLLAMA_OPENAI_BASE_URL ${OLLAMA_BASE_URL}/v1 OpenAI-compatible endpoint (consumed by OpenAIProvider)
OLLAMA_TAGS_URL ${OLLAMA_BASE_URL}/api/tags Lists installed models + capabilities
OLLAMA_GENERATE_URL ${OLLAMA_BASE_URL}/api/generate Used by the router for fast classification
MODEL_ROUTER / MODEL_FAST / MODEL_BRAIN see Requirements Ollama model names
DEFAULT_MODEL MODEL_FAST Used when auto-routing is disabled and no model is manually selected
AGENT_OPTIONS.temperature 0.1 Sampling temperature
AGENT_OPTIONS.maxTurns 20 Cap on the model→tool→feedback loop
MAX_HISTORY_ENTRIES 30 Max verbatim entries in history.md before oldest are folded into a summary
MAX_HISTORY_CHARS 8000 Max characters of history.md injected into the prompt each turn
ROUTER_PROMPT (see file) Zero-shot classifier prompt (rules + user input)
WORKING_DIRECTORY process.cwd() (override via CAZAGENT_CWD) Directory the agent operates in

Python CLI

Edit legacy/config.py:

  • MODEL_ROUTER / MODEL_FAST / MODEL_BRAIN — Ollama model names
  • OLLAMA_OPTIONS_ROUTER / OLLAMA_OPTIONS_FAST / OLLAMA_OPTIONS_BRAIN — per-tier temperature and keep_alive (how long models stay resident). BRAIN runs hotter and stays resident longer than FAST.
  • OLLAMA_TIMEOUT — HTTP timeout for Ollama API calls
  • REQUIRE_CONFIRMATION — human gate before each sandboxed command (overridable per-run with ask --no-confirm)
  • MAX_AGENT_ITERATIONS — cap on the model→execute→feedback loop
  • MAX_HISTORY_ENTRIES / MAX_HISTORY_CHARS — history.md compaction thresholds (oldest entries are folded into a summary once exceeded)
  • COMMAND_TIMEOUT — per-command execution timeout in seconds

Architecture

TypeScript chatbot

chatbot/
├── src/
│   ├── index.tsx          Entry point — render(<App/>) + ThemeProvider
│   ├── App.tsx            Root component: boot → error → chat view; commands; status line
│   ├── chat-hook.ts       useChat() — conversation state, routing, streaming, permissions
│   ├── router.ts          routePrompt() / modelForTier() — classifies prompt as FAST/BRAIN (port of router.py)
│   ├── ollama.ts          checkOllama(), listOllamaModels(), createOllamaProvider()
│   ├── system-prompt.ts   SYSTEM_PROMPT (function-call tools) + REVIEW_PROMPT (Review Mode)
│   ├── handbook.ts        Self-optimizing operational handbook + Review Mode (port of handbook.py)
│   ├── memory.ts          Filesystem-backed plan/context/history memory (port of memory.py)
│   ├── parallel-agents.ts ParallelAgents tool — up to 10 concurrent subagents via Promise.all()
│   ├── config.ts          Model + runtime configuration (port of config.py)
│   └── smoke-test.ts      Non-interactive end-to-end test
├── package.json           Workspace package (depends on @claude-code-kit/*)
├── tsconfig.json          Self-contained TS config (moduleResolution: bundler)
└── tsup.config.ts         ESM bundler config (used by `pnpm build`)

Key flows:

  1. Boot — App checks Ollama health, lists models, and picks an initial model: it prefers DEFAULT_MODEL if present (matched by name); otherwise falls back to the first tool-capable model, then the first available model. It also initializes the handbook (initHandbook()) and persistent memory (initWorkspace()), and uses loadHandbook() as the system prompt.
  2. Submit — useChat.submit() optionally routes the prompt via routePrompt(), calls agent.setModel(), prepends the compressed memory block (getCompactState()) to the user message, then iterates agent.run() (an async generator).
  3. Events — text chunks stream into the UI (with memory-update tags stripped); tool_call/tool_result render as cards; error surfaces inline; done finalizes the assistant message, applies any <plan_update>/<context_update> blocks to disk, and appends a timestamped entry to history.md. On run errors, a failure log is captured for /review.
  4. Permissions — read-only tools (Read/Glob/Grep/TaskGet/TaskList) and "always allow" tools run silently; write tools (Bash/Edit/Write/Agent/ParallelAgents/TaskCreate/TaskUpdate/NotebookEdit/EnterWorktree/ExitWorktree) surface a permission prompt. Bash commands render a command preview; Edit/Write show the target file path.

Built-in tools (17):

Category Tools Source
File & Shell Bash, Read, Edit, Write, Glob, Grep @claude-code-kit/tools
SubAgent Agent (single delegated execution) createSubagentTool()
Parallel Agents ParallelAgents (up to 10 concurrent subagents) parallel-agents.ts
Task Management TaskCreate, TaskUpdate, TaskGet, TaskList createTaskTool()
Web WebFetch (SSRF-protected), WebSearch @claude-code-kit/tools
Notebook NotebookEdit (Jupyter .ipynb) @claude-code-kit/tools
Git Worktree EnterWorktree, ExitWorktree @claude-code-kit/tools

The SubAgent and ParallelAgents tools share the same agentFactory: each spawns a new Agent with MODEL_BRAIN, the current handbook, and the basic toolset (no SubAgent/Task/ParallelAgents tools — prevents infinite recursion). The ParallelAgents tool runs all subagents concurrently via Promise.all() with a shared 5-minute timeout and abort scope. Task tools hold in-memory state via useRef, so the task list survives agent recreation (model switch, Review Mode, etc.).

Built on:

  • @claude-code-kit/agent — headless agent loop, OpenAIProvider, tool registry, permissions
  • @claude-code-kit/ui — REPL, WelcomeScreen, Spinner, StatusLine, MessageList, PermissionRequest
  • @claude-code-kit/ink-renderer — React reconciler for the terminal (Flexbox via Yoga)
  • @claude-code-kit/tools — bashTool, readTool, editTool, writeTool, globTool, grepTool, webFetchTool, webSearchTool, notebookEditTool, enterWorktreeTool, exitWorktreeTool, createSubagentTool(), createTaskTool()

Python CLI

legacy/
├── main.py        Entry point + CLI + agentic loop
├── router.py      Intent classifier (FAST vs BRAIN tier)
├── context.py     Gathers terminal/git context for the prompt
├── memory.py      Filesystem-backed plan/context/history memory
├── executor.py    Secure execution bridge (sandbox + blocklist)
├── handbook.py    Self-optimizing system prompt (Review Mode)
├── prompts.py     Prompt templates (system, router, review)
├── retry.py       Exponential-backoff retry wrapper for transient Ollama errors
├── config.py      Model + runtime configuration
├── tests/         Unit tests (test_executor, test_handbook, test_main, test_memory, test_retry)
└── requirements.txt

Runtime state lives in .agent_workspace/:

  • instructions.txt — the evolved handbook (system prompt)
  • instructions.bak.txt — previous handbook (for rollback)
  • plan.md, context.md, history.md — persistent memory
  • sandbox/ — restricted working directory for executed commands

Python → TypeScript migration map

The TypeScript chatbot ports the core routing + agent loop from Python. The following Python files have their primary functionality migrated:

Python file TypeScript replacement Status
legacy/config.py chatbot/src/config.ts Migrated (models, endpoints, router prompt)
legacy/router.py chatbot/src/router.ts Migrated (routePrompt / modelForTier)
legacy/prompts.py (system prompt) chatbot/src/system-prompt.ts Migrated (adapted for function-call tools)
legacy/main.py (agent loop) chatbot/src/App.tsx + chat-hook.ts Migrated (interactive REPL replaces single-shot CLI)
legacy/context.py — Not migrated (chatbot uses working-directory scoping instead)
legacy/memory.py chatbot/src/memory.ts Migrated (plan/context/history persistence + <plan_update>/<context_update> tag protocol + history compaction)
legacy/executor.py — Not migrated (chatbot uses @claude-code-kit/tools bashTool + permission system)
legacy/handbook.py chatbot/src/handbook.ts Migrated (Review Mode + handbook evolution; /review, /rollback, /show-handbook, /reset-handbook commands)

Testing

TypeScript chatbot

cd lib/claude-code-kit-0.3.1

# Type-check
pnpm --filter cazagent-chatbot typecheck

# Non-interactive smoke test (requires Ollama running)
pnpm --filter cazagent-chatbot exec tsx src/smoke-test.ts

The smoke test verifies tool-schema generation and end-to-end tool calling with qwen2.5:7b-instruct. Expected output ends with RESULT: PASS (tool calls executed successfully).

Python CLI

python -m unittest discover -s legacy/tests -v

Troubleshooting

"Cannot reach Ollama" at startup

Ensure Ollama is running:

ollama serve

Verify the endpoint responds:

curl http://localhost:11434/api/tags

If Ollama is on a different host, edit OLLAMA_BASE_URL in chatbot/src/config.ts or OLLAMA_URL in legacy/config.py.

"No Ollama models installed"

Pull the required models:

ollama pull phi4-mini
ollama pull qwen2.5-coder:7b-instruct-q8_0
ollama pull gemma-4-12B-agentic-fable5-composer2.5-v2-q6_k

Or list what's available:

ollama list

Model not found after /model <name>

The name must match exactly what ollama list shows (including tags like :latest or :7b-instruct-q8_0). Run /models inside the chatbot to see valid names.

Auto-router picks the wrong tier

The router is a lightweight phi4-mini model with a temperature of 0.1. If it mis-routes:

  • Run /router off and use /model <name> to pin a specific model.
  • Edit ROUTER_PROMPT in chatbot/src/config.ts to tune the classifier instructions.

VS Code shows "Could not find a declaration file for '@claude-code-kit/agent'"

This is a VS Code TS-server resolution issue. The tsc --noEmit typecheck passes correctly via pnpm's symlinks. To fix VS Code:

  1. Ensure chatbot/tsconfig.json is self-contained (does not extends the library tsconfig) — VS Code's TS server doesn't always pick up moduleResolution: "bundler" through extends.
  2. Run "TypeScript: Restart TS Server" in VS Code.
  3. If it persists, run pnpm -r build from lib/claude-code-kit-0.3.1/ to regenerate dist/*.d.ts files.

tsx runtime error: "does not provide an export named 'OpenAIProvider'"

This happens if tsconfig.json uses paths to map @claude-code-kit/* to .d.ts files — tsx respects paths and tries to import from declaration files. Keep tsconfig.json free of paths mappings; rely on pnpm's workspace:* symlinks instead.

Smoke test fails with "no tool calls"

The model may not support function calling well. The smoke test tries qwen2.5:7b-instruct first, then llama3.1:latest, then DEFAULT_MODEL. Ensure at least one tool-capable model is installed:

ollama list   # look for models with "tools" capability

Safety notes

The sandbox is not a true OS-level isolation boundary. The dangerous-pattern blocklist catches obvious foot-guns (rm -rf /, sudo, fork bombs, etc.) and commands run in a restricted working directory with sanitized environment variables. For untrusted models, swap execute_command() for a Docker backend that mounts the sandbox in a container.

In the TypeScript chatbot, write tools (Bash/Edit/Write/Agent/ParallelAgents/TaskCreate/TaskUpdate/NotebookEdit/EnterWorktree/ExitWorktree) always prompt for permission before executing. You can choose:

  • Allow once — runs this one call, prompts again next time.
  • Always allow — adds the tool to an allowlist for the session.
  • Deny — blocks the call and returns an error to the agent.

Read-only tools (Read/Glob/Grep/TaskGet/TaskList/WebFetch/WebSearch) never prompt.


License

This project is licensed under the MIT License - see the LICENSE file for details.


Credits

Built with Trae IDE — an AI-powered development environment that helped architect and refine this project.

Special thanks to:

  • claude-code-kit (MIT License, Copyright 2026 Minnzen) for the foundational agent framework and terminal UI components

  • Ollama for enabling local LLM inference

About

A context-aware, terminal-based code architect agent inspired by Claude Code. Runs locally via Ollama out of the box, with cloud API and more local model formats support on the roadmap.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages