Metadata-Version: 2.4
Name: raggiecode
Version: 1.0.0
Summary: AI Coding Agent
License: Apache-2.0
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: tree-sitter==0.25.2
Requires-Dist: tree-sitter-python==0.25.0
Requires-Dist: tree-sitter-go==0.25.0
Requires-Dist: tree-sitter-c-sharp==0.21.0
Requires-Dist: tree-sitter-javascript==0.21.0
Requires-Dist: tree-sitter-typescript==0.21.0
Requires-Dist: tree-sitter-rust==0.24.2
Requires-Dist: tree-sitter-zig==1.1.2
Requires-Dist: tree-sitter-elixir==0.3.5
Requires-Dist: tree-sitter-cpp==0.23.4
Requires-Dist: tree-sitter-c==0.23.4
Requires-Dist: tree-sitter-php==0.24.1
Requires-Dist: tree-sitter-language-pack==1.8.1
Requires-Dist: rich>=13.7.1
Requires-Dist: pathspec>=1.0.0
Requires-Dist: openai==2.43.0
Requires-Dist: prompt_toolkit
Requires-Dist: xxhash
Requires-Dist: ddgs
Requires-Dist: dulwich
Requires-Dist: ripgrep_rs
Requires-Dist: agent-client-protocol==0.12.1
Requires-Dist: mcp==2.0.0
Requires-Dist: yoyo-migrations>=9.0.0

# Raggie Code 

> *Raggie Code v1.0.0*

<p style="padding:30px 50px;">
  <img src="Raggie.png" alt="Raggie" width="312">
</p>

**Raggie** is an autonomous AI coding agent that doesn't just read your codebase. it *understands* it.

Most AI coding assistants dump file contents into a prompt and hope for the best. Raggie is different. It builds a **code semantic index** of your entire codebase, navigates **call graphs**, traces **dependency chains**, and uses that structural understanding to make surgical, context-aware changes. not blind edits.

It plans multi-step tasks with **todo lists**, delegates subtasks to **subagents**, fetches **skills on demand**, and tracks every change in a **built-in git repo** with one-click `/undo` and `/redo`. When the context window fills up, it performs an **automatic handover** to a fresh session. summarizing everything it's done so the next iteration picks up exactly where it left off. All while respecting your `.gitignore`, asking for your approval on big decisions, and working with **any OpenAI-compatible LLM**. local or cloud.

It runs locally. Your code index, chat history, and git repo never leave your machine.

Raggie also speaks **ACP** (Agent Client Protocol) and **MCP** (Model Context Protocol). Run it as a headless agent server for editors like Zed, serve its built-in chat web UI with `raggie code --web`, or plug in external MCP tool servers (GitHub, filesystem, databases) — both protocol eras supported, including the stateless 2026-07-28 revision.

---

## Why Raggie?

### It actually understands your code

Raggie doesn't grep for strings and guess. It parses your codebase with **tree-sitter**. the same parser engine used by Neovim, GitHub code search, and tree-sitter's own language grammars. It tracks all dependencies and all dependents (something tree-sitter alone cannot do), letting the agent analyze the blast radius of each change by knowing what calls what, what imports what, and where every symbol lives. When you ask it to "refactor the auth middleware," it traces the call tree, finds every caller, and updates them all.

**15 languages supported:** Python, Go, C#, JavaScript, TypeScript, TSX, Rust, Zig, Elixir, C, C++, PHP, Dart, Java, and Kotlin.

### It can plan before it acts

Give Raggie a complex task like "migrate the database from SQLite to PostgreSQL" and it won't just start editing files blindly. It can create a **todo list**, breaks the work into ordered steps, shows you the plan, and waits for your y/n approval before touching anything. Then it executes each step sequentially via **isolated subagents**. one task at a time, never in parallel, with full context carried forward.

### Almost never loses context

When the LLM's context window fills up mid-task, Raggie doesn't just truncate and hope. It performs an **automatic session handover**: the agent generates a detailed handover document covering the original goal, current state, decisions made, changes applied, test results, errors encountered, and the exact next step. then spins up a fresh session that picks up the work seamlessly. You can also resume interrupted todo lists and conversations across sessions. Even if the process dies mid-tool-call, the next startup detects unanswered tool calls, re-executes them (subagent tasks resume their existing child session instead of starting over), and repairs the history before it is sent back to the API.

### It's safe by design

- **Built-in git repo**: Every change is committed to `.raggie/git/`. Type `/undo` to undo instantly, `/redo` to re-apply. The working tree is auto-snapshotted before each prompt so `/undo` always has a valid state to restore.
- **Code health tracking**: After every response, the agent shows the most complex function by a weighted branch-nesting metric. Type `/health` for a full complexity report.
- **`.gitignore` / `.aiignore` respected**: The agent can't read, write, or modify ignored files. If a `.aiignore` file exists, it's used instead of `.gitignore` for both file access and code indexing.
- **Human-in-the-loop**: The `AskUser` tool lets the agent ask you questions mid-task. Todo list plans require your approval before execution.
- **Crash recovery**: Undo/redo operations use marker files for crash safety. Interrupted todo lists are detected and offered for resumption on next startup. Chat history is validated and repaired on load and again before every API call (tool-call/tool-response pairing, message ordering, content types), so interrupted or corrupted sessions resume cleanly instead of failing with API errors.

### It gets smarter over time

Raggie's **skills system** lets it learn and persist knowledge across sessions. Skills are named instruction sets (like `code/testing` or `code/git-workflow`) stored in the database. At startup, only brief summaries go into the system prompt. the full content is fetched on demand via `GetSkill`, saving tokens. The agent can even create its own skills with `SetSkill` (with your consent). Skills survive across sessions, can be imported/exported as Markdown files, and stack with project-specific `AGENTS.md` overrides.

### It works with your stack

- **Any OpenAI-compatible LLM**: OpenAI, DeepSeek, OpenRouter, Ollama, vLLM, LocalAI. if it speaks the OpenAI API, Raggie works with it.
- **32 tools**: Code exploration, file operations, shell execution (including background processes), web search, web fetch, image reading for vision models, and more.
- **Project-specific customization**: Drop an `AGENTS.md` in your project root and the agent picks up your conventions automatically.
- **Role-based configuration**: Define multiple agent roles with different models, tools, and system prompts.

### It's transparent

Every tool call is displayed in real time with its arguments. Debug mode (`--debug`) shows full tool outputs. The `ViewChanges` tool lets the agent introspect its own git history. status, diffs, and commit log. You always know what the agent is doing, what it changed, and why.

---

## Feature Overview

| Feature | What it means |
|---|---|
| **code semantic indexing** | Full codebase parsing into symbols, functions, classes, imports, and dependency graphs (blast radius analysis). not just text search |
| **Call graph traversal** | BFS traversal from any entry point with cycle detection (depth 5). Trace execution flow across your entire codebase |
| **Fuzzy symbol search** | Find functions/classes/variables by name even when you don't know the exact spelling |
| **Multi-step task planning** | Todo list system with user approval gates, sequential subagent execution, and crash recovery |
| **Subagent delegation** | Spawn child agents for subtasks with depth controlled by thinking modes and optional timeouts |
| **Automatic context handover** | When the context window fills up, the agent generates a handover document and continues in a fresh session |
| **Skills system** | Persistent, on-demand instruction sets that the agent advertises and fetches as needed |
| **Built-in git versioning** | Every change committed automatically. `/undo` to undo, `/redo` to redo. Auto-snapshot before each prompt. Full diff and log introspection |
| **Code health tracking** | Weighted branch-nesting complexity metric. Health stats after every response. `/health` for full report. Tunable nesting weight modes |
| **Human-in-the-loop** | `AskUser` tool for mid-task questions. Todo list approval gates. `SetSkill` requires user consent |
| **32 tools** | Code exploration, file I/O, shell (foreground + background), web search/fetch, image reading for vision models, and more |
| **`.gitignore` / `.aiignore` enforcement** | Ignored files are invisible to the agent. can't read, write, modify, or index them. Use `.aiignore` to control this independently of git |
| **15 languages** | Python, Go, C#, JavaScript, TypeScript, TSX, Rust, Zig, Elixir, C, C++, PHP, Dart, Java, Kotlin |
| **Any OpenAI-compatible LLM** | Works with OpenAI, DeepSeek, OpenRouter, Ollama, vLLM, LocalAI, and anything else that speaks the OpenAI API |
| **Persistent chat history** | SQLite-backed sessions, messages, skills, and todo lists. all survive across restarts. Crashed sessions resume with unanswered tool calls re-executed and history validated/repaired before any API call |
| **File references in prompts** | Type `@path/to/file.py:10-25` in your prompt and the referenced lines are expanded inline. ships with a VSCode extension that copies selections in this format |
| **Project customization** | `AGENTS.md` for project conventions, `roles.json` for model/tool configuration, skills for persistent instructions |
| **Thinking modes** | Control how deep the agent can nest subagents. 5 modes: Zen (depth 1), Serious (2), Extreme (4), Feral (8), Insane (16). Change mid-session with `/thinkingMode` |
| **Background shell execution** | Run long-running commands (dev servers, watchers) non-blocking with PID tracking and kill support |
| **Web search & fetch** | Search the web via DuckDuckGo and fetch URL content. the agent can look up docs and APIs |
| **Multiprocessing indexing** | Tree-sitter parsing uses multiprocessing for fast indexing of large codebases |
| **ACP agent server** | Run Raggie as a headless agent over ACP (Agent Client Protocol). stdio transport for editors like Zed, HTTP+SSE transport for web UIs. Tool calls, permissions, and streaming all bridged |
| **Built-in web UI** | A compact chat UI served by the agent itself (`raggie code --web`). Streaming responses, tool call timelines, permission and question panels, indexing progress — no separate frontend deployment |
| **MCP client integration** | Connect external MCP (Model Context Protocol) servers — stdio subprocess or Streamable HTTP. Supports both the 2026-07-28 stateless revision and earlier stateful servers. Tools merge seamlessly into the agent's toolset |
| **Agent Skills compatibility** | Import and export skills in the Agent Skills standard format (agentskills.io). Auto-discovers skills from `.skills/`, `skills/`, and `.claude/skills/` directories at startup |

---

## Table of Contents

- [Installation](#installation)
- [Quick Start](#quick-start)
- [File References in Prompts](#file-references-in-prompts)
- [Commands Reference](#commands-reference)
- [In-Chat Commands](#in-chat-commands)
- [Thinking Modes](#thinking-modes)
- [Architecture](#architecture)
- [Configuration](#configuration)
- [Using Local AI](#using-local-ai)
- [Tools Reference](#tools-reference)
- [Skills System](#skills-system)
- [Todo List System](#todo-list-system)
- [Code Indexing](#code-indexing)
- [Git Integration](#git-integration)
- [Code Health](#code-health)
- [ACP Agent Server](#acp-agent-server)
- [Web UI](#web-ui)
- [MCP Server Integration](#mcp-server-integration)
- [FAQ](#faq)

---

## Installation

### From pip (GitHub)

```bash
pip install raggiecode
```

### From source

```bash
git clone https://github.com/Hussein-L-AlMadhachi/RaggieCode.git
cd raggie
pip install .
```

### Requirements

- Python 3.10+
- An API key for an OpenAI-compatible LLM provider (OpenAI, DeepSeek, OpenRouter, etc.)

### First-time setup

```bash
raggie setup
```

This guided wizard walks you through:
1. Adding your API keys
2. Reviewing agent roles (model, base URL)

### Start the agent

```bash
raggie code myproject
```

---

## Quick Start

### 1. Run the setup wizard

```bash
raggie setup
```

You'll be prompted to add API keys and review your agent roles in one seamless flow.

### 2. Run the agent

```bash
# Single prompt mode (in a new project)
raggie code myproject --prompt "Write a hello world function in Python"

# Single prompt mode (in a specific project)
raggie code /path/to/project --prompt "Write a hello world function in Python"

# Interactive mode (chat loop)
raggie code /path/to/project

# Web UI mode (serves a chat UI in your browser)
raggie code --web
```

In interactive mode:
- **Enter** to send your message
- **Esc then Enter** for multi-line input
- **`exit`** or **`quit`** to leave
- **`!command`** to run a shell command directly (e.g. `!ls -la`)

### 3. Undo if something goes wrong

After the agent makes changes, type `/undo` as your next prompt to undo the last commit. Type `/redo` to re-apply it.

### 4. Reference exact code in your prompt

Type `@path/to/file.py:10-25` (or a single line like `@path/to/file.py:10`) anywhere in your prompt and Raggie expands it inline with the referenced lines before sending it to the LLM:

```
You:
❯ fix the off-by-one in @src/app.py:48-52
```

Rules of thumb:
- Paths are relative to the project directory. Missing files and email addresses like `user@example.com` are left untouched.
- Reversed ranges (`:5-3`) are normalized, and ranges past end-of-file are clamped.
- The same reference used twice is only expanded once.

A companion **VSCode extension** (`vscode-extension/` in this repo, "Raggie Code Tools") adds a right-click "Copy Reference for Raggie Code" command that copies the current selection as `@path/to/file:23-43`, ready to paste into the chat.

### See it in action

```bash
$ raggie code .

Raggie Agent (code) v1.0.0 - Interactive Mode
--------------------------------------------------
Indexing codebase...

Thinking mode: Zen - to change it use /thinkingMode

Press Esc followed by Enter to send message, or type 'exit' to quit

You:
❯ Add input validation to the login endpoint and update all callers

Agent (deepseek-v4-flash:0):
I'll start by finding the login endpoint and tracing its callers.

  [tool] GetSymbolSourceCode(name="login")
  [tool] WalkCallTree(entry_point="login", depth=3)
  [tool] GetFileCodeSemantics(file_path="src/auth/views.py")

I found the login endpoint at `src/auth/views.py:42` and 3 callers across
the codebase. I'll add validation for the email and password fields,
then update each caller to handle the new validation errors.

  [tool] ReplaceText(file_path="src/auth/views.py", ...)
  [tool] ReplaceText(file_path="src/api/routes.py", ...)
  [tool] ReplaceText(file_path="tests/test_auth.py", ...)
  [tool] Shell(command="python -m pytest tests/test_auth.py")

All 3 callers updated and tests pass. Changes committed.
type /undo to undo the last code changes
```

---

## Thinking Modes

Thinking modes control how deep the agent can nest subagents. Higher thinking modes allow the agent to break down complex tasks into more layers of subtasks.

| Level | Name | Max Depth | Description |
|---|---|---|---|
| 1 | **Zen** | 1 | Minimal. One level of subagents only. Fast and cheap. Default for new sessions |
| 2 | **Serious** | 2 | Moderate. Up to 2 levels of nested subagents |
| 3 | **Extreme** | 4 | Deep. Up to 4 levels of nested subagents for complex multi-step tasks |
| 4 | **Feral** | 8 | Very deep. Up to 8 levels. For highly complex tasks requiring extensive decomposition |
| 5 | **Insane** | 16 | Deepest. Up to 16 levels. For the most complex tasks. Use with caution |

### Changing thinking mode

- **In interactive mode**: The current thinking mode is displayed before each prompt. Use `/thinkingMode` to change it:
  ```
  /thinkingMode 3        # set by number
  /thinkingMode extreme  # set by name (case-insensitive)
  /thinkingMode          # interactive prompt to pick a mode
  ```
- **In non-interactive mode**: Pass `--thinking-mode <num>` on the command line:
  ```bash
  raggie code myproject --prompt "Refactor everything" --thinking-mode 5
  ```
- New sessions default to **Zen** (level 1). The thinking mode persists per session in the database.

### How depth works

When the agent dispatches a subagent, the child session's depth increments. If the depth reaches the thinking mode's `max_depth`, further subagent dispatch and todo list creation are blocked. This prevents runaway recursion and keeps costs predictable.

---

## Commands Reference

### `raggie <role> <project-dir>`

Run the AI agent with a specific role in a project directory.

| Argument | Description |
|---|---|
| `role` | (Required) Agent role, defined in `roles.json`. Default: `"code"` |
| `project-dir` | (Optional) Path to the project directory. Use `.` for current directory. Created if it doesn't exist. Default: `.` |
| `--prompt` | (Optional) Single prompt. Omit for interactive mode |
| `--thinking-mode` | (Optional) Thinking mode 1-5 (zen, serious, extreme, feral, insane). Controls max subagent depth |
| `--debug` | Show raw tool call outputs for debugging |
| `--acp-stdio` | Run as an ACP (Agent Client Protocol) agent over stdio. For editors like Zed. No `role` or `project-dir` required |
| `--acp-http` | Run as an ACP agent over HTTP (JSON-RPC POST + SSE streaming). For custom web clients and remote consumers |
| `--acp-port` | Port for `--acp-http` and `--web` (default: 8765) |
| `--acp-auto-approve` | Auto-approve permission requests in ACP mode. Use when no interactive client answers permission prompts |
| `--web` | Serve the built-in web UI rooted at the current directory instead of running a terminal session — see [Web UI](#web-ui) |

**Examples:**
```bash
raggie code /path/to/project --prompt "Refactor the API router to use dependency injection"
raggie code /path/to/project
raggie code . --debug
raggie code --web
```

### `raggie setup`

First-time setup wizard. Guides you through configuring API keys and reviewing agent roles. everything needed to get started.

### `raggie keys`

Manage API keys via an interactive menu. Keys are stored in `~/.config/raggie/keys.json`.

Options: Add key, Remove key, Exit (press `q`).

### `raggie roles`

List and edit agent roles via an interactive menu. Roles are stored in `~/.config/raggie/roles.json`.

Options: Edit role's base URL / model, Exit (press `q`).

### `raggie skill [role]`

Manage named skills stored in the database. A role can have multiple skills, each identified by a unique name.

Running `raggie skill` or `raggie skill <role>` without flags opens an interactive menu (like `raggie keys` and `raggie roles`):

```
Skills for role 'code'
------------------------------------------------------------
  1. testing: Always write tests after implementing. Use pytest.
  2. refactoring: When refactoring, preserve behavior.
------------------------------------------------------------
q. Exit
1. View skill content
2. Delete skill
3. Export skill to file
4. Import skill from file
5. List all skills (all roles)
```

For scripting, flags are also available:

| Flag | Description |
|---|---|
| `--show` | Display all skills for the role (or a specific skill with `--name`) |
| `--name <name>` | Specify the skill name (required for import/export/delete) |
| `--import-skill <file>` | Import a skill from a Markdown file into the database (requires `--name`) |
| `--export-skill <file>` | Export a skill from the database to a Markdown file (requires `--name`) |
| `--import-skill-dir <dir>` | Import an Agent Skills directory (folder with `SKILL.md`) or a container of skill folders |
| `--export-skill-dir <dir>` | Export a skill as an Agent Skills directory with `SKILL.md` (requires `--name`) |
| `--delete` | Delete a skill (requires `--name`) |
| `--list-all` | List all skills across all roles (role arg not required) |

**Examples:**
```bash
raggie skill code                          # interactive menu for role 'code'
raggie skill                               # interactive menu (all roles)
raggie skill code --show --name testing     # show full content of a specific skill
raggie skill code --import-skill my-skills.md --name testing   # import from file
raggie skill code --export-skill backup.md --name testing      # export to file
raggie skill code --delete --name testing   # delete a skill
raggie skill --list-all                    # list all skills across all roles

# Agent Skills format (agentskills.io)
raggie skill code --import-skill-dir ./my-skills/   # import a directory of skill folders
raggie skill code --import-skill-dir ./my-skills/web-testing/  # import a single skill folder
raggie skill code --export-skill-dir ./exported/ --name testing  # export as Agent Skills directory
```

### `raggie mcp`

Manage external MCP (Model Context Protocol) servers. Supports both the 2026-07-28 revision (stateless, "MCP 2.0") and earlier 2025-era stateful servers, over stdio and Streamable HTTP.

Servers are configured in `~/.config/raggie/mcp_servers.json`:

```json
{
  "local-files": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
    "trust": false
  },
  "remote-api": {
    "url": "https://example.com/mcp",
    "trust": true
  }
}
```

| Flag | Description |
|---|---|
| `--list` | List all configured MCP servers |
| `--add <name>` | Add a server (use with `--cmd` or `--url`) |
| `--remove <name>` | Remove a server |
| `--test <name>` | Connect to a server and list its discovered tools |
| `--cmd <exe>` | Executable for a stdio server (use with `--add`) |
| `--args <...>` | Arguments for the stdio command (use with `--add`) |
| `--url <url>` | URL for a Streamable HTTP server (use with `--add`) |
| `--trust` | Mark server as trusted (skip per-call confirmation) |
| `--env KEY=VALUE` | Environment variable for stdio server (repeatable) |

**Examples:**
```bash
# Add a local stdio server
raggie mcp --add local-files --cmd npx --args -y @modelcontextprotocol/server-filesystem /tmp

# Add a remote HTTP server (trusted)
raggie mcp --add remote --url https://example.com/mcp --trust

# List configured servers
raggie mcp --list

# Test connectivity and list tools
raggie mcp --test local-files

# Remove a server
raggie mcp --remove local-files
```

Tools from connected MCP servers are exposed to the agent as `mcp__<server>__<tool>` and merged into the toolset alongside Raggie's built-in tools. Untrusted servers require per-call user confirmation (routed through the I/O backend, so in ACP mode the editor's permission UI is used).

---

## In-Chat Commands

These commands are available inside the interactive chat loop. They are intercepted before reaching the LLM and handled locally.

| Command | Description |
|---|---|
| `/undo` | Undo the last agent commit (restore previous file state) |
| `/redo` | Re-apply the last undone commit |
| `/reasoning on\|off` | Toggle reasoning output mid-conversation. Persists to `roles.json` |
| `/windowSize <number>` | Set the context window size (in tokens) for handover logic. Persists to `roles.json` |
| `/globalTodo on\|off` | Toggle shared todo lists across subagents. Persists to `roles.json` |
| `/thinkingMode <num\|name>` | Set thinking mode (1-5 or zen, serious, extreme, feral, insane). Controls max subagent depth |
| `/reindex [--force]` | Re-index the codebase. Use `--force` to re-index all files from scratch |
| `/health` | Generate a full code complexity report (`.txt` file in the current directory) |
| `/skills` | List all loaded skills with their summaries |
| `/reload-skills` | Re-scan `.skills/`, `skills/`, and `.claude/skills/` directories for new or changed skills. Updates the agent's skill list mid-session without restarting |
| `/use <name>` | Inject a skill's full content into the conversation for the agent to follow immediately |
| `/help` | Show available in-chat commands |
| `!<command>` | Run a shell command directly (e.g. `!ls -la`, `!pytest tests/`) |

**Notes:**
- `/reasoning` and `/windowSize` take effect on the next message and persist to `~/.config/raggie/roles.json` so they survive across sessions.
- Calling `/reasoning` without arguments shows the current status.
- Calling `/windowSize` without arguments shows the current context window size.
- Calling `/thinkingMode` without arguments prompts you to pick a mode interactively.
- Calling `/globalTodo` without arguments shows the current status.
- Shell commands run via `!` are executed in the project directory and their output is printed directly. They do not go through the LLM.

---

## Architecture

```
raggie/
├── src/
│   ├── raggie.py              # Entry point. parses args (role + project-dir), runs agent loop
│   ├── cli.py                 # Argument parser (argparse)
│   ├── interactive.py         # Interactive chat loop + @path:lines file reference expansion
│   ├── io_backend.py          # Configurable I/O layer (terminal / ACP headless modes)
│   ├── mcp_client.py          # MCP client manager (dual-era, stdio + Streamable HTTP)
│   ├── chat.py                # Watermelon-themed status messages (flavor)
│   ├── acp_server/            # ACP (Agent Client Protocol) server
│   │   ├── __init__.py        # Entry points: run_stdio(), run_http(), run_web()
│   │   ├── agent.py           # RaggieACPAgent — maps raggie events to ACP notifications
│   │   └── http_transport.py  # HTTP+SSE transport for --acp-http and the web UI
│   ├── config/                # Default configuration files
│   │   ├── roles.json         # Agent role definitions
│   │   ├── tools.json         # Tool definitions for LLM function calling
│   │   ├── mcp_servers.json   # MCP server config (empty by default)
│   │   └── coder_system_prompt.md  # System prompt for the code role
│   ├── Agent/
│   │   ├── agent.py           # Core Agent class. prompt loop, tool execution, history validation, commit
│   │   ├── config.py          # Config loader. reads from ~/.config/raggie/
│   │   ├── tools.py           # ToolRegistry. maps tool names to handler functions
│   │   ├── chat_history_db.py # SQLite DB. sessions, messages, skills, todo lists + history repair/validation
│   │   ├── thinking_modes.py  # Thinking mode tiers controlling max subagent depth
│   │   └── git_manager.py     # Local git repo in .raggie/git/ for versioning
│   ├── Tools/
│   │   ├── __init__.py        # Registers all tool handlers with the registry
│   │   ├── read.py            # WholeFileContentDump
│   │   ├── write.py           # WriteFile
│   │   ├── replace.py         # ReplaceText
│   │   ├── edit_symbol.py     # EditSymbol (replace a symbol's implementation by name)
│   │   ├── remove.py          # RemoveFile
│   │   ├── read_image.py      # ReadImage (vision input)
│   │   ├── document.py        # Document (persisted symbol descriptions)
│   │   ├── ask_user.py        # AskUser (human-in-the-loop questions)
│   │   ├── shell.py           # Shell command execution
│   │   ├── temp_background_service.py # TempBackgroundService. temporary background services
│   │   ├── shell_kill.py      # ShellKill. kill background processes
│   │   ├── search.py          # SearchAllFilesContent (grep)
│   │   ├── list_dir.py        # ListDir
│   │   ├── web_fetch.py       # WebFetch
│   │   ├── web_search.py      # WebSearch
│   │   ├── view_changes.py    # ViewChanges (git status/diff/log)
│   │   ├── dispatch_subagent.py  # DispatchSubagent. spawns child agents (crash-safe resume)
│   │   ├── todo_list.py       # Todo list CRUD + execution
│   │   ├── GetSymbolSourceCode.py  # GetSymbolSourceCode
│   │   ├── GetFileCodeStructure.py  # GetFileCodeSemantics
│   │   ├── walk_call_tree.py  # WalkCallTree
│   │   ├── fuzzy_search.py    # FileNameSearch (fuzzy file name matching)
│   │   └── utils.py           # Colors, is_within_cwd, is_ignored_by_gitignore
│   ├── indexing/
│   │   ├── code_indexer.py    # Tree-sitter based code indexer
│   │   ├── code_index_sdk.py  # SDK for querying the code index
│   │   ├── file_utils.py      # File walking utilities
│   │   ├── extractors.py      # Symbol extraction per language
│   │   ├── frontend/          # HTML/CSS/JSX/TSX indexing (components, styles, bindings)
│   │   ├── language_config.py # Language parser configurations
│   │   ├── models.py          # Data models (Symbol, Function, Class, etc.)
│   │   ├── db_schema.py       # SQLite schema for the code index
│   │   ├── node_utils.py      # Tree-sitter node helpers
│   │   ├── queries.py         # Tree-sitter query patterns
│   │   ├── parse_worker.py    # Multiprocessing parse worker
│   │   └── export_to_json.py  # Export index to JSON
│   ├── RAG/
│   │   ├── find.py            # Find symbols in the index
│   │   ├── graph.py           # Dependency graph traversal
│   │   └── document.py        # Symbol description storage
│   └── skills/
│       ├── __init__.py        # Exports SkillManager
│       ├── manager.py         # SkillManager. CRUD for named skills (role + name)
│       └── tool.py            # SetSkill + GetSkill tool handlers
├── vscode-extension/          # VSCode extension: copy selection as @path:lines reference
├── AGENTS.md                  # Project-specific overrides (auto-loaded)
├── pyproject.toml             # Package metadata + dependencies
├── .raggie/
│   ├── .raggie.chat           # SQLite DB: sessions, messages, skills, todo lists
│   ├── .code_index.raggie     # SQLite DB: tree-sitter code index
│   └── git/                   # Local git repo for change tracking
└── requirements.txt           # pip dependencies
```

### How the Agent Works

1. **Startup**: The agent loads its role config, connects to the LLM API, indexes your codebase (tree-sitter, multiprocessing), and initialises its local git repo. Before the agent is created, the CLI entry point checks for a `.raggie` folder in the working directory and prompts the user if none is found.
2. **Prompt loop**: User sends a message → agent calls the LLM with full chat history + tool definitions → LLM responds with text and/or tool calls.
3. **Tool execution**: Each tool call is dispatched to a registered handler. Results are fed back to the LLM as tool responses.
4. **Re-indexing**: After each tool call, the code index is updated so the agent always has fresh context.
5. **Context handover**: When the context window is nearly full, the agent generates a detailed handover document and seamlessly continues in a new session. no lost progress.
6. **Auto-snapshot**: Before processing each prompt, the current working tree is committed as a snapshot (only if there are uncommitted changes). This ensures `/undo` always restores to a valid state.
7. **Commit**: When the agent finishes responding (no more tool calls), all changed files are committed to `.raggie/git/` (skipped if nothing changed).
8. **Health stats**: After the commit, the agent displays the most complex function by weighted branch count. Type `/health` for a full report.
9. **Undo/Redo**: Type `/undo` to undo the last commit and restore the previous state. Type `/redo` to re-apply an undone commit.

---

## Configuration

### User Config Directory

All user-specific config lives in `~/.config/raggie/`:

```
~/.config/raggie/
├── keys.json          # API keys (base_url -> key mappings)
├── roles.json         # Role definitions (copied from src/config/ on first run)
├── tools.json         # Tool definitions (copied from src/config/ on first run)
└── mcp_servers.json   # MCP server config (copied from src/config/ on first run)
```

### `roles.json`

Defines agent roles. Each role has a model, base URL, tools list, and system prompt.

```json
{
  "code": {
    "tools": ["WholeFileContentDump", "Shell", "WriteFile", ...],
    "model": "deepseek-v4-flash",
    "base_url": "https://api.deepseek.com",
    "system_prompt_file": "coder_system_prompt.md"
  }
}
```

### `AGENTS.md`

Place a file called `AGENTS.md` in the project root. Its contents are automatically appended to the agent's system prompt every time it starts. Useful for project-specific conventions:

```markdown
# Project Conventions
- Use TypeScript for all new files
- Tests go in a __tests__/ directory
- Follow the existing ESLint config
```

### `.gitignore` and `.aiignore`

Raggie uses ignore patterns to determine which files are off-limits. If a `.aiignore` file exists in the project root, it is used **instead of** `.gitignore` for both code indexing and agent file access enforcement. If no `.aiignore` exists, `.gitignore` is used as a fallback.

When `.aiignore` is active, files matched by its patterns cannot be read, written, modified, or indexed by the agent. This gives you a single file to control what the agent sees and touches, independently of your git configuration.

`.aiignore` uses the same pattern syntax as `.gitignore`.

---

## Using Local AI

Raggie works with any OpenAI-compatible local LLM server. Below are setup guides for the most popular options.

### Ollama

[Ollama](https://ollama.com) runs models locally with a built-in OpenAI-compatible endpoint.

1. **Install Ollama**: Follow the instructions at [ollama.com](https://ollama.com)
2. **Pull a model that supports tool calling** (not all models do):
   ```bash
   ollama pull qwen2.5:14b
   # or
   ollama pull llama3.1:8b
   ```
3. **Start the Ollama server** (it usually starts automatically):
   ```bash
   ollama serve
   ```
4. **Configure Raggie** — edit `~/.config/raggie/roles.json`:
   ```json
   {
     "code": {
       "model": "qwen2.5:14b",
       "base_url": "http://localhost:11434/v1/",
       "tools": ["..."],
       "system_prompt_file": "coder_system_prompt.md",
       "context_window": 32768,
       "reasoning": false,
       "stream": false
     }
   }
   ```
5. **Set the API key to `nokey`** — edit `~/.config/raggie/keys.json`:
   ```json
   {
     "http://localhost:11434/v1/": "nokey"
   }
   ```
   Raggie sees `nokey` and passes an empty API key to the client, which Ollama ignores.
6. **Run Raggie**:
   ```bash
   raggie code myproject
   ```

> **Note:** `context_window` should match the model's actual context length. For example, `qwen2.5:14b` supports 32768 tokens. Set this too high and the handover logic won't trigger when it should.

### vLLM

[vLLM](https://github.com/vllm-project/vllm) is a high-throughput inference engine with an OpenAI-compatible server.

1. **Install vLLM**:
   ```bash
   pip install vllm
   ```
2. **Start the server** with a tool-calling model:
   ```bash
   vllm serve Qwen/Qwen2.5-14B-Instruct --enable-auto-tool-choice --tool-call-parser hermes
   ```
3. **Configure Raggie** — edit `~/.config/raggie/roles.json`:
   ```json
   {
     "code": {
       "model": "Qwen/Qwen2.5-14B-Instruct",
       "base_url": "http://localhost:8000/v1/",
       "tools": ["..."],
       "system_prompt_file": "coder_system_prompt.md",
       "context_window": 32768,
       "reasoning": false,
       "stream": false
     }
   }
   ```
4. **Set the API key to `nokey`** — edit `~/.config/raggie/keys.json`:
   ```json
   {
     "http://localhost:8000/v1/": "nokey"
   }
   ```
5. **Run Raggie**:
   ```bash
   raggie code myproject
   ```

### LM Studio

[LM Studio](https://lmstudio.ai) provides a desktop GUI for running local models with an OpenAI-compatible server.

1. **Install LM Studio** from [lmstudio.ai](https://lmstudio.ai)
2. **Download a model** that supports tool calling (e.g. Qwen2.5, Llama 3.1)
3. **Start the local server**: In LM Studio, go to the "Local Server" tab, load your model, and click "Start Server". The default endpoint is `http://localhost:1234/v1/`
4. **Configure Raggie** — edit `~/.config/raggie/roles.json`:
   ```json
   {
     "code": {
       "model": "qwen2.5-14b-instruct",
       "base_url": "http://localhost:1234/v1/",
       "tools": ["..."],
       "system_prompt_file": "coder_system_prompt.md",
       "context_window": 32768,
       "reasoning": false,
       "stream": false
     }
   }
   ```
   > The `model` name must match what LM Studio shows as the loaded model identifier.
5. **Set the API key to `nokey`** — edit `~/.config/raggie/keys.json`:
   ```json
   {
     "http://localhost:1234/v1/": "nokey"
   }
   ```
6. **Run Raggie**:
   ```bash
   raggie code myproject
   ```

### General Notes for Local AI

- **Tool calling is required**: Raggie relies on function/tool calling. Not all models support this. Known good options include Qwen2.5 (7B+), Llama 3.1 (8B+), and Mistral (7B+). If the model doesn't support tool calls, Raggie won't be able to use its tools.
- **Context window**: Set `context_window` in `roles.json` to match the model's actual context length. This controls when the automatic handover kicks in. Too high = handover never triggers (API errors). Too low = handover triggers too often (wasted tokens).
- **Streaming**: Set `"stream": false` for local models. Streaming with tool calling can be unreliable with some local servers.
- **The `nokey` convention**: Any `base_url` in `keys.json` with the value `"nokey"` tells Raggie to skip authentication and pass an empty key to the OpenAI client.

---

## Tools Reference

Raggie provides 32 tools to the LLM. Here they are grouped by category:

### Code Exploration

this part is powered by the code indexer (code analysis and dependency tracking engine )

| Tool | What it does |
|---|---|
| `GetFileCodeSemantics` | Show a file's structure: functions, classes, imports, dependencies, with optional full source bodies |
| `GetSymbolSourceCode` | Get full source of a function/class/variable by name with fuzzy search fallback |
| `WalkCallTree` | BFS traversal of the call graph from any entry point (up to depth 5, cycle detection) |
| `WholeFileContentDump` | Read raw file contents (heavily throttled. prefer semantic tools first) |
| `Document` | Read or update persisted descriptions for symbols in the code index (experimental) |
| `ListDir` | List directory contents with type and size |
| `SearchAllFilesContent` | Regex grep across files/directories |
| `FileNameSearch` | Fuzzy search for file names by partial or approximate match (top 5 results) |

### File Operations

| Tool | What it does |
|---|---|
| `WriteFile` | Create or overwrite a file (auto-creates dirs, respects .gitignore) |
| `ReplaceText` | Find-and-replace in an existing file (literal or regex, supports replace_all) |
| `EditSymbol` | Replace the entire implementation of a function/method/class (or frontend entity) by name. returns a diff view |
| `RemoveFile` | Delete a file or directory (refuses gitignored paths) |
| `Shell` | Execute a shell command (for build, test, etc.) |
| `TempBackgroundService` | Start a temporary background service (non-blocking, returns PID) |
| `ShellKill` | Kill a background shell process by PID |

### Information Gathering

| Tool | What it does |
|---|---|
| `WebFetch` | Fetch a URL and return readable text (HTML stripped, configurable max chars) |
| `WebSearch` | Search the web via DuckDuckGo (up to 20 results, optional region) |
| `ReadImage` | Read an image file as vision input for the model (PNG, JPG, GIF, BMP, WEBP, SVG, TIFF, ICO, HEIC, HEIF) |

### Agent Management & Communication

| Tool | What it does |
|---|---|
| `DispatchSubagent` | Spawn a child agent to handle a subtask (nesting depth limited by the session's thinking mode) |
| `SetSkill` | Create/update a named skill for the agent's own role (requires user consent) |
| `GetSkill` | Fetch the full content of a skill by role and name |
| `ViewChanges` | Show git status, diff, or log from `.raggie/git/` |
| `AskUser` | Ask the user a question mid-task, optionally with predefined options (single or multiple choice, or free-form) |

### Todo Lists

| Tool | What it does |
|---|---|
| `CreateTodoList` | Create a new todo list |
| `AddTask` | Add a task with goal, requirements, notes, and order |
| `GetTodoList` | View the plan with all tasks and their status |
| `ApproveTodoList` | Present the plan to the user for y/n approval |
| `ExecuteNextTask` | Dispatch a subagent to execute the next pending task |
| `MarkTaskComplete` | Manually mark a task as done (auto-deletes todo list if all done) |
| `MarkTaskFailed` | Mark a task as failed |
| `MarkTaskCancelled` | Mark a task as cancelled (skipped intentionally) |
| `GetActiveTodoList` | Check for an incomplete todo list to resume |

---

## Skills System

Skills are named instruction sets stored in the database and advertised to the agent at startup. A role can have multiple skills, each identified by a unique name.

### How it works

1. **At startup**, all skills are listed as brief summaries in the system prompt (e.g. `code/testing: Always write tests after implementing...`)
2. **The LLM picks** the skill it needs and calls `GetSkill(role, name)` to fetch the full content
3. **The full skill content** is returned as a tool response, giving the agent detailed instructions for the task at hand

### Key characteristics

- **Persistent**: Skills survive across sessions
- **Multiple per role**: Each role can have many named skills (e.g. `code/testing`, `code/refactoring`, `code/git-workflow`)
- **On-demand loading**: Only summaries go into the system prompt. full content is fetched when needed, saving tokens
- **User-controlled**: The `SetSkill` tool always asks for user consent before applying changes
- **Override with AGENTS.md**: Project-specific instructions in `AGENTS.md` are appended after skills
- **Agent Skills standard**: Compatible with the [Agent Skills](https://agentskills.io) format (used by Claude). Import and export skill directories with `SKILL.md` files. Auto-discovers skills from project directories at startup

### Managing skills

```bash
# List all skills for a role
raggie skill code

# Show a specific skill
raggie skill code --show --name testing

# Import from a file
raggie skill code --import-skill my-skills.md --name testing

# Export to a file (backup)
raggie skill code --export-skill backup.md --name testing

# Delete a skill
raggie skill code --delete --name testing

# List all skills across all roles
raggie skill --list-all
```

### Agent Skills format (agentskills.io)

Raggie supports the [Agent Skills](https://agentskills.io) standard — the same format used by Anthropic's Claude. Each skill is a directory containing a `SKILL.md` file with YAML frontmatter:

```
my-skills/
├── web-testing/
│   └── SKILL.md
└── git-workflow/
    └── SKILL.md
```

A `SKILL.md` file looks like:

```markdown
---
name: web-testing
description: Systematic approach to testing web applications
---

# Web Testing Skill

When asked to test a web application, follow this approach:
1. Start with unit tests for individual components
2. Write integration tests for API endpoints
...
```

The `name` and `description` fields from the frontmatter are used as the skill's identity and summary in the system prompt (progressive disclosure). The markdown body is the full skill content loaded on demand via `GetSkill`.

**Importing:**
```bash
# Import a container directory (scans for subdirectories with SKILL.md)
raggie skill code --import-skill-dir ./my-skills/

# Import a single skill directory
raggie skill code --import-skill-dir ./my-skills/web-testing/
```

**Exporting:**
```bash
# Export a skill as an Agent Skills directory
raggie skill code --export-skill-dir ./exported/ --name web-testing
```

**Auto-discovery:**

At startup, Raggie scans the project root for skill directories and auto-imports any new skills (existing skills with the same name are not overwritten). The following directories are checked in order:

1. `.skills/` — Raggie-native skills directory
2. `skills/` — generic skills directory
3. `.claude/skills/` — Claude-compatible skills directory

Place your skill folders in any of these directories and they'll be available to the agent automatically on the next startup.

### How skills stack

At startup, the agent builds its system prompt in this order:

1. Role system prompt file (e.g. `coder_system_prompt.md`)
2. Current date, working directory, host system info
3. All skill summaries from database (role/name: one-line summary)
4. `AGENTS.md` from project root (if it exists)

---

## Todo List System

The todo list system lets the agent plan and execute complex multi-step tasks with user oversight.

### Workflow

```
1. GetActiveTodoList  →  check for existing incomplete todo list
2. CreateTodoList     →  create a new list
3. AddTask (x N)     →  add tasks with goals and requirements
4. GetTodoList        →  review the plan
5. ApproveTodoList    →  present to user for y/n approval
6. ExecuteNextTask    →  execute tasks one by one via subagents
```

### Key behaviors

- **Sequential execution**: Tasks run one at a time, never in parallel
- **Subagent isolation**: Each task is handled by a fresh subagent that receives context from completed tasks
- **Auto-deletion**: When all tasks are done, the todo list is automatically removed from the database
- **Crash recovery**: If the session is interrupted, `GetActiveTodoList` returns the incomplete list and the user is offered to resume it
- **Nested todo lists**: Subagents can create their own todo lists for complex subtasks (nesting depth limited by the session's thinking mode)

---

## Code Indexing

At startup and after every tool call, Raggie indexes your codebase using tree-sitter. This gives the agent:

- **Symbol definitions**: Functions, classes, methods, and their locations
- **Dependency graphs**: What calls what, what imports what
- **Call trees**: Full execution flow from any entry point
- **Fuzzy search**: Find symbols even if you don't know the exact name

### Supported languages

The code indexer supports 15 programming languages via tree-sitter grammars:

| Language | Extensions | What gets indexed |
|---|---|---|
| **Python** | `.py` | Functions, classes, methods, imports, variables, type aliases, docstrings, branches |
| **Go** | `.go` | Functions, methods (with receivers), structs, interfaces, type aliases, imports |
| **C#** | `.cs` | Methods, constructors, classes, records, interfaces, structs, enums, namespaces, properties, using directives |
| **JavaScript** | `.js`, `.jsx` | Functions, generator functions, classes, methods, imports, variables (var/let/const) |
| **TypeScript** | `.ts` | Functions, classes (incl. abstract), interfaces, type aliases, enums, public fields, imports |
| **TSX** | `.tsx` | Same as TypeScript, with JSX support |
| **Rust** | `.rs` | Functions, structs, enums, traits, impl blocks, constants, statics, type aliases, use declarations |
| **Zig** | `.zig` | Functions, variable declarations (const/var), `@import` calls |
| **Elixir** | `.ex`, `.exs` | `def`/`defp`/`defmacro` functions, `defmodule` modules, alias imports, assignments |
| **C** | `.c`, `.h` | Functions, structs, enums, typedefs, `#include` directives, macros |
| **C++** | `.cpp`, `.cc`, `.cxx`, `.hpp`, `.h`, `.hxx` | Functions, classes, structs, enums, type aliases, `#include` directives, macros |
| **PHP** | `.php` | Functions, methods, classes, interfaces, `use`/`include`/`require` imports |
| **Dart** | `.dart` | Function signatures, getters/setters, constructors, classes, mixins, extensions, imports |
| **Java** | `.java` | Methods, constructors, classes, records, annotation types, interfaces, enums, imports |
| **Kotlin** | `.kt`, `.kts` | Functions, classes, objects, interfaces, enums, type aliases, imports |

Languages are gracefully skipped if their tree-sitter grammar is not installed.

### Project directory detection

Before indexing, Raggie checks whether a `.raggie` folder exists in the current directory. This folder is created by Raggie on first run, so its presence means the user has already confirmed this is a project directory.

- **`.raggie` exists**: indexing proceeds automatically as normal.
- **No `.raggie` folder, but directory has no subdirectories**: indexing proceeds without prompting — a flat directory is small enough to be safe.
- **No `.raggie` folder, directory has subdirectories**: Raggie warns that the directory doesn't look like a project and asks whether to index anyway. This prevents accidentally scanning unrelated files (e.g. if you run `raggie code .` in your home directory). If you decline, Raggie exits and suggests you `cd` into your project directory or start a new one with `raggie code <project-name>`.
- **Subagent sessions**: subagents inherit the parent's `.raggie` folder (same working directory), so they always index normally.

You can manually trigger re-indexing at any time with the `/reindex` command.

### Data location

The index is stored in `.raggie/.code_index.raggie` (SQLite).

### `.aiignore`

The code indexer and agent file tools respect a `.aiignore` file in the project root. If present, it is used **instead of** `.gitignore` to determine which files are off-limits — for both indexing and file read/write/modify enforcement. If no `.aiignore` exists, `.gitignore` is used as a fallback.

This lets you control what the agent sees and touches independently of your git configuration. `.aiignore` uses the same pattern syntax as `.gitignore`.

### Indexing Performance

The indexer uses multiprocessing (tree-sitter parsing in parallel workers) with a sliding-window scheduler and a dedicated writer thread to keep both CPU and I/O saturated. Batch `executemany` inserts and a post-indexing dependency resolution pass minimize SQLite round-trips.

**Benchmark: Linux Kernel 7.1.1** (27844648 lines of code across 62,875 files)

| Phase | Time |
|---|---|
| File collection | ~4s |
| Changed-file detection | ~1.5s |
| Parse + insert (parallel) | ~521s |
| Dependency resolution | ~66s |
| **Total** | **~10m37s** |

Symbols indexed: 750K functions, 5.9M macros, 367K classes, 909K structs, 84K enums, 266K variables.

**Benchmark: Typical project** (a few hundred files)

Indexing completes in seconds. Re-indexing after a tool call is incremental — only changed files are re-parsed.

---

## Git Integration

Raggie maintains a local git repository at `.raggie/git/` for change tracking and rollback.

### How it works

1. **Before every prompt**: The agent auto-commits the current working tree state as a snapshot (only if there are uncommitted changes). This ensures `/undo` always has a valid previous state to restore, even on freshly initialized repos where the initial commit has an empty tree.
2. **After every response**: The agent commits all current project files to `.raggie/git/` (only if files changed — empty commits are skipped).
3. **Commit messages**: Include the user prompt, tool call count, and agent response summary
4. **Proper nested trees**: Subdirectories are stored as proper git tree objects (standard git compatible)
5. **Undo/Redo**: Type `/undo` to undo the last commit and restore files. Type `/redo` to re-apply an undone commit.

### Commands

```
/undo            →  Undo the last commit (restore previous state)
/redo            →  Redo the last undone commit (re-apply)
```

### The `ViewChanges` tool

The agent can introspect the git repo itself:

| view_type | What it shows |
|---|---|
| `status` | Files added/modified/deleted/unchanged since last commit |
| `diff` | Actual line-by-line diffs (with optional path filter and line limit) |
| `log` | Commit history (with configurable max count) |

### Ignore file support

- Files matched by `.aiignore` (or `.gitignore` as fallback) are excluded from commits and status checks
- Common exclusions are hardcoded as fallback: `.raggie`, `.git`, `.venv`, `__pycache__`, `build`, `dist`, `.egg-info`, and binary extensions

### Crash safety

The undo and redo operations write marker files (`.raggie/.undoing` and `.raggie/.redoing`) before deleting files, and remove them after successful restoration. If the process crashes mid-operation, the marker is detected on next startup and a warning is displayed. The redo stack (`.raggie/.redo_stack`) tracks undone commits so they can be re-applied; it is cleared when a new commit is made.

---

## Code Health

Raggie tracks code complexity using a weighted branch-count metric computed from the tree-sitter AST. After every main-agent response, a concise health summary is displayed showing the single most complex function. A full report can be generated on demand with `/health`.

### Complexity scoring

Each function's complexity score combines two factors:

```
score = round(branch_count / 30, 2) + (line_count / 100)
```

- **Branch count**: Weighted count of branching constructs (if/for/while/switch/try/match/etc.). Nested branches contribute more weight based on their nesting depth.
- **Line count**: Number of lines in the function body (`end_line - start_line + 1`).

### Nesting weight modes

The variable `NESTING_WEIGHT_MODE` in `src/indexing/node_utils.py` controls how branch-nesting depth maps to weight:

| Mode | Weight at depth 1/2/3/4/5 | Description |
|---|---|---|
| `"linear"` | 1, 2, 3, 4, 5 | Default — each nesting level adds +1 |
| `"flat"` | 1, 1, 1, 1, 1 | No nesting penalty — pure branch count |
| `"sqrt"` | 1.0, 1.4, 1.7, 2.0, 2.2 | Mild nesting penalty (square root) |
| `"quadratic"` | 1, 4, 9, 16, 25 | Harsh nesting penalty (squared) |

To change the mode, edit the single line in `node_utils.py`:

```python
NESTING_WEIGHT_MODE = "linear"  # "flat", "sqrt", or "quadratic"
```

This setting applies to all branch counting: regular functions, class methods, C/C++ preprocessor macros, and Rust `macro_rules!` entries.

### What counts as a branch

The following constructs are counted as branches (per language):

- **Conditionals**: `if`, `match`/`switch`, `try`/`catch`
- **Loops**: `for`, `while`, `do-while`, `foreach`, `loop` (Rust), range-based for (C++)
- **Elixir**: `call` nodes whose first identifier is `if`, `case`, `cond`, `try`, `receive`, `for`, `with`, or `unless`

Not counted: `goto`, `break`, `continue`, `return`, labeled jumps.

### Macros

C/C++ preprocessor macros (`preproc_def`, `preproc_function_def`) and Rust `macro_rules!` entries are indexed as separate function-like symbols with `type = "macro"`. Each macro receives its own branch count and appears in complexity queries and reports.

### Health stats output

After every main-agent response (subagents excluded), the agent displays:

```
health stats: (beta)
  _extract_symbols() in src/indexing/parse_worker.py:298  complexity: 15.5
  use /health to generate report
```

- The `health stats:` heading is yellow
- The complexity line is color-coded by severity:
  - **Green** — score ≤ 1.5 (clean)
  - **Yellow** — score > 1.5 (bloated)
  - **Red** — score > 3.5 (very blaot)
- The `/health` hint is gray
- If the codebase has no complex functions, the message "the codebase is healthy" is shown instead

### `/health` command

Generates a full complexity report as a `.txt` file in the current working directory (not under `.raggie/`). The filename format is `complexity_report_<YYYYMMDD_HHMMSS>.txt`.

The report includes:
- Timestamp
- Total functions with branches
- For each function (sorted by complexity score descending):
  - Function name
  - Source file and line number
  - Complexity score
  - Raw branch count
  - Line count

### Query: `get_top_complex_functions`

The SDK method `get_top_complex_functions(limit)` queries the `functions` table for all functions and methods with `branch_count > 0`, ordered by the complexity formula (`branch_count/30 + lines/100`) descending. This is used by both the health stats and the full report.

---

## ACP Agent Server

Raggie can run as a headless agent server speaking **ACP** (Agent Client Protocol), the JSON-RPC 2.0 protocol used by editors like Zed. All terminal I/O is routed through a configurable I/O backend, so stdout stays a clean protocol channel while human-facing output goes to stderr.

### Transports

| Flag | Transport | Use case |
|---|---|---|
| `--acp-stdio` | JSON-RPC over stdin/stdout | Editors that spawn the agent as a subprocess (Zed, custom editor integrations) |
| `--acp-http` | HTTP POST + SSE streaming | Web UIs, remote clients, service-style deployments |

### Running

```bash
# stdio mode (for Zed etc.)
raggie --acp-stdio

# HTTP mode (for web UIs)
raggie code --acp-http --acp-port 8765

# HTTP mode with auto-approve (no interactive permission prompts)
raggie code --acp-http --acp-port 8765 --acp-auto-approve
```

### How it works

- **Events**: Raggie's generator-based event stream (`response_chunk`, `reasoning_chunk`, `tool_call`, `tool_result`) is mapped onto ACP `session/update` notifications (`agent_message_chunk`, `agent_thought_chunk`, `tool_call`, `tool_call_update`)
- **Permissions**: Tool confirmations (shell commands, background services, skill creation) are bridged to the ACP client via `session/request_permission`. In stdio mode the editor shows the approval UI; in HTTP mode permissions are interactive for clients that answer `session/respond_permission` (the built-in web UI does), or answered by policy with `--acp-auto-approve` (deny by default)
- **Cancellation**: `session/cancel` sets a per-session cancel event checked between events
- **MCP integration**: MCP servers are connected during `session/new`, so external tools are available in ACP mode too

### Connecting from Zed

Add Raggie as an ACP agent in Zed's settings:

```json
{
  "agents": {
    "raggie": {
      "command": "raggie",
      "args": ["--acp-stdio"]
    }
  }
}
```

---

## Web UI

Raggie ships a built-in chat web UI. `raggie code --web` starts the agent and serves the UI (plus the ACP-over-HTTP JSON-RPC API) from a single process — no separate frontend deployment. The UI is rooted at the directory you run the command in: it lists your existing chats, streams responses, shows tool calls with their output, and surfaces the same permission prompts and "agent has a question" panels the terminal uses.

### Running

```bash
# from inside your project directory
raggie code --web               # serves http://127.0.0.1:8765

# isolated dev instance (uses .raggie-dev, never touches .raggie)
raggie code --web --dev

# custom port
raggie code --web --acp-port 9000
```

On startup the server prints the URL to open, e.g.:

```
raggie web ui: http://127.0.0.1:8765/?sid=1a2b3c4d
```

The link carries a unique session id (`?sid=...`) per running instance, so a stale tab opened against a different running instance is rejected. A chat is locked only while a turn/generation is running — not for the lifetime of the session. The lock is an OS-level file lock (an anchor file under `.raggie/locks/`) that is auto-released when the turn ends or the process exits; a second instance trying to generate into a locked chat gets an error instead of silently interleaving.

Everything works exactly like terminal mode — same chats, same `.raggie` data directory, same indexing, same git tracking. The server stays in the foreground; Ctrl+C stops it.

### Building the frontend

The UI ships pre-built inside the pip package (bundled from `web-ui/dist` via
`python sync_webui.py` at wheel-build time). In a source checkout the server
uses `web-ui/dist` directly; if neither exists, the server still starts and
the JSON-RPC API works, but `GET /` responds with 503 and a build hint:

```bash
cd web-ui && pnpm install && pnpm build && cd ..
```

When releasing, sync the fresh build into the package before building the
wheel so pip installs include it:

```bash
python sync_webui.py    # copies web-ui/dist -> src/acp_server/webui
python -m pip wheel . -w dist
```

For frontend development, run the backend in one terminal and Vite's dev server (with HMR) in another:

```bash
raggie code --web               # terminal 1 — backend on 8765
cd web-ui && pnpm dev           # terminal 2 — proxies POSTs to 8765
```

### What you get

- **Chat list** — resume any previous chat; new chats start with a codebase indexing pass ("Indexing codebase..." with the same loading state the terminal spinner uses)
- **Streaming** — responses and agent reasoning stream in live; tool calls appear as an expandable timeline with status and raw output
- **Permissions** — shell commands and background services show an Allow / Always Allow / Reject panel; the turn pauses until you answer
- **Questions** — when the agent uses `ask_user`, the question appears as an answer panel in the chat
- **Code health** — the health summary never mixes into the chat text; a `health` button in the header opens a modal with the stats (badge when fresh data arrives, refreshable on demand)
- **Cancel** — stop an in-flight turn; pending permission prompts are auto-denied so the agent stops cleanly

### API

The web UI talks to the same endpoint it is served from: JSON-RPC 2.0 `POST /`, with `session/prompt` streaming as Server-Sent Events. Standard ACP methods (`session/new`, `session/prompt`, `session/cancel`, ...) work as-is; the UI adds a few web-only extensions (`chats/list`, `chats/open`, `chats/history`, `health/stats`, `session/respond_permission`, `session/respond_ask`) documented in [`web-ui/README.md`](web-ui/README.md). You can build your own client against the same API.

---

## MCP Server Integration

Raggie can call tools from external **MCP** (Model Context Protocol) servers. This lets you extend the agent with tools like GitHub, filesystem access, database queries, or any of the growing ecosystem of MCP servers — without writing Raggie-specific tool handlers.

### Supported protocols and transports

| | stdio | Streamable HTTP |
|---|---|---|
| **2026-07-28** (stateless, "MCP 2.0") | ✓ | ✓ |
| **2025-era** (stateful) | ✓ | ✓ |

The official `mcp` Python SDK (v2.0.0) auto-negotiates the protocol version per server, so you don't need to know which revision a server speaks.

### Configuration

MCP servers are configured in `~/.config/raggie/mcp_servers.json`:

```json
{
  "filesystem": {
    "command": "npx",
    "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"],
    "trust": false
  },
  "github": {
    "url": "https://api.github.com/mcp",
    "trust": true
  }
}
```

| Field | Description |
|---|---|
| `command` | Executable to run for a stdio server |
| `args` | Arguments for the command |
| `env` | Environment variables (object) |
| `url` | URL for a Streamable HTTP server |
| `trust` | If `true`, skip per-call confirmation. Default: `false` |

### Managing servers

```bash
# Add a stdio server
raggie mcp --add filesystem --cmd npx --args -y @modelcontextprotocol/server-filesystem /tmp

# Add a trusted HTTP server
raggie mcp --add github --url https://api.github.com/mcp --trust

# List configured servers
raggie mcp --list

# Test connectivity and discover tools
raggie mcp --test filesystem

# Remove a server
raggie mcp --remove filesystem
```

### How tools appear to the agent

Tools from MCP servers are exposed as `mcp__<server>__<tool>` (e.g. `mcp__filesystem__read_file`) and merged into the agent's toolset alongside the 32 built-in tools. The LLM sees them as regular function calls — no special handling needed.

### Trust and permissions

- **Trusted servers** (`"trust": true`): tool calls execute immediately without asking
- **Untrusted servers** (default): each tool call requires user confirmation. In terminal mode this is a y/n prompt; in ACP mode it's routed through the editor's permission UI via `session/request_permission`

### Using MCP servers in ACP mode

MCP servers are connected during ACP `session/new`, so external tools are available when running Raggie as an agent server for editors. Permissions for untrusted MCP servers are bridged through the same ACP permission mechanism as built-in tools.

---

## FAQ

### Does my code get sent to an external API?

Yes. your prompts and the agent's responses are sent to the LLM provider you configure (OpenAI, OpenRouter, DeepSeek, etc.). The code index and git repo stay local.

### Can I use it with a local model?

Yes. Point `base_url` to any OpenAI-compatible local server (e.g. Ollama, vLLM, LocalAI) in your `~/.config/raggie/roles.json`.

### Where is my data stored?

```
.raggie/
├── .raggie.chat           # Chat sessions and messages
├── .code_index.raggie     # Tree-sitter code index
└── git/                   # Local git repository for changes
```

All of this is in your project directory and is gitignored by default.

### How do I stop the agent from making changes?

The agent only writes files when you explicitly ask it to. You can review changes before accepting them. The `/undo` command undoes the last set of changes, and `/redo` re-applies them.

### Can I customise the agent's behavior?

Yes. Create a `AGENTS.md` file in your project root with custom instructions. Edit `roles.json` to change models or tools per role. Use `raggie skill code --import-skill ... --name <name>` to add persistent named skills.

### What happens if I interrupt the agent mid-task?

Todo lists are persisted in the database. When you restart, the agent checks for incomplete todo lists and offers to resume them. If the process died mid-tool-call, the unanswered tool calls are detected and re-executed on resume (subagent dispatches and todo tasks resume their existing child sessions rather than starting over), and the chat history is validated and repaired before it is sent to the API. so a hard quit never corrupts a session. The git repo also has the last committed state for recovery.

### What happens when the context window fills up?

Raggie performs an **automatic session handover**. The agent generates a detailed handover document (original goal, current state, decisions made, changes applied, test results, errors, next step) and continues in a fresh session. so it can work on large tasks that exceed a single context window without losing progress.

### Can the agent ask me questions?

Yes. The `AskUser` tool lets the agent ask you questions mid-task, optionally with predefined options (single-choice, multiple-choice, or free-form). This means the agent can clarify requirements, confirm design decisions, or ask for preferences without guessing.

### Can I use Raggie in my editor (Zed, VS Code)?

Yes, via ACP. Run `raggie --acp-stdio` and configure it as an ACP agent in your editor. Zed has native ACP support; for VS Code you'd need a custom extension or webview panel that speaks ACP over HTTP (`--acp-http`). Or skip the editor integration entirely and use the built-in web UI: `raggie code --web`. See [ACP Agent Server](#acp-agent-server) and [Web UI](#web-ui).

### Can I extend Raggie with external tools?

Yes, via MCP. Any MCP-compatible server (GitHub, filesystem, databases, custom tools) can be added to `~/.config/raggie/mcp_servers.json` and its tools will be available to the agent as `mcp__<server>__<tool>`. Both stdio and HTTP servers are supported, across both protocol revisions. See [MCP Server Integration](#mcp-server-integration).

### License
```
Copyright 2026 Hussein Layth Al-Madhachi

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```
