# AGENTS.md Project-level context for AI agents working in this repository. ## Project Overview Ollie is an AI agent runtime inspired by Plan 9: agent state and behaviors are exposed as files in a 9P namespace. Orchestration, scheduling, and UIs are external — shell scripts, editors, web apps. The core is minimal; capabilities come from composing scripts. ## Repository Layout Monorepo with Git submodules. Each submodule has its own Go module (except `el` which is Elisp and `kde` which is C++/Qt). ``` ollie/ ← you are here ├── agent/ (Go) Agent loop, history, hooks, commands ├── toolsrv/ (Go) Tool server, registry, sandboxed execution ├── session/ (Go) Session lifecycle, config, persistence ├── fs/session/ (Go) 9P filesystem tree ├── dbus/ (Go) D-Bus adapter ├── cmd/ (Go) Binaries (olliesrv, ollie-9p, ollie-remote) ├── kde/ (C++/Qt6) KDE integration: plasmoid, GUI, Kate plugin, KRunner, tray ├── el/ (Elisp) Emacs frontend (ellie.el) ├── agents/ Agent config JSONs (loaded at runtime) ├── prompts/ System prompt templates (markdown) ├── tools/ Tool scripts (file_read, lsp_*, memory_*, etc.) ├── sandbox/ Landlock sandbox config YAML ├── scripts/ User-facing CLI scripts: │ ├── s/ Session management (sh, bfg, ls, kill, ...) │ ├── u/ Utilities (complete, optimize, cascade) │ └── x/ Internal/plumbing (elevate, prime, bd, task) ├── doc/ Architecture docs, usage guide ├── contrib/ Community scripts └── experiments/ Trial notes ``` ### Canonical source for prompts/tools/skills Prompt and tool files live in `data/`. The `just install-data` target copies them to `~/.config/ollie/`. **Do not edit `~/.config/ollie/` directly** — changes are overwritten on next install. | Location | Purpose | Deployed by | |----------|---------|-------------| | `data/prompts/`, `data/tools/` | Canonical source for all prompts, tools, and skills | `just install-data` | | `data/skills/` | Domain knowledge modules (markdown) | `just install-data` | | `kde/` | KDE-specific tool scripts (`gui_*`) | `just install-kde` | ## Build System ```bash # Build everything: just # Individual targets: just ninep # olliesrv + ollie-9p just acme # acme frontend just kde # KDE integration (cmake with ~/.local prefix) just ollie-remote # remote execution binary # Install targets (run automatically by the top-level paths): just install-data # agents, prompts, tools, skills → ~/.config/ollie/ just install-scripts # CLI scripts → ~/.config/ollie/scripts/ just install-contrib # contrib scripts → ~/bin/ just install-kde # KDE plugins, desktop file, env → ~/.local/ just install-el # ellie.el → ~/.config/emacs/ellie/ # Test: just test # run all tests just test-core # core tests only just test-9p # 9p tests only # Lifecycle: just uninstall # remove all installed files just clean # remove build artifacts ``` Requires [just](https://github.com/casey/just): `cargo install just` ## Testing ```bash # All Go tests: go test ./... # KDE has integration test scripts: cd kde && ./test-e2e.sh ``` ## Language & Conventions - **Go** (root module): Go 1.25+, standard library preferred, minimal dependencies. - **C++20/Qt6/KF6** (kde): CMake build, dual Qt5/Qt6 support where noted. - **Elisp** (el): single file `ellie.el`. - **Tool scripts**: Python 3, Bash, or compiled binaries. Must be executable. Metadata lives in a `.meta` sidecar JSON file (see `data/tools/*.meta`). ### Code style - Go: `gofmt`, short variable names, error returns (no panics), table-driven tests. - Tool scripts: emit structured output (`STATUS=ok`, `STATUS=error`). Image/LSP tools return JSON content blocks. - Prompts: markdown, concise, example-driven. Follow the pattern in existing `tools-*.md` files. ## Architecture (key concepts) 1. **Two integration surfaces**: 9P filesystem (sessions at `session/{id}/agent/{aid}/`) and D-Bus (`org.ollie.SessionManager`). Tools, skills, memory on physical filesystem via env vars. 2. **Agent loop** (`agent/loop.go`): Streaming LLM call → parse tool calls → dispatch → loop until no more tool calls or max steps. 3. **Tool dispatch** (`toolsrv/`): `shell` is built-in. All others are external scripts resolved from `OLLIE_TOOLS_PATH`. 4. **Sandbox** (`sandbox/`): Landlock-based. Config in `sandbox/*.yaml` defines filesystem access per profile. 5. **Backends** (`backend/`): Ollama, OpenAI-compatible, Anthropic, Copilot, Kiro, Gemini, CodeWhisperer. Selectable per-session. 6. **Prompts assembled at runtime**: Agent JSON `prompt` array runs shell commands (via `x/prime`) that cat markdown files together. No static prompt file is used directly. 7. **D-Bus** embedded in `olliesrv`: `org.ollie.SessionManager` exposed by the same binary as the 9P server. ## Key Files | What | Where | |------|-------| | Agent loop | `agent/loop.go` | | Tool server | `toolsrv/server.go` | | Remote execution | `toolsrv/remote.go`, `cmd/ollie-remote/` | | Sandbox enforcement | `sandbox/` | | 9P filesystem | `fs/session/` | | Session management | `session/session.go` | | System prompt template | Embedded in binary | | Agent configs | `agents/*.json` | | D-Bus adapter | `dbus/` | | KDE D-Bus client | `kde/plasmoid/plugin/olliedbusclient.cpp` | | Standalone GUI | `kde/gui/` | | Kate plugin | `kde/kate/` | ## Environment Config lives in `~/.config/ollie/env`. Key variables: - `OLLIE_BACKEND` — default backend (ollama, openai, anthropic, copilot, kiro) - `OLLIE_MODEL` — default model - `OLLIE_TOOLS_PATH` — where tool scripts live (default: `~/.config/ollie/tools`) - `OLLIE_MEMORY_PATH` — persistent memory directory - `OLLIE_ENABLED_BACKENDS` — backends available for routing ## Adding a new tool 1. Create an executable in `data/tools/` 2. Create a `.meta` sidecar file (`data/tools/.meta`) with JSON metadata: ```json {"description":"...","prompt":"...","args":{...},"tier":"hot","readOnly":false} ``` 3. Run `just install-data` to install ## Adding a new prompt 1. Write the markdown file in `data/prompts/` 2. If it should be loaded by default, reference it in `agents/default.json` 3. Run `just install-data` to install ## Submodule workflow The only remaining submodule is `kde/`. For KDE: ```bash # Update KDE submodule: git submodule update --remote --merge kde # Work in the KDE submodule: cd kde # ... make changes, commit ... git push cd .. git add kde git commit -m "update kde submodule" ``` Each submodule has its own remote at `ssh://lkn@lneely.de:44220/lkn/ollie-{name}.git`. When cloning, use `--recurse-submodules` or run `git submodule update --init --recursive`. ## Environment The only remaining submodule is `kde/`. For KDE: ```bash # Update KDE submodule: git submodule update --remote --merge kde # Work in the KDE submodule: cd kde # ... make changes, commit ... git push cd .. git add kde git commit -m "update kde submodule" ``` Each submodule has its own remote at `ssh://lkn@lneely.de:44220/lkn/ollie-{name}.git`. When cloning, use `--recurse-submodules` or run `git submodule update --init --recursive`.