Metadata-Version: 2.4
Name: kodiqa
Version: 3.39.0
Summary: AI coding agent that runs anywhere — 8 cloud providers plus local Ollama, 33 tools, skills, writing sub-agents, background commands, plugins, sub-agents, LSP, themes, RAG, 88 commands
Author: Kodiqa-Solutions
License: AGPL-3.0-only
Project-URL: Homepage, https://github.com/Kodiqa-Solutions/Kodiqa-agent
Project-URL: Repository, https://github.com/Kodiqa-Solutions/Kodiqa-agent
Project-URL: Issues, https://github.com/Kodiqa-Solutions/Kodiqa-agent/issues
Project-URL: Changelog, https://github.com/Kodiqa-Solutions/Kodiqa-agent/blob/main/CHANGELOG.md
Keywords: ai,coding-agent,llm,ollama,claude,openai,deepseek,groq,mistral,qwen,openrouter,venice,cli,developer-tools,code-assistant,mcp
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: GNU Affero General Public License v3
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: rich>=13.0
Requires-Dist: beautifulsoup4>=4.12
Requires-Dist: requests>=2.31
Requires-Dist: prompt_toolkit>=3.0
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Dynamic: license-file

<h1 align="center">Kodiqa</h1>

<p align="center">
  <strong>The AI coding agent that runs anywhere — free locally with Ollama, or supercharged by 8 cloud APIs. One agent, every model, zero limits.</strong>
</p>

<p align="center">
  <em>88 slash commands &bull; 33 tools &bull; lazy MCP tools &bull; RAG search &bull; custom personas &bull; plugins &bull; sub-agents &bull; LSP &bull; 5 themes</em>
</p>

<p align="center">
  <a href="#install"><img src="https://img.shields.io/badge/python-3.11+-blue?logo=python&logoColor=white" alt="Python 3.11+"/></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/license-AGPL--3.0-purple" alt="License"/></a>
  <a href="#testing"><img src="https://img.shields.io/badge/tests-1487%20passing-brightgreen" alt="Tests"/></a>
  <a href="#api-setup"><img src="https://img.shields.io/badge/providers-8-cyan" alt="8 Providers"/></a>
  <a href="#33-tools"><img src="https://img.shields.io/badge/commands-88-orange" alt="88 Commands"/></a>
  <a href="https://pypi.org/project/kodiqa/"><img src="https://img.shields.io/pypi/v/kodiqa?color=blue" alt="PyPI"/></a>
</p>

<!-- The source repository is private, so images and badges served from it render
     broken on the PyPI page — the logo, the demo GIFs, and the GitHub stars /
     last-commit / code-size / CI badges were removed for that reason. Restore them
     if the repository is ever made public, or point them at a public host. -->

---

## How Kodiqa Compares

Every cell below was checked against each vendor's own documentation in September 2026.
Where a vendor doesn't publish something, the cell says "Not documented" instead of guessing.

| Feature | Kodiqa | Claude Code | Aider | Gemini CLI | OpenCode |
|---------|--------|-------------|-------|------------|----------|
| **Open source** | Yes (AGPL-3.0) | No — proprietary | Yes (Apache-2.0) | Yes (Apache-2.0) | Yes (MIT) |
| **Language** | Python | TypeScript | Python | TypeScript | TypeScript |
| **Install** | `pip install kodiqa` | install script, Homebrew, WinGet | `pip install aider-install` | `npm i -g @google/gemini-cli` | install script, npm, Homebrew |
| **Price** | Free with Ollama, or pay-per-token | $20/mo Pro, from $100/mo Max, or API pay-per-token | Pay-per-token, bring your own key | Free tier: 60 req/min, 1,000 req/day | Pay-per-token, or sign in with an existing ChatGPT Plus/Pro or GitHub Copilot plan |
| **Runs fully offline** | Yes — Ollama, with managed start/stop | No | Yes — Ollama, LM Studio | No | Yes — Ollama |
| **Model providers** | 9 — 8 cloud plus local Ollama | Anthropic, plus Bedrock, Vertex and third-party | "Almost any LLM" — 18+ named | Google Gemini | 75+ via Models.dev |
| **Built-in tools** | 33 | 45+ | Not tool-based — uses edit formats | 8 | 13 |
| **MCP** | Yes — local, remote, OAuth | Yes | Not documented | Yes | Yes |
| **On-demand tool loading** | Yes — lazy MCP, ~94% fewer schema tokens | Yes — deferred tools via `ToolSearch` | No | No | No |
| **OpenAPI / GraphQL endpoints as tools** | Yes | Not documented | Not documented | Not documented | Not documented |
| **Multi-model consensus** | Yes | No | No | No | No |
| **Cross-provider failover** | Yes (`/failover`) | No | No | No | No |
| **Sub-agents** | Yes — research, plus writers that work in a git worktree and hand back a diff; your own in `.kodiqa/agents/` | Yes | No | Not documented | Yes — 3 built-in plus custom |
| **Plan mode** | Yes | Yes | Architect mode | Not documented | Yes |
| **Permissions** | 3 modes, plus allow/ask/deny rules per tool and pattern | allow/ask/deny rules plus permission modes | Confirms each edit | Yes, plus sandbox | allow/ask/deny, per tool and per glob |
| **Undo** | 10 levels per file, plus `/rewind` | `/rewind` and checkpoints | `/undo`, git-based | Checkpointing | `/undo` and `/redo` |
| **Auto git commit** | Yes (`/autocommit`) | On request | Yes, on by default | No | Not documented |
| **Auto-lint after edits** | Yes (`/lint`) | Via hooks | Yes, built-in | No | Not documented |
| **Web search** | Yes — 3 engines | Yes | No | Yes — Google grounding | Yes |
| **Persistent memory** | Yes — SQLite | Yes — CLAUDE.md plus auto memory | Conventions file | Yes — GEMINI.md plus `save_memory` | AGENTS.md |
| **RAG over your codebase** | Yes (`/embed`, `/rag`) | No | No | No | No |
| **Conversation branching** | Yes (`/branch`) | No | No | No | No |
| **Per-session budget cap** | Yes (`/budget`) | No | No | No | Workspace and monthly limits in Zen |
| **Batch edit review** | Yes — accept/reject per file | No | No | No | No |
| **Auto model discovery** | Yes — live from provider APIs | No | No | No | Via Models.dev |
| **CI bot (GitHub / GitLab)** | Yes — GitHub ([`/kq` in comments](#github-bot)) | Yes | No | Yes — GitHub | Yes |
| **Desktop app / IDE** | Editor bridge (`--serve`) | VS Code, JetBrains, desktop, web, mobile | Browser UI | No | Desktop app plus IDE extension |
| **Shareable session link** | No | No | No | No | Yes (`/share`) |

**Where Kodiqa stands alone.** Multi-model consensus, cross-provider failover, OpenAPI and GraphQL
endpoints as callable tools, conversation branching, a per-session spend cap, batch edit review, and
RAG over your own codebase. No other agent in this table ships all of them, and most ship none of them.

**Where Kodiqa is behind.** There is no desktop app and no shareable session links, and the CI bot covers GitHub only.
Those are roadmap items, not shipped features.

## Install

```bash
pip install kodiqa
kodiqa
```

Requires Python 3.11 or newer. `python -m kodiqa` works too.

## Features

- **Claude Code-style UI** — `❯` prompt with separator line (prompt_toolkit), arrow-key navigation for all prompts
- **33 tools** — file ops, git, search, web, memory, clipboard, multi-edit, undo, diff apply, live task list, background commands, skills, `explore` to delegate research and `delegate` to hand a change to a sub-agent in an isolated worktree
- **9 API providers** — Ollama (local/free), Claude, OpenAI, DeepSeek, Groq, Mistral, Qwen, OpenRouter, Venice (hundreds of models)
- **Editor/IDE bridge** — `kodiqa --serve` exposes a local HTTP API (`/ask`, `/diagnostics`) for VS Code/Zed/Neovim extensions
- **Cross-provider failover** — if a provider is down/rate-limited, the turn auto-retries on the next configured provider and continues (`/failover`)
- **TOON output** — `/toon` re-encodes JSON tool results into a compact tabular form (~60% fewer tokens on large arrays)
- **Custom commands** — drop `.kodiqa/commands/<name>.md` and run it as `/<name>` (with `$ARGUMENTS`/`$1` substitution); `/commands` lists them
- **Skills** — `.kodiqa/skills/<name>/SKILL.md` instructions the model loads by itself when a task matches their description; `/skills` lists them
- **MCP server support** — connect external tool servers via Model Context Protocol
- **Lazy MCP tools** — large MCP servers are discovered on demand (`mcp_search` / `mcp_call`) instead of injecting every tool schema each turn — ~94% fewer tool-schema tokens (`/mcp lazy`)
- **Auto model discovery** — new Claude/Qwen models appear automatically from APIs
- **Interactive pickers** — `/model` and `/key` show numbered menus, navigate with arrows
- **Tab autocomplete** — slash commands, model names, file paths (prompt_toolkit)
- **Compact streaming** — hides code output, shows progress instead (toggle with `/verbose`)
- **Stream interrupt** — press Esc or Ctrl+C to stop any response instantly
- **Stream stall indicator** — animated spinner when response pauses (so you know it's still working)
- **Thinking display** — shows spinner for `<think>` reasoning blocks, line count summary
- **Multi-model consensus** — query all models, merge best answers
- **3 permission modes** — default (confirm all), relaxed (auto file ops), auto (no confirms)
- **Plan mode** — AI explores + plans, you approve, then it implements
- **Batch edit review** — queue edits, accept/reject per file with arrow keys
- **Context window management** — warns at 70%, auto-compacts at 85%, visual progress bar
- **Conversation branching** — save/switch between conversation states
- **Token tracking** — cost per response, session totals, tok/s speed
- **Prompt caching** — Claude API cache for faster + cheaper responses
- **Auto-retry** — exponential backoff on API errors (429, 5xx, timeouts)
- **Undo / redo / rewind** — per-file undo (up to 10 levels) with `/redo`, plus `/rewind` to revert ALL file changes from the last turn(s)
- **Checkpoints** — save/restore conversation state
- **Session export** — export conversation to markdown
- **Git-aware context** — auto-detects git repo, includes diff stats
- **Project indexing** — symbol extraction (def/class/function), cached
- **Shell env detection** — auto-detects OS, shell, dev tools
- **Diff preview** — colored diff before every file write/edit
- **Parallel tools** — read-only operations run concurrently
- **Session summary** — auto-saves context summary on quit, loaded on next start
- **Conversation recovery** — auto-saved sessions, resume on crash or with `kodiqa -c` / `--resume`
- **Workspace boundary** — asks permission before accessing files outside working directory
- **Smart Ollama lifecycle** — starts on launch, stops when switching to cloud, restarts on local switch
- **Dynamic model library** — scrapes ollama.com/library on every launch (never a baked-in list) with pull counts, download sizes, and whether the model fits your RAM
- **Unlimited iterations** — no artificial cap, AI keeps working until the task is done
- **Live API model routing** — auto-discovered models from Claude/Qwen APIs routed to correct provider
- **Auto git commit** — toggle with `/autocommit`, auto-commits after AI edits with descriptive message
- **`.kodiqaignore`** — per-project exclusion for scans and searches: file names (`secrets.txt`, `.env`), globs (`creds_*.json`), extensions (`*.log`) and directories (`node_modules/`)
- **Budget limit** — `/budget 5` sets $5 session limit, warns at 80%, blocks at 100%
- **Auto-lint** — `/lint ruff check --fix` runs linter after edits, feeds errors back to AI
- **Custom personas** — `/persona` switches AI expertise (security-expert, code-reviewer, teacher, architect, debugger)
- **RAG search** — `/embed` indexes codebase, `/rag` searches with AI-enhanced context
- **Test generation** — `/test <file>` auto-generates unit tests
- **Git diff review** — `/review-local` AI reviews staged changes
- **Interactive debugger** — `/debug <script>` runs, catches errors, debugs with AI
- **Diagram generation** — `/diagram` generates Mermaid diagrams via AI
- **File watcher** — `/watch <path>` monitors for changes
- **Config profiles** — `/profile save/load` manages settings presets
- **Multi-file refactoring** — `/refactor rename/extract` across project
- **Session history** — `/history` browses and resumes past sessions
- **Clipboard patches** — `/patch` applies diffs from clipboard
- **Changelog** — `/changelog` shows version history
- **Session stats** — `/stats` shows metrics (files, tools, time, cost)
- **1487 tests** — pytest test suite, all passing

## Arrow-Key UI

All interactive prompts use arrow keys — no typing letters:

```
  Allow: Write file: ~/project/app.py
    ❯ Yes
      Yes, don't ask again — for this action type
      No
```

Navigate with **↑↓ arrows** or **j/k**, press **Enter** to select, or **1/2/3** to jump.

Prompt uses a separator line (like Claude Code):
```
────────────────────────────────────────
❯ your prompt here
```

## Slash Commands

| Command | What it does |
|---------|-------------|
| `/model <name>` | Switch model (interactive picker if no arg) |
| `/models` | List all available models (with live API discovery) |
| `/multi <models>` | Multi-model consensus mode |
| `/single` | Back to single model |
| `/scan [path]` | Scan project into context (with symbol extraction) |
| `/clear` | Clear conversation history |
| `/compact` | Summarize conversation to save context |
| `/memories` | Show stored memories |
| `/forget <id>` | Delete a memory |
| `/context` | Show project context file |
| `/key [provider]` | Add/update API key (interactive picker if no arg) |
| `/tokens` | Session token usage, cost, context bar |
| `/config` | Show config / `/config reload` to reload |
| `/export` | Export session to markdown file |
| `/checkpoint [n]` | Save conversation checkpoint |
| `/restore [n]` | Restore checkpoint (no arg = list all) |
| `/env` | Show detected shell environment |
| `/verbose` | Toggle compact/verbose streaming |
| `/mode [mode]` | Set permission mode (default/relaxed/auto) |
| `/permissions` | Allow/ask/deny rules: list, add, remove, and `check <tool> <arg>` to see how a call is decided |
| `/plan` | Toggle plan mode (explore → approve → implement) |
| `/accept` | Toggle batch edit review |
| `/search <engine>` | Switch search engine (duckduckgo/google/api) |
| `/cd <path>` | Change working directory |
| `/branch` | Save/switch/list conversation branches |
| `/mcp` | Manage MCP tool servers (add/remove/list) |
| `/autocommit` | Toggle auto git commit after AI edits |
| `/budget <amount>` | Set session budget limit (warns 80%, blocks 100%) |
| `/undo [path]` | Undo last edit / list undo history |
| `/redo [path]` | Re-apply an undone edit / list redo history |
| `/rewind [n]` | Revert all file changes from the last n turns (default 1) |
| `/diff [args]` | Show git diff (supports --staged etc.) |
| `/lint <cmd>` | Auto-lint after edits (`/lint off` to disable) |
| `/toon [on\|off]` | Compact JSON tool results into TOON (saves tokens) |
| `/pin <path>` | Pin file to always include in context |
| `/unpin <path>` | Remove pinned file |
| `/alias <name> <cmd>` | Create command alias |
| `/commands` | List custom prompt-template commands (`.kodiqa/commands/*.md`) |
| `/skills [name]` | List skills the model can load on demand, or show one |
| `/jobs` | List background commands; `/jobs log <id>`, `/jobs stop <id>`, `/jobs stop all` |
| `/unalias <name>` | Remove command alias |
| `/notify` | Toggle desktop notifications for long tasks |
| `/optimizer` | Toggle cost optimizer tips |
| `/theme <name>` | Switch UI theme (dark/light/dracula/monokai/nord) |
| `/share` | Export session as styled HTML (tool output is left out) |
| `/pr [title]` | Create GitHub PR via gh CLI |
| `/review [number]` | Review PR diff via gh CLI |
| `/issue [number]` | View GitHub issue via gh CLI |
| `/init [template]` | Scaffold project from template (existing files are kept) |
| `/plugins` | List/reload custom tool plugins |
| `/agent [@name] <task>` | Spawn a read-only research sub-agent, or one of your own from `.kodiqa/agents/` |
| `/delegate [@name] <task>` | A sub-agent makes a change in an isolated git worktree; you review the diff before anything is written |
| `/agents` | List your sub-agent definitions (and why a broken one is refused), then running/completed ones |
| `/lsp [start\|stop]` | Start/stop Language Server Protocol |
| `/voice` | Voice input via sox + Whisper |
| `/changelog` | Show version history |
| `/stats` | Session metrics (files, tools, time, cost) |
| `/review-local` | AI review of staged git changes |
| `/test <file>` | Generate unit tests for a file |
| `/persona <name>` | Switch AI persona (security-expert, code-reviewer, etc.) |
| `/patch` | Apply diff/patch from clipboard |
| `/profile` | Save/load config profiles |
| `/refactor` | Multi-file refactoring (rename, extract) |
| `/history` | Browse and resume past sessions |
| `/watch <path>` | Watch files for changes |
| `/embed [path]` | Index files for RAG search |
| `/rag <query>` | RAG search + AI answer |
| `/debug <script>` | Run script, catch errors, debug with AI |
| `/diagram <desc>` | Generate Mermaid diagram |
| `/help` | Show help |
| `/quit` | Exit |

## Permission Modes

| Mode | Behavior |
|------|----------|
| `default` | Arrow-key confirm for all writes/commands (Yes / Don't ask again / No) |
| `relaxed` | Auto-approve file operations, only confirm commands + deletes |
| `auto` | No confirmations — everything auto-approved |

Switch with `/mode relaxed` or `/mode auto`. Default is `default`.

## Permission Rules

Say exactly what may run without asking, what must always ask, and what must never happen — per tool and per argument. In `~/.kodiqa/config.json`, or with `/permissions allow|ask|deny <rule>`:

```json
"permissions": {
  "allow": ["run_command(npm test*)", "run_command(git status)", "edit(docs/**)"],
  "ask":   ["run_command(git push*)", "edit(migrations/**)"],
  "deny":  ["read(.env*)", "read(~/.ssh/*)", "web_fetch(domain:internal.example.com)"]
}
```

- **A rule is `tool` or `tool(pattern)`.** `read` covers every file-reading tool (read_file, grep, glob, tree, …), `edit` every file-writing one, and `mcp_github_*` a whole MCP server.
- **`deny › ask › allow › your mode`.** `deny` refuses in every mode, for sub-agents too. `ask` always asks, even in auto mode and after "don't ask again", and a headless run refuses it. `allow` skips the prompt even in default mode.
- **Hard to get around.** A command is allowed only when *every* part of it matches, so `npm test*` does not allow `npm test && curl … | sh`. Anything the rule matcher does not fully understand — `$(…)`, backticks, redirections, backslash escapes, comments, `$'…'` quoting, subshells or groups, or an unclosed quote — is never auto-allowed. Paths are resolved first, so `./x/../.env` and a symlink to `.env` are still `.env`. On macOS and Windows, `.ENV` counts as `.env`. A rule naming a directory covers everything inside it. A symlink cannot borrow an `allow` from the name it is reached through. A `read` rule also hides the file from grep and from `git_diff`, which refuses `--no-index`, `--output` and external diff drivers. A `web_fetch` rule is checked on every redirect, with hosts normalised (case, trailing dot, default port). Direct and lazy MCP calls are both checked under the real tool's name.
- **Projects can tighten, never loosen.** `.kodiqa/permissions.json` in a project may add `ask` and `deny` rules. An `allow` there is ignored with a warning, because a cloned repository must not grant itself permission to run commands.
- **Nothing is dropped silently.** A malformed rule, an unknown tool or a pattern on a tool that takes none is reported at startup and in `/permissions`. `/permissions check run_command "npm test && rm -rf x"` shows how a call would be decided, part by part.
- **Limits:** a shell command can read any file, and a determined command can be disguised (`command rm`, `eval`, a script file) past a `deny run_command(rm *)` rule. Command `deny`/`ask` rules catch honest mistakes; for a guarantee, deny or ask `run_command` as a whole.

## Hooks

Run your own command before or after any tool, in `~/.kodiqa/config.json`:

```json
"hooks": {
  "pre_run_command": "./scripts/allow-command.sh {command}",
  "post_write_file": "ruff check {path}"
}
```

Keys are `pre_<tool>` / `post_<tool>`; `{param}` is replaced by that tool parameter, shell-quoted.

- **A pre-hook is a gate.** The tool runs only if the hook exits 0. A non-zero exit, a timeout (30s) or a hook that cannot start all block it, and the model is told why, including the hook's output.
- **A post-hook reports.** The action has already happened, so it cannot be blocked; if the hook fails, its output is added to the tool result so the model can fix what it flagged.
- **With batch edit review**, a file's post-hook runs when you accept the edit and it is written, not when it is queued.
- **For a background command**, `post_run_command` runs once the command has started, not when it ends.
- **A hook that needs longer than 30 seconds** can be an object: `{"command": "npm test", "timeout": 300}` (up to an hour).
- **A key that would never fire**, such as `on_stop`, `post_write` or `pre_explore`, is reported at startup instead of being silently ignored.

### Session events

Four more hooks run at points in the session rather than around a tool. Each gets the event as JSON on stdin; nothing is substituted into the command line, so the prompt cannot inject anything.

| Hook | When | Exit 0 | Non-zero exit |
|------|------|--------|---------------|
| `user_prompt_submit` | before your message goes to the model | its output is added to the message as context | the message is **not sent** (also on a timeout) |
| `stop` | when the model finishes its turn | done | its output goes **back to the model** to fix, up to 3 times |
| `session_start` | when a session (or a headless run) starts | its output is context for the whole session | reported |
| `pre_compact` | before `/compact` or auto-compaction | its output is extra instructions for the summary | reported; compaction goes ahead |

```json
"hooks": {
  "session_start": "cat docs/SPRINT.md",
  "stop": {"command": "python -m pytest -q -x", "timeout": 300}
}
```

With a `stop` hook that runs the tests, the model does not finish until they pass, or until three attempts are used up. A `stop` hook that times out or cannot start is reported to you, not handed to the model, since the model cannot fix a broken hook. It does not run in plan mode, in multi-model mode, after an interrupt, or once the budget is spent.


## Skills

A skill is a set of instructions the model loads **on its own** when a task calls for it: how this project cuts a release, writes migrations, or formats a changelog entry. Only each skill's name and one-line description sit in the prompt, so a project can carry many of them for a few dozen tokens each. When a task matches a description, the model calls the `skill` tool and gets the full instructions.

```
.kodiqa/skills/changelog-entry/SKILL.md      (project; ~/.kodiqa/skills/ for global)
---
description: How this project writes changelog entries. Use whenever asked to
  write or add a changelog or release-notes entry.
---
1. The first line is exactly: `### Entry`
2. One bullet per change, each starting with a past-tense verb.
3. End with the ticket id from templates/ticket.txt.
```

- **The directory name is the skill's name.** A project skill wins over a global one with the same name.
- **A skill can carry files.** The model is told the skill's directory, so `templates/ticket.txt` above is read from there.
- **A broken skill is reported.** `/skills` lists every skill; one with no `description`, or with unclosed frontmatter, is shown with the reason instead of silently doing nothing. `/skills <name>` prints one.
- **Skill or custom command?** A custom command (`.kodiqa/commands/`) runs when *you* type it. A skill is picked up by the model when the task matches, even if you never mention it.

## Background Commands

A dev server, a file watcher or a long test run no longer blocks the turn — or gets killed at the 120-second command timeout. The model starts it with `run_command` and `background: true`, gets a job id at once, and keeps working:

```
run_command  npm run dev  (background)   →  Started job_1 (pid 48211)
job_output   job_1  until "ready|listening"   →  waits until the server is up (max 60s)
run_command  curl -s localhost:5173/api/health
job_output   job_1   →  only the lines printed since the last read
job_stop     job_1   →  stops npm and everything it started
```

- **Same protections as any command** — the confirmation prompt (relaxed mode still asks), the blocklist, `/sandbox` and `pre_run_command` hooks all apply.
- **Never hangs on its own output** — output goes to a log file, so a chatty process can't fill a pipe and freeze; each read returns only new output, capped to the last 20 KB.
- **Stops cleanly** — each job runs in its own process group, so stopping it stops its children too. Quitting Kodiqa (or a crash, or the end of a headless run) stops every job, so no server is left holding a port.
- **`/jobs`** lists what's running; `/jobs log <id>` shows the recent output without taking it from the model; `/jobs stop <id>` or `/jobs stop all`.

## Plan Mode

Activate with `/plan`. The AI will:
1. **Explore** — read files, search, analyze (no writes allowed)
2. **Present plan** — show what it intends to do
3. **You decide** — approve, revise, or reject (arrow keys)
4. **Implement** — on approval, AI executes the plan

## Batch Edit Review

When enabled (default ON, toggle with `/accept`), file edits are queued and presented for review:

```
  ? (1/3) app.py — write  +15 -3 lines
    ❯ Accept
      Reject
      Show diff
      Accept all — remaining 3 edits
      Reject all
```

Navigate with arrow keys, view diffs, accept/reject individually or in bulk.

## MCP Server Support

Connect external tool servers via the Model Context Protocol — **local or remote**:

```
# Local (stdio) server — a command Kodiqa runs
/mcp add fs npx -y @modelcontextprotocol/server-filesystem ~/projects

# Remote (HTTP) server — a hosted URL, with optional auth
/mcp add linear https://mcp.linear.app/mcp --bearer env:LINEAR_TOKEN
/mcp add api https://example.com/mcp --header "X-Api-Key:abc123"

# Remote with OAuth login (opens your browser)
/mcp add linear https://mcp.linear.app/mcp --oauth
# …or machine-to-machine (no browser)
/mcp add api https://example.com/mcp --oauth-client-id env:CID --oauth-client-secret env:CSEC

# Any REST API via its OpenAPI spec — each operation becomes a tool (no codegen)
/mcp add petstore --spec https://petstore3.swagger.io/api/v3/openapi.json
# Any GraphQL endpoint — each query/mutation becomes a tool
/mcp add gql --graphql https://api.example.com/graphql --bearer env:TOKEN

/mcp list                                # show servers + kind ([stdio]/[http]/[openapi]/[graphql]) + lazy mode
/mcp remove mytools                      # disconnect
/mcp lazy [on|off]                       # toggle lazy tool loading (default: on)
```

Remote servers use the **Streamable HTTP** transport. Auth values support `env:VAR` and
`file:PATH` so tokens aren't typed inline. **OAuth** (`--oauth`) handles discovery, dynamic
client registration, the PKCE browser login, and automatic token refresh — tokens are cached
under `~/.kodiqa/oauth/` and reused across sessions.

MCP tools are automatically available to the AI alongside built-in tools, and work with
lazy mode (discovered on demand).

### ⚡ Lazy MCP tools — save up to 94% of tool-schema tokens

Most agents paste **every** MCP tool's JSON schema into **every** request, so a big
MCP server quietly taxes every turn. Kodiqa doesn't. When servers are connected,
it exposes **3 fixed meta-tools** and lets the model discover tools on demand:

| | Per-turn tool-schema cost (50-tool server) |
|---|---|
| Inject all schemas (typical agents) | ~5,300 tokens |
| **Kodiqa lazy mode** | **~310 tokens** (~94% less) |

- `mcp_search` — find tools by keyword, ranked by how often you've used them
- `mcp_tool_schema` — fetch one tool's full schema only when needed
- `mcp_call` — run a tool by name

It's **on by default**, fully automatic (the model drives it), and the cost stays
flat no matter how many MCP tools you connect. Toggle with `/mcp lazy off`, or set
`mcp_lazy: false` in settings to always inject every schema.

## Model Shortcuts

### Local Models (free, unlimited, requires Ollama)

| Shortcut | Full Model | Best For |
|----------|-----------|----------|
| `/model fast` | qwen3:30b-a3b | Fast answers, 30B brain at 3B speed (MoE) |
| `/model qwen` | qwen3:14b | General purpose, smart, thinking mode |
| `/model coder` | qwen3-coder | Coding agent (default without API key) |
| `/model reason` | phi4-reasoning | Deep reasoning, math, logic |
| `/model gpt-local` | gpt-oss | OpenAI's open model, reasoning + agentic |

### Claude API Models (paid, requires API key)

| Shortcut | Full Model | Price (in/out per MTok) |
|----------|-----------|-------------------------|
| `/model claude` / `sonnet` | claude-sonnet-4-6 | $3/$15 |
| `/model opus` | claude-opus-4-6 | $5/$25 |
| `/model haiku` | claude-haiku-4-5 | $1/$5 |
| `/model sonnet-4.5` | claude-sonnet-4-5 | $3/$15 |
| `/model opus-4.5` | claude-opus-4-5 | $5/$25 |
| `/model opus-4.1` | claude-opus-4-1 | $15/$75 |
| `/model sonnet-4` / `opus-4` | Legacy Claude 4 | varies |

### Qwen API Models (paid, Alibaba Cloud DashScope)

| Shortcut | Full Model | Best For |
|----------|-----------|----------|
| `/model qwen3.5` / `qwen-plus` | qwen3.5-plus | Newest flagship |
| `/model qwen-max` / `qwen3-max` | qwen3-max | Most powerful |
| `/model qwen-coder` / `qwen3-coder` | qwen3-coder-plus | Coding |
| `/model qwen-coder-next` | qwen3-coder-next | Newest coder |
| `/model qwq` | qwq-plus | Deep reasoning |
| `/model qwen-flash` | qwen3.5-flash | Fast |
| `/model qwen-turbo` | qwen-turbo | Cheapest/fastest |
| `/model qwen-math` | qwen-math-plus | Math |
| `/model glm-5` | glm-5 | Third-party (Coding Plan) |
| `/model kimi` | kimi-k2.5 | Third-party (Coding Plan) |

**Qwen Coding Plan**: If you have a Coding Plan subscription (`sk-sp-` key), `/key qwen` auto-detects it and configures the dedicated endpoint. Supports $3/mo Lite and $15/mo Pro tiers.

### OpenAI API Models (paid, requires API key)

| Shortcut | Full Model | Best For |
|----------|-----------|----------|
| `/model gpt` | gpt-4o | General purpose flagship |
| `/model gpt-mini` | gpt-4o-mini | Fast and cheap |
| `/model o3` | o3 | Deep reasoning |
| `/model o3-mini` | o3-mini | Fast reasoning |
| `/model o4-mini` | o4-mini | Latest reasoning |

### DeepSeek API Models (paid, requires API key)

| Shortcut | Full Model | Best For |
|----------|-----------|----------|
| `/model deepseek` | deepseek-chat | V3 general purpose |
| `/model deepseek-r1` | deepseek-reasoner | R1 deep reasoning |

### Groq API Models (free tier available)

| Shortcut | Full Model | Best For |
|----------|-----------|----------|
| `/model llama` | llama-3.3-70b-versatile | Best open model |
| `/model llama-small` | llama-3.1-8b-instant | Ultra fast |
| `/model gemma` | gemma2-9b-it | Google's open model |
| `/model mixtral` | mixtral-8x7b-32768 | MoE, 32K context |

### Mistral API Models (paid, requires API key)

| Shortcut | Full Model | Best For |
|----------|-----------|----------|
| `/model mistral` | mistral-large-latest | Flagship |
| `/model mistral-small` | mistral-small-latest | Fast and cheap |
| `/model codestral` | codestral-latest | Code generation |

New models are auto-discovered from the APIs — they appear in `/model` and `/models` automatically.

You can also use full model names: `/model qwen3:14b` or `/model claude-opus-4-6`

## Editor / IDE bridge

Run Kodiqa as a small local HTTP server that your editor (VS Code, Zed, Neovim, …)
can call:

```bash
kodiqa --serve            # prints the URL + an auth token
# or, inside a session:  /serve
```

It binds to `127.0.0.1` only and requires the printed bearer token. Set a **stable**
token (handy for editor config) with `KODIQA_BRIDGE_TOKEN=…`, and a fixed port with
`--port`. Protocol:

| Endpoint | | |
|----------|---|---|
| `GET /health` | no auth | `{status, model, version}` |
| `POST /ask` | `{prompt, context?}` | `{response}` — one-shot model answer (no history, no file edits) |
| `GET /diagnostics?file=PATH` | | `{file, diagnostics}` from the LSP (start one with `/lsp`) |

```bash
curl -s localhost:PORT/ask -H "Authorization: Bearer TOKEN" \
  -d '{"prompt":"explain this","context":"def f(): return 1"}'
```

`/ask` is a safe, non-streaming Q&A call — ideal for "ask Kodiqa about the selection."
A minimal reference client is in [`examples/bridge_client.py`](examples/bridge_client.py); editor
extensions are thin clients over this API.

## GitHub bot

Mention `/kodiqa` or `/kq` in an issue or pull-request comment and Kodiqa does the
work in **your own Actions runner**, replies in the thread, and opens a pull
request when it changed something.

```
/kq the parser drops the last token when the input ends in a comma — fix it
```

Copy [`examples/workflows/kodiqa.yml`](examples/workflows/kodiqa.yml) to
`.github/workflows/kodiqa.yml`, add your provider key under **Settings → Secrets
and variables → Actions**, and that is the whole setup:

```yaml
- uses: Kodiqa-Solutions/Kodiqa-agent/github@v3.39.0
  env:
    ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
  with:
    model: claude-sonnet-4-6
```

> **Currently internal.** The source repository is private, and GitHub only lets a
> private repository's action be used inside its own organization. Until it is public,
> this `uses:` line resolves for Kodiqa-Solutions repositories only.

Any provider works — set `DEEPSEEK_API_KEY`, `GROQ_API_KEY`, `OPENROUTER_API_KEY`
and so on, and name a model that provider serves. Keys are read from the
environment, so nothing is written to disk in the runner.

### Only maintainers can command it

A workflow that runs an agent hands your API key and your runner to whoever can
make the job start. Kodiqa only acts on comments from an **OWNER**, **MEMBER** or
**COLLABORATOR** — GitHub decides that, not the commenter — and, on `issues` or
`pull_request` events, only on issues and PRs they opened. Anyone else is logged and
ignored **before** any model call, so a drive-by comment on a public repository costs
nothing.

What the agent reads from other people (the thread, an issue body) is marked in its
prompt as untrusted information, not instructions. The agent never gets the job's GitHub
token: it is removed from its environment, and the credential `actions/checkout` keeps
in `.git/config` is taken out while the agent runs and used only for the bot's own push.

Set `require-trusted: false` to lift that, and only on a private repository.

### What else it can do

| Event | What happens |
|-------|--------------|
| `issue_comment` on an issue | Reads the thread, makes the change, opens a PR |
| `issue_comment` on a PR | Commits to that PR's own branch (not pushed when the PR comes from a fork) |
| `pull_request_review_comment` | Gets the exact file, line and hunk you commented on |
| `pull_request` | Reviews the diff automatically — see [`kodiqa-review.yml`](examples/workflows/kodiqa-review.yml) |
| `schedule` / `workflow_dispatch` | Runs the workflow's `prompt` — see [`kodiqa-scheduled.yml`](examples/workflows/kodiqa-scheduled.yml) |

| Input | Default | |
|-------|---------|---|
| `model` | — | **Required.** Any model Kodiqa can reach |
| `prompt` | `""` | The task, for events with no comment to read |
| `mentions` | `/kodiqa,/kq` | Trigger phrases, case-insensitive |
| `require-trusted` | `true` | Ignore comments from non-maintainers |
| `kodiqa-version` | latest | Pin a version |
| `python-version` | `3.12` | Python used in the runner |
| `github-token` | `github.token` | Token for reading, commenting and pushing |

A review job only needs `contents: read` and `pull-requests: write`; a job that
should open PRs needs `contents: write` too. Grant the smaller set where you can —
a job that cannot write cannot be talked into writing.

## Sub-agents

`/agent` hands a question to a **research sub-agent** that runs its own tool loop in
the background — reading files, grepping, listing directories — and reports back,
while you keep working:

```
❯ /agent where is the retry logic for provider requests, and what does it retry on?
● Spawned agent_1: where is the retry logic... (read-only; /agents to check)

❯ /agents
  ● agent_1 done — where is the retry logic...
  ╭─ agent_1 ─────────────────────────────────────────────────────╮
  │ _retry_api_call in kodiqa/agent.py retries on 429 and 5xx... │
```

It has **its own context**: the research never lands in your conversation, only the
report does. It is **read-only** — `read_file`, `grep`, `glob`, `tree`, `list_dir`,
`git_status`, `git_diff`, `read_pdf`, `read_image`, `web_search`, `web_fetch`,
`memory_search` — so it never needs to ask you anything and can safely run in the
background. Paths outside your project are refused rather than prompted for.

`/team <task>` splits a task into up to four subtasks, runs a sub-agent on each in
parallel, and merges what they found.

### The model can delegate by itself

You do not have to type `/agent`. The `explore` tool lets the model hand an
open-ended question to a sub-agent on its own — "where is retry handled", "which
callers pass a timeout" — and continue with only the report. Several explore calls in
one turn run **in parallel**. The investigation never lands in your conversation, so a
search that needed twenty reads costs your context one reply.

Sub-agent spending is booked against the session, so **`/budget` covers it**, and a
sub-agent stops before its next request once the budget is spent.

Works with Claude, every OpenAI-compatible provider, and local Ollama models that
support tool calling.

### Your own sub-agents

Define a specialised sub-agent in `.kodiqa/agents/<name>.md` (or `~/.kodiqa/agents/` for every project):

```markdown
---
description: Reviews code for real bugs. Use whenever asked to review or check code.
tools: read_file, grep, glob, git_diff      # optional — narrows the default read-only set
model: deepseek-chat                        # optional — an alias or full id; default: your model
max_steps: 20                               # optional — 1 to 50, default 15
---
You are a strict code reviewer. For each real defect give file:line, what goes
wrong, and one input that triggers it. Do not report style issues.
```

- **The model picks it by itself.** It sees each agent's name and description and delegates with `explore` and `agent: "reviewer"` when a task matches. You can call one directly with `/agent @reviewer <task>`.
- **Its own model.** A cheap, fast model can do the searching while your main model does the thinking. Its spend is booked at that model's price and counts toward `/budget`.
- **Read-only unless it is a writer.** A definition whose `tools` include a file-writing tool (`edit_file`, `write_file`, …) is a writing agent, and runs only through `delegate` (below). No sub-agent can run commands, so a definition asking for `run_command` is not loaded. `/agents` lists every definition and says why a broken one was refused.

### Sub-agents that make changes: `delegate`

The model can hand a whole change to a sub-agent — "add input validation to every handler in `api/`" — and keep its own context for the rest of the task. You can too: `/delegate [@agent] <task>`.

```
  ● Delegate  add input validation to every handler in api/
  Sub-agent changes (4 file(s), +38 -6)
    diff --git a/api/users.py b/api/users.py
    ...
  Allow: Apply sub-agent changes: 4 file(s), +38 -6
```

- **It works on a copy, never on your files.** A throwaway `git worktree` outside your project, holding your working tree as it is right now, including uncommitted changes and new untracked files.
- **You see one diff and decide.** Accept applies it to your files, with `/undo` per file. Reject writes nothing, and the patch is kept in `~/.kodiqa/patches/`. The prompt follows your permission mode, as any file write does (`auto` and `relaxed` apply without asking).
- **All or nothing.** If your files changed meanwhile and the diff no longer applies, nothing is written and the patch is saved. Several `delegate` calls in one turn run in parallel, each in its own worktree, and are reviewed in order.
- **Confined.** Every path is resolved inside the worktree. Anything outside it, and anything under `.git`, is refused. Your extra allowed directories do not apply to it.
- **It can run the tests, sandboxed. Opt in** with `/config set delegate_commands on`, or list `run_command` in a writing agent's `tools`. Its commands then run in an OS sandbox (`sandbox-exec` on macOS, `bwrap` on Linux):
  - they write only inside its copy and a private temp dir, never your project, `/tmp` or another sub-agent's worktree;
  - no outbound network, and no unix sockets (so no `docker`, which could otherwise write anywhere);
  - no background jobs, and nothing a command starts outlives it;
  - no new symlinks on macOS;
  - your permission rules still apply.

  Files the test run leaves behind (`__pycache__/`, `.pytest_cache/`, `node_modules/`, `*.pyc`…) are left out of the diff.

  It is told where your git-ignored `venv/` or `node_modules/` are, to run the tests with them. Without an OS sandbox it gets no commands at all, and the result says so.
- **Leaves nothing behind.** No branch, no directory in your project, no git hooks run. The worktree is removed even if the sub-agent fails or you interrupt it.
- Needs a git repository with at least one commit.

## Scripting and CI

Run a task without the UI and get the answer back:

```bash
kodiqa --headless "add error handling to the retry loop in client.py"
```

With `--format json`, stdout carries **one object and nothing else** — every panel,
spinner and diff moves to stderr — so it pipes straight into `jq`:

```bash
kodiqa --headless "audit the dependencies" --format json | jq
cat long-task.md | kodiqa --headless - --format json      # "-" reads the task from stdin
```

```json
{
  "ok": true,
  "task": "audit the dependencies",
  "model": "claude-sonnet-4-6",
  "result": "Two packages are a major version behind …",
  "error": "",
  "files_changed": ["requirements.txt"],
  "tools_used": {"read_file": 6, "edit_file": 1, "run_command": 2},
  "counts": {"messages": 1, "files_read": 6, "files_edited": 1, "commands_run": 2, "searches": 0},
  "tokens": {"input": 84210, "output": 6120, "cache_read": 71000, "cache_creation": 0},
  "cost": 0.3271,
  "elapsed_s": 128.4
}
```

Which makes the usual CI things one-liners:

```bash
# fail the job if a task costs more than a dollar
COST=$(kodiqa --headless "$TASK" --format json | jq '.cost')
awk "BEGIN{exit !($COST > 1.0)}" && echo "too expensive" && exit 1

# did it actually change anything?
kodiqa --headless "$TASK" --format json | jq -e '.files_changed | length > 0'
```

**Exit codes.** `0` when the run produced an answer or changed a file, `1` when it
raised — and `1` when it finished having produced nothing at all. That last case is
what an unreachable provider or an uninstalled local model looks like: Kodiqa prints
a hint and returns normally, which would otherwise report success for a run that
never happened.

`--result FILE` writes just the final answer, and `--output FILE` the full
transcript, if a file suits you better than stdout.

## Compact Streaming Mode

By default, Kodiqa hides code blocks during streaming and shows progress instead:

```
Kodiqa  I'll create the project structure...

  ⠋ Writing code (javascript)... 45 lines, 1,890 chars
  ╰─ code block: javascript 45 lines, 1,890 chars

Now the package.json:

  ⠋ Writing code (json)... 12 lines, 340 chars
  ╰─ code block: json 12 lines, 340 chars

  1,204 in / 847 out | 42.3 tok/s | ($0.0061 / session: $0.0183)
```

Use `/verbose` to toggle full output (see all code as it streams).

## API Setup

Use `/key` to add API keys interactively (shows all 8 providers), or specify directly:

| Provider | Command | Get Key |
|----------|---------|---------|
| Claude | `/key claude` | https://console.anthropic.com/settings/keys |
| OpenAI | `/key openai` | https://platform.openai.com/api-keys |
| DeepSeek | `/key deepseek` | https://platform.deepseek.com/api_keys |
| Groq | `/key groq` | https://console.groq.com/keys |
| Mistral | `/key mistral` | https://console.mistral.ai/api-keys |
| Qwen | `/key qwen` | https://bailian.console.alibabacloud.com/?apiKey=1 |
| Venice | `/key venice` | https://venice.ai/settings/api |

Then switch: `/model claude`, `/model gpt`, `/model deepseek`, `/model llama`, `/model mistral`, `/model qwen3.5`

### Keys from the environment

Every provider also reads its key from the environment, which takes precedence
over `settings.json`. This is what makes CI, devcontainers and `direnv` work
without a settings file — and it lets you override a stored key for one shell.

| Provider | Environment variable |
|----------|---------------------|
| Claude | `ANTHROPIC_API_KEY` |
| OpenAI | `OPENAI_API_KEY` |
| DeepSeek | `DEEPSEEK_API_KEY` |
| Groq | `GROQ_API_KEY` |
| Mistral | `MISTRAL_API_KEY` |
| Qwen | `QWEN_API_KEY` or `DASHSCOPE_API_KEY` |
| Venice | `VENICE_API_KEY` |
| OpenRouter | `OPENROUTER_API_KEY` |

If one of those names is already taken by something else, `KODIQA_<PROVIDER>_API_KEY`
wins over it. A key found in the environment is **never written to `settings.json`** —
the environment owns that value. `/help` marks such providers as *connected, from env*.

## What You Can Ask

### File Operations
```
read the file ~/.zshrc
create a file called hello.py with a hello world program
edit main.py and change the function name from foo to bar
move config.json to config.backup.json
delete the temp file at ~/scratch.txt
```

### Multi-Edit & Undo
```
rename all occurrences of "oldName" to "newName" in utils.py
undo the last edit to main.py
```

### Search
```
find all .py files in ~/projects
search for "TODO" in my project
```

### Commands & Git
```
run npm install
show me the git status
commit these changes with message "fix login bug"
```

### Web Search
```
search the web for kotlin coroutines tutorial
fetch the content from https://some-docs-page.com
```

### Memory
```
remember that I prefer Kotlin for Android development
what do you remember about my preferences?
```

### Images & PDFs
```
look at this screenshot ~/Desktop/screenshot.png
read the PDF ~/Documents/report.pdf
```

### Clipboard
```
paste what's on my clipboard
copy this code to clipboard
```

### Project Analysis
```
/scan ~/myapp
now explain what this project does
find any bugs in this code
```

## Safety

- **Auto-approved**: reading files, listing dirs, searching, web, memory, clipboard read, undo
- **Asks permission**: writing/editing files, running commands, git commits, delete, move, clipboard write, patches
- **Workspace boundary**: asks before accessing files outside current working directory (Allow once / Allow directory / Deny)
- **Blocked**: `rm -rf /`, `sudo rm`, `mkfs`, `dd`, fork bombs, etc.
- **Permission modes**: `/mode default` (confirm all) → `/mode relaxed` (auto file ops) → `/mode auto` (no confirms)

## 33 Tools

| Category | Tools |
|----------|-------|
| File ops | read_file, write_file, edit_file, multi_edit, search_replace_all, create_directory, move_file, delete_file, undo_edit |
| Search | glob, grep, list_dir, tree |
| Commands | run_command (foreground or `background`), job_output, job_stop |
| Git | git_status, git_diff, git_commit |
| Web | web_search, web_fetch |
| Media | read_image, read_pdf |
| Memory | memory_store, memory_search |
| Clipboard | clipboard_read, clipboard_write |
| Patch | diff_apply |
| Tasks | todo_write |
| Delegation | explore (read-only research), delegate (a change in an isolated worktree, reviewed as a diff) |
| Skills | skill (loads a SKILL.md on demand) |
| UX | ask_user |

## Files

```
~/LLMS/kodiqa/
  kodiqa/            # the package (everything imports as kodiqa.<module>)
    agent.py         # Main agent (7558 lines)
    actions.py       # Action handlers (1287 lines)
    tools.py         # Tool schemas (497 lines)
    config.py        # Config, themes, provider registry (1046 lines)
    web.py           # Web search + page fetch (241 lines)
    memory.py        # SQLite persistent memory (94 lines)
    mcp.py           # MCP client (444 lines)
    templates.py     # 5 project templates (61 lines)
    lsp.py           # LSP client (272 lines)
    embeddings.py    # RAG vector store (92 lines)
    repomap.py       # Tree-sitter/regex repo map (163 lines)
  github/            # the GitHub action (not part of the pip package)
  examples/          # bridge client + workflow templates
  bin/kodiqa         # Global install script
  tests/             # 1487 tests (pytest)
  pyproject.toml     # Package config (pip install .)
  requirements.txt   # Dependencies

~/.kodiqa/
  config.json        # User-editable config (overrides defaults)
  settings.json      # API keys, default model
  memory.db          # Persistent memories
  session.json       # Auto-saved conversation
  input_history      # prompt_toolkit FileHistory
  error.log          # Error log (capped 1MB)
  KODIQA.md          # Global context (always in system prompt)
  projects/          # Per-project context files
  checkpoints/       # Conversation checkpoints
  exports/           # Exported session markdown files
```

## Tips

- All prompts use **arrow keys** — no typing letters, just navigate and press Enter
- Default is **compact mode** — code hidden during streaming, progress shown instead
- Use `/verbose` when you want to see code as it streams
- Use `/mode relaxed` to skip file edit confirmations
- Use `/plan` for complex tasks — review the plan before implementation
- Use `/accept` to toggle batch edit review on/off
- Use `/branch save` before experimenting — switch back if it goes wrong
- Use `/mcp add` to connect external tool servers
- Use `/checkpoint` before risky operations, `/restore` to roll back
- Use `/export` to save a conversation for later reference
- Use `/tokens` to monitor API costs and context usage
- Use `/model` with no arg for interactive picker
- Use `/key` with no arg to choose provider
- Tab complete works for commands, models, and file paths
- New API models appear automatically — no code updates needed
- Memories persist forever across sessions
- Arrow keys work: up/down for history, left/right to edit
- Sessions auto-save — restart if anything goes wrong
- Session summary auto-saved on quit — next start has full context
- Type `quit` or `exit` (no slash needed) to exit
- Ollama starts/stops automatically — stops on cloud switch, restarts on local switch

## Testing

```bash
pytest -v          # 1487 tests, all passing
```

## Requirements

- Python 3.11+
- Ollama installed (`/Applications/Ollama.app` on macOS) — or just use API models
- Models pulled automatically on first run, or `ollama pull qwen3-coder`
- (Optional) Claude API key for Claude models
- (Optional) DashScope API key for Qwen API models

## License

Kodiqa is open source under the [AGPL-3.0 License](LICENSE).

For commercial use without AGPL obligations, see [Commercial License](COMMERCIAL_LICENSE.md) or contact [eniz@kodiqa.com](mailto:eniz@kodiqa.com).
