docs: update README and usage for current architecture

This commit is contained in:
Levi Neely 2026-08-12 18:06:22 +02:00
parent 23f3a6092b
commit 31d550a94b
2 changed files with 131 additions and 90 deletions

View File

@ -53,15 +53,15 @@ Everything lives under `$XDG_CONFIG_HOME/ollie/` (default: `~/.config/ollie/`)
| Capability | How |
|---|---|
| **CLI** | `o` — unified namespace CLI: `read`, `write`, `ls`, `ctl`, `prompt`, `tui`, `env`, `generate` |
| **CLI** | `o` — unified namespace CLI: `read`, `write`, `ls`, `new`, `ctl`, `prompt`, `tui`, `env`, `generate` |
| **Terminal TUI** | `o tui` — tmux layout, no widgets |
| **One-shot LLM** | `o generate "explain monads"` or `echo "prompt" \| o generate` |
| **Run an agent** | Create a session + agent via 9P — then connect with any frontend ([ellie](doc/ellie.md), KDE (GUI/KRunner/Kate), `o tui`) |
| **Run an agent** | Create a session + agent via 9P — then connect with any frontend ([ellie](doc/ellie.md), KDE (GUI/KRunner/Kate), acme, `o tui`) |
| **Remote execution** | Set `remote=user@host` in session config |
| **Background processes** | Pass `"background": true` to any tool — runs with no timeout, output pushed to agent prompt on completion |
| **Parallel execution** | Non-conflicting tool calls within a turn run in parallel (scope-based conflict scheduling) |
| **Agents** | Write a JSON config in `data/agents/` with agent prompt in `data/prompts/` |
| **Tools** | Drop an executable + `.meta` in `~/.config/ollie/tools/` — load at runtime via `/tool_load` |
| **Agents** | Write a JSON config in `~/.config/ollie/agents/` with agent prompt in `~/.config/ollie/prompts/` |
| **Tools** | Drop an executable + `.meta` in `~/.config/ollie/tools/` — load at runtime via `tool_load` |
| **Domain skills** | Load markdown skill modules at runtime |
## Repository layout
@ -70,28 +70,42 @@ Single Go module with one Git submodule (kde).
| Directory | Language | Description |
|-----------|----------|-------------|
| `agent/` | Go | Agent loop, history, prompt resolution, context compaction |
| `backend/` | Go | LLM providers (Anthropic, OpenAI, Ollama, Gemini, Copilot, CodeWhisperer) |
| `toolsrv/` | Go | Tool server client library (9P client for toolsrv) |
| `cmd/toolsrv/` | Go | Tool execution server (separate 9P server, sandboxed execution) |
| `tools/lsp/` | Go | LSP bridge daemon + client library (gopls, clangd, intelephense) |
| `session/` | Go | Session lifecycle, config, persistence |
| `fs/` | Go | 9P filesystem tree (EDSL-declared namespace, ctl dispatch) |
| `fsedsl/` | Go | Filesystem declaration EDSL (generic, reusable) |
| `bypass/` | Go | Bypass broker (sandbox escape approval) |
| `sandbox/` | Go | Landlock sandbox config |
| `lib9p/` | Go | 9P protocol library + native C client |
| `cmd/olliesrv/` | Go | The main server binary (session/agent 9P namespace) |
| `cmd/toolsrv/` | Go | Tool execution server (spawned by olliesrv, separate 9P server) |
| `cmd/toolsrv/` | Go | Tool execution server (separate 9P server, sandboxed execution) |
| `cmd/ollie-9p/` | Go | 9P client CLI |
| `cmd/ollie-remote/` | Go | Remote execution binary |
| `toolsrv/` | Go | Tool server client library + tool discovery (9P client for toolsrv) |
| `virtfs/` | Go | Filesystem declaration EDSL (generic, reusable) |
| `lib9p/` | Go | 9P protocol library + native C client |
| `tools/lsp/` | Go | LSP bridge daemon + client library (gopls, clangd, intelephense) |
| `env/` | Go | Environment variable defaults |
| `format/` | Go | Output formatting |
| `log/` | Go | Structured logging |
| `paths/` | Go | XDG path resolution |
| `kde/` | C++/Qt6 | KDE plasmoid, GUI, Kate plugin, KRunner *(submodule)* |
| `data/agents/` | JSON | Agent configs |
| `contrib/elisp/` | Emacs Lisp | ellie.el — Emacs frontend |
| `data/agents/` | JSON | Agent configs (installed to `~/.config/ollie/agents/`) |
| `data/prompts/` | Markdown | System prompt templates |
| `data/tools/` | Mixed | Tool executables (scripts + compiled) + `.meta` sidecar files |
| `data/skills/` | Markdown | Domain knowledge modules |
| `data/scripts/` | Shell | CLI scripts (`o`, `ollie-remount`, acme helpers) |
| `doc/` | Markdown | Architecture docs, usage guide |
### Internal packages (not importable outside their command)
| Package | Parent | Description |
|---------|--------|-------------|
| `agent` | `cmd/olliesrv` | Agent loop, history, prompt resolution, context compaction |
| `backend` | `cmd/olliesrv` | LLM providers (Anthropic, OpenAI/OpenRouter, Ollama, Gemini, Copilot, Kiro) |
| `session` | `cmd/olliesrv` | Session lifecycle, config, persistence |
| `fs` | `cmd/olliesrv` | 9P filesystem tree (virtfs-declared namespace, ctl dispatch) |
| `bypass` | `cmd/olliesrv` | Bypass broker (sandbox escape approval) |
| `toolclient` | `cmd/olliesrv` | Spawns and connects to toolsrv |
| `prompts` | `cmd/olliesrv` | Prompt template resolution |
| `registry` | `cmd/toolsrv` | Per-agent tool registry |
| `exec` | `cmd/toolsrv` | Sandboxed tool execution |
| `sandbox` | `cmd/toolsrv` | Landlock sandbox config and wrapper |
| `server` | `cmd/toolsrv` | 9P filesystem + proc management |
## Architecture
```mermaid
@ -126,6 +140,7 @@ graph TB
ANT[Anthropic]
COP[Copilot]
KIRO[Kiro]
GEM[Gemini]
end
TUI & SCRIPTS & ACME --> O
@ -135,7 +150,7 @@ graph TB
SESS --> AG
SESS -->|9P over Unix socket| TOOLS
AG -->|streaming| OLL & OAI & ANT & COP & KIRO
AG -->|streaming| OLL & OAI & ANT & COP & KIRO & GEM
TOOLS --> EXEC
```
@ -156,4 +171,4 @@ filesystem, see [`doc/9p.md`](doc/9p.md).
## License
GPLv3
GPLv3

View File

@ -32,20 +32,21 @@ Valid levels: `debug`, `info`, `warn`, `error`.
## `o` — Terminal CLI
`o` is a multi-call shell script that wraps the 9P namespace into a human-friendly interface.
Installed to `~/bin/o` by `just install-data`.
Installed to `~/.local/bin/o` by `just install-data`.
### Quick start
```sh
eval $(o env myproject default) # set session + agent context
o prompt # interactive prompt REPL
o new myproject # create a session
o myproject new default # create an agent in that session
o myproject/default tui # launch the tmux TUI
```
In another terminal:
Or without the TUI:
```sh
eval $(o env myproject default)
o read chat # stream chat output
o myproject/default prompt # interactive prompt REPL (one terminal)
o myproject/default read chat # stream chat output (another terminal)
```
<table align="center" width="90%">
@ -61,59 +62,70 @@ o read chat # stream chat output
</tr>
</table>
### Context model
Context is determined by the first argument — not by environment variables:
```
o <cmd> Root level (no context)
o <session> <cmd> Session level
o <session>/<agent> <cmd> Agent level
```
The slash in `<session>/<agent>` disambiguates session-only from session+agent.
If no command follows the context, `o` defaults to `ls`.
### Commands
| Command | Description |
|---|---|
| `o prompt` | Interactive multi-line prompt REPL |
| `o read [-l] <path>` | Read a file (-l: loop, re-read after each return) |
| `o write <path> [data]` | Write to any file |
| `o ls [path]` | List namespace entries |
| `o ctl <cmd> [args]` | Send control command (rdwr: gets response) |
| `o generate <prompt>` | One-shot generation (no session needed) |
| `o tui` | Launch tmux TUI |
| `o env [session] [agent]` | Print export statements for context |
### Context
Context is set via `$session` and `$agent` environment variables:
```sh
eval $(o env myproject default) # export session=myproject agent=default
# Now every o command addresses the right agent automatically:
o ctl model # → shows current model
o read -l statewait
```
| Command | Context | Description |
|---|---|---|
| `o ls` | root | List sessions, models, backends |
| `o new <session> [cwd]` | root | Create a new session |
| `o generate <prompt>` | root | One-shot generation (no session needed) |
| `o <sess> ls` | session | List session contents |
| `o <sess> new <agent> [cwd]` | session | Create a new agent |
| `o <sess> ctl <cmd>` | session | Session control |
| `o <sess>/<agent> prompt` | agent | Interactive multi-line prompt REPL |
| `o <sess>/<agent> tui` | agent | Launch tmux TUI |
| `o <sess>/<agent> ctl <cmd>` | agent | Agent control (stop, compact, model, etc.) |
| `o <sess>/<agent> log [-n N]` | agent | Show last N lines of agent log |
| `o read [-l] <path>` | any | Read a file (-l: loop) |
| `o write <path> [data]` | any | Write to a file (args or stdin) |
| `o env` | any | Print export statements for current context |
| `o help` | any | Show help |
### Path resolution
Paths are slash-delimited 9P namespace paths. The `o` CLI resolves them based
on context:
When you supply a context, `o` sets a **prefix**:
- Session: `session/<sess>`
- Agent: `session/<sess>/agent/<agent>`
| Path type | Example | Resolves to |
|---|---|---|
| Root-level | `o read models` | `models` (no context needed) |
| Agent file | `o read state` | `session/$session/agent/$agent/state` |
| Session file | `o read env` | `session/$session/env` |
| Full path | `o read session/foo/agent/bar/chat` | Used as-is |
Paths given to `read`, `write`, and `ls` are resolved relative to this prefix.
A leading `/` escapes the prefix and addresses the root namespace directly:
Root-level paths (`session/`, `agents`, `models`, `help`, `ctl`, `tools`) and
absolute paths (starting with `session/`) bypass context resolution entirely.
Agent-level files (`chat`, `state`, `prompt`, `statewait`, `cfg`, `plan`,
`log`, `cost`, `offset`, `context`, `systemprompt`) require both `$session`
and `$agent`. Session-level files (`env`, `ctl`, `id`, `name`, `paused`)
require only `$session`.
| Invocation | Resolves to |
|---|---|
| `o myproj/coding read chat` | `session/myproj/agent/coding/chat` |
| `o myproj/coding read cfg` | `session/myproj/agent/coding/cfg` |
| `o myproj read env` | `session/myproj/env` |
| `o myproj/coding read /models` | `models` (root) |
| `o myproj/coding ls /bypass` | `bypass` (root) |
| `o read models` | `models` (no context, no prefix) |
The leading slash is necessary when you want to access root-level paths
(like `models`, `backends`, `bypass/`) while in session or agent context.
Without it, the path is concatenated with the context prefix.
### Prompt REPL
`o prompt` is an interactive multi-line REPL with readline editing:
`o <session>/<agent> prompt` is an interactive multi-line REPL:
```
$ o prompt
[myproject/default]
$ o myproj/coding prompt
[myproj/coding]
Type . on a blank line to send, Ctrl+D to exit.
Slash commands: /stop /compact /kill /clear /model /backend /cwd /help
/ prefix runs ctl: /stop, /compact, /model X, /inject X
!q exits the TUI.
> write a fibonacci function in python
and include a test case
@ -127,13 +139,16 @@ Slash commands control the agent without sending a prompt:
|---|---|
| `/stop` | Interrupt running agent |
| `/compact` | Compact context window |
| `/kill` | Kill the session (exits REPL) |
| `/clear` | Clear history |
| `/model X` | Switch model |
| `/backend X` | Switch backend |
| `/cwd X` | Change working directory |
| `/quit` or `/q` | Kill the tmux TUI |
| `/help` | List commands |
| `!q` | Kill the tmux TUI session and exit |
Piped input is also supported:
```sh
echo "explain this error" | o myproj/coding prompt
cat file.go | o myproj/coding write prompt
```
### One-shot generation
@ -145,18 +160,13 @@ cat error.log | o generate # pipe content as the prompt
echo "write a haiku about filesystems" | o generate | wc -w
```
Chain multiple steps:
```sh
echo "list 5 blog post ideas" | o generate | head -3 | o generate
```
---
## `o tui` — tmux Terminal UI
`o tui` composes `o read chat` and `o prompt` into a single tmux layout — two shell
commands in two panes, with agent state in the tmux status bar:
`o <session>/<agent> tui` composes `o read chat` and `o prompt` into a single
tmux layout — two shell commands in two panes, with agent state in the tmux
status bar:
<p align="center">
<a href="img/ollie-tui.png"><img src="img/ollie-tui.png" alt="Screenshot of the o tui tmux layout: chat pane on top, prompt REPL on bottom, agent state in status bar" width="75%"></a>
@ -165,17 +175,15 @@ commands in two panes, with agent state in the tmux status bar:
### Usage
```sh
eval $(o env myproject default)
o tui
o myproj/coding tui
```
1. Requires `$session` and `$agent` to be set.
2. Creates a tmux session named `o-<session>`.
3. Two panes:
- **Pane 0** (top, 80%): `o read chat` — streams filtered chat output (markers stripped server-side).
1. Creates a tmux session named `o-<session>`.
2. Two panes:
- **Pane 0** (top, 80%): streams chat output (log tail + live `read chat`).
- **Pane 1** (bottom, 20%): `o prompt` — multi-line REPL (`/` prefix runs ctl commands).
4. A background loop reads `statewait` and updates the tmux status bar instantly.
5. Focuses the prompt pane and attaches.
3. A background loop reads `statewait` and updates the tmux status bar on each state transition.
4. Focuses the prompt pane and attaches.
No polling. Each read blocks until data arrives. The status bar updates on every
state transition via `statewait` — zero CPU when idle.
@ -189,10 +197,28 @@ state transition via `statewait` — zero CPU when idle.
---
## `o env` — Context export
`o env` prints export statements for the current context. This is useful for
other tools (raw `ollie-9p` commands, scripts) that need to know which session
and agent are being addressed:
```sh
eval $(o myproj/coding env)
# exports OLLIE_SESSION=myproj OLLIE_AGENT=coding
ollie-9p read session/$OLLIE_SESSION/agent/$OLLIE_AGENT/stats
```
Note: `o` itself does not read these environment variables — it determines
context purely from its positional arguments.
---
## Other front-ends
- **[ellie](ellie.md)** — Emacs session tree, chat, multi-agent
- **KDE** — plasmoid, standalone GUI, Kate plugin, KRunner
- **[KDE](kde-gui.md)** — plasmoid, standalone GUI, Kate plugin, KRunner
- **acme** — Plan 9 editor (scripts in `data/scripts/acme/`)
For technical details (generation parameters, sandboxing, multi-agent workflows,
tool discovery, and the raw 9P filesystem), see [doc/whitepaper.md](whitepaper.md).
For technical details on the raw 9P filesystem, see [`doc/9p.md`](9p.md).
For tool authoring, see [`doc/writing-tools.md`](writing-tools.md).