diff --git a/README.md b/README.md
index 04b4779..93ccd0b 100644
--- a/README.md
+++ b/README.md
@@ -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
\ No newline at end of file
+GPLv3
diff --git a/doc/usage.md b/doc/usage.md
index 3521df4..4a3d804 100644
--- a/doc/usage.md
+++ b/doc/usage.md
@@ -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)
```
@@ -61,59 +62,70 @@ o read chat # stream chat output
+### Context model
+
+Context is determined by the first argument — not by environment variables:
+
+```
+o Root level (no context)
+o Session level
+o / Agent level
+```
+
+The slash in `/` 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] ` | Read a file (-l: loop, re-read after each return) |
-| `o write [data]` | Write to any file |
-| `o ls [path]` | List namespace entries |
-| `o ctl [args]` | Send control command (rdwr: gets response) |
-| `o generate ` | 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 [cwd]` | root | Create a new session |
+| `o generate ` | root | One-shot generation (no session needed) |
+| `o ls` | session | List session contents |
+| `o new [cwd]` | session | Create a new agent |
+| `o ctl ` | session | Session control |
+| `o / prompt` | agent | Interactive multi-line prompt REPL |
+| `o / tui` | agent | Launch tmux TUI |
+| `o / ctl ` | agent | Agent control (stop, compact, model, etc.) |
+| `o / log [-n N]` | agent | Show last N lines of agent log |
+| `o read [-l] ` | any | Read a file (-l: loop) |
+| `o write [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/`
+- Agent: `session//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 / 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 / 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:
@@ -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-`.
-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-`.
+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).
\ No newline at end of file
+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).