# 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 ├── core/ (Go) Core library: agent loop, backends, tools, config ├── 9p/ (Go) 9P filesystem server (olliesrv) ├── dbus/ (Go) D-Bus session manager daemon (ollied) ├── acme/ (Go) Plan 9 acme editor frontend ├── httpgw/ (Go) HTTP-to-9P gateway ├── webui/ (TypeScript) Preact SPA browser frontend ├── kde/ (C++/Qt6) KDE integration: plasmoid, standalone GUI, Kate plugin, KRunner, tray ├── el/ (Elisp) Emacs frontend (ellie.el) ├── agents/ Agent config JSONs (loaded at runtime) ├── prompts/ System prompt templates (markdown) ← NOT used; see note below ├── 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 Three locations have prompt and tool files. The **source of truth** depends on which component you're editing: | Location | Purpose | Deployed by | |----------|---------|-------------| | `9p/prompts/`, `9p/tools/` | Canonical source for the 9P server | `just install-data` | | `9p/skills/`, `kde/skills/` | Shared `agent-skills` submodule (same repo in both) | `just install-data` | | `kde/prompts/`, `kde/tools/` | KDE-specific copies (may diverge for KDE-only tools like `gui_*`) | `just install-kde` | | Root `prompts/`, `tools/` | Top-level copies installed by `just install-data` | `just install-data` | The `just install-data` target copies `agents/`, `prompts/`, `tools/`, `sandbox/` (and `skills/` from submodules) into `~/.config/ollie/`. **Do not edit `~/.config/ollie/` directly** — changes are overwritten on next install. When adding a new prompt/tool that should be available to all frontends, add it to both `9p/prompts/` (or `9p/tools/`) and the root `prompts/` (or `tools/`) directory. ## Build System ```bash # From monorepo root (pick one): just # 9P path (recommended): core, 9p, acme, kde, httpgw, webui, emacs just dbus # D-Bus path (KDE-only): core, ollied, kde, httpgw, webui # Individual build targets: just core # core library just ninep # 9P server just acme # acme frontend just kde # KDE integration (cmake with ~/.local prefix) just httpgw # HTTP gateway just webui # web UI (needs npm) just dbus-bin # D-Bus daemon (ollied) # 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/ just install-dbus-bin # ollied + autostart → ~/.local/bin/, ~/.config/autostart/ # Test: just test # run all tests (core + 9p) 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 # Go tests (from any Go submodule): go test ./... # Core has the most tests: cd core && go test ./... # 9P server tests: cd 9p && go test ./... # KDE has integration test scripts: cd kde && ./test-e2e.sh ``` ## Language & Conventions - **Go** (core, 9p, dbus, acme, httpgw): Go 1.25+, standard library preferred, minimal dependencies. Modules are `ollie` (core), `olliesrv` (9p), `ollie-dbus`, `ollie-acme`, `ollie-httpgw`. - **C++20/Qt6/KF6** (kde): CMake build, dual Qt5/Qt6 support where noted. - **TypeScript** (webui): Vite + Preact. - **Elisp** (el): single file `ellie.el`. - **Tool scripts**: Python 3 or Bash. Must be executable. Header comments declare metadata (`# ollie:parallel read`, `# ollie:tier cold`, `# description:`, `# args:`). ### 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 `s/{name}/`) and D-Bus (`org.ollie.SessionManager`). Tools, skills, memory on physical filesystem via env vars. 2. **Agent loop** (`core/pkg/agent/`): Streaming LLM call → parse tool calls → dispatch → loop until no more tool calls or max steps. 3. **Tool dispatch** (`core/pkg/tools/`): `execute_code` is built-in. All others are external scripts resolved from `OLLIE_TOOLS_PATH`. 4. **Sandbox** (`core/internal/sandbox/`): Landlock-based. Config in `sandbox/*.yaml` defines filesystem access per profile. 5. **Backends** (`core/pkg/backend/`): Ollama, OpenAI-compatible, Anthropic, Copilot, Kiro. 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** (kde/dbus only): `ollied` exposes `org.ollie.SessionManager` for KDE frontends. It's a separate daemon from `olliesrv`. ## Key Files | What | Where | |------|-------| | Agent loop | `core/pkg/agent/loop.go` | | Tool dispatcher | `core/pkg/tools/execute/` | | Remote execution client | `core/pkg/remote/remote.go` | | Remote execution server | `remote/main.go` | | Sandbox enforcement | `core/internal/sandbox/` | | 9P filesystem | `9p/fs/` | | Session management | `9p/session/` | | System prompt template | `prompts/SYSTEM_PROMPT.md` | | Agent configs | `agents/*.json` | | D-Bus daemon | `dbus/main.go` | | 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 script in `tools/` (and `9p/tools/`, `kde/tools/` if needed) 2. Add header comments: `# description:`, `# args:`, optionally `# ollie:parallel read` or `# ollie:tier cold` 3. Create a matching `prompts/tools-*.md` documentation file (and in `9p/prompts/`, `kde/prompts/`) 4. Run `just install-data` to install ## Adding a new prompt 1. Write the markdown file in `9p/prompts/` and root `prompts/` 2. If it should be loaded by default, add a `$OLLIE_CFG_PATH/scripts/x/prime ` entry to `agents/default.json` 3. Run `just install-data` to install ## Submodule workflow ```bash # Update all submodules: git submodule update --remote --merge # Work in a submodule (e.g., core): cd core # ... make changes, commit ... git push cd .. git add core git commit -m "update core submodule" ``` Each submodule has its own remote at `ssh://lkn@lneely.de:44220/lkn/ollie-{name}.git`. ### Nested submodules Both `9p/` and `kde/` contain a nested `skills/` submodule pointing to the same repo (`agent-skills.git`). There is no root-level `skills/` directory. ``` 9p/skills/ → ssh://lkn@lneely.de:44220/lkn/agent-skills.git kde/skills/ → ssh://lkn@lneely.de:44220/lkn/agent-skills.git (same repo) ``` When cloning, use `--recurse-submodules` or run `git submodule update --init --recursive` to get these.