9.8 KiB
Usage
Server
Start and stop
olliesrv # start the server (foreground)
# Stop by sending SIGTERM or via the supervisor (e.g. rc-service ollie stop)
TCP listener
To also accept connections over TCP (e.g. for remote access):
olliesrv -tcp :9564
Debug logging
Log level is controlled by OLLIE_LOG (default: warn). Set to debug for verbose output:
OLLIE_LOG=debug olliesrv
Valid levels: debug, info, warn, error.
Security and sandboxing
toolsrv applies the configured policy directly through native Landlock in a short-lived child helper; it does not depend on an external sandbox executable. On Linux, the helper creates and restricts a Landlock ruleset before executing the tool. Use yolo=true only for explicit development cases where enforcement should be disabled.
o — Terminal CLI
o is a multi-call shell script that wraps the 9P namespace into a human-friendly interface.
Installed to ~/.local/bin/o by make install-data.
Quick start
o myproj/default new # create session + agent
o myproj/default tui # launch the tmux TUI
Or without the TUI:
o myproject/default prompt # interactive prompt REPL (one terminal)
o myproject/default read chat # stream chat output (another terminal)
o tui — tmux + shell commands |
acme — Plan 9 editor |
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.
o ls lists the root of the ollie namespace; o with no arguments prints help.
Commands
| Command | Context | Description |
|---|---|---|
o ls |
root | List sessions, models, backends |
o generate <prompt> |
root | One-shot generation (no session needed) |
o <sess>/<agent> new [cwd] |
agent | Create session (if needed) + agent |
o <sess> ls |
session | List session contents |
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
When you supply a context, o sets a prefix:
- Session:
session/<sess> - Agent:
session/<sess>/agent/<agent>
Paths given to read, write, and ls are resolved relative to this prefix.
A leading / escapes the prefix and addresses the root namespace directly:
| 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 <session>/<agent> prompt is an interactive multi-line REPL:
$ o myproj/coding prompt
[myproj/coding]
Type . on a blank line to send, Ctrl+D to exit.
/ prefix runs ctl: /stop, /compact, /model X, /inject X
!q exits the TUI.
> write a fibonacci function in python
and include a test case
.
Type your prompt across multiple lines, then send with . on its own line.
Any agent ctl command works as a slash command — the / prefix is stripped
and the rest is sent to ctl:
| Command | Description |
|---|---|
/stop |
Interrupt running agent |
/compact |
Compact context window |
/clear |
Clear history |
/kill |
Kill the agent |
/model [X] |
Show or switch model |
/models |
List available models |
/backend |
Show current backend |
/agent [X] |
Show or switch agent profile |
/name [X] |
Show or set agent display name |
/cwd [X] |
Show or change working directory |
/inject X |
Inject text into context (alias: /i) |
/tools |
List loaded tools |
/tool_load X |
Load a tool |
/tool_unload X |
Unload a tool |
!q |
Kill the tmux TUI session and exit |
Piped input is also supported:
echo "explain this error" | o myproj/coding prompt
cat file.go | o myproj/coding write prompt
One-shot generation
No session or agent needed — o generate sends a prompt and returns a response:
o generate "explain monads in one sentence"
cat error.log | o generate # pipe content as the prompt
echo "write a haiku about filesystems" | o generate | wc -w
o tui — tmux Terminal UI
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:
Usage
o myproj/coding tui
- Creates a tmux session named
o-<session>. - 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).
- Pane 0 (top, 80%): streams chat output (log tail + live
- A background loop reads
statewaitand updates the tmux status bar on each state transition. - 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.
tmux tips
Ctrl+b ;— toggle between last two panes (fast prompt ↔ tail switch)Ctrl+b z— zoom any pane to full screenCtrl+b [— scroll mode (arrow keys,qto exit)Ctrl+b d— detach (session keeps running, reattach withtmux attach -t o-<session>)
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:
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.
Pair programming — observer agents
An observer agent watches your coding session and makes real-time observations: bugs, missed error handling, security issues. It uses the feed file — a change-detecting input present on every agent. The same mechanism works whether a human or another agent is coding.
Setup
# Create the observer (use the observer profile for read-only tools):
o myproj/obs new /path/to/repo
o myproj/obs ctl agent observer
Wire a human coding session
Poll git diffs and pipe into the observer's feed. The feed file deduplicates — same diff written twice is ignored:
while :; do git diff HEAD --; sleep 5; done | o myproj/obs write feed
Read observations in another terminal:
o myproj/obs read chat
Wire an agent coding session
Use statewait as the trigger — it blocks until the coder's state changes (turn completes). Then pipe in the git diff:
while :; do o myproj/coder read statewait >/dev/null; git diff HEAD --; done | o myproj/obs write feed
How it works
The feed file on each agent is a BlockOnce file:
- Write: stores the data + signals change.
- Read (blocking): blocks until the content changes from what it was when you opened. Returns new data once, then EOF.
- Dedup: built into the read side. Same content written repeatedly never wakes the reader.
Internally, each agent has a ConsumeFeed goroutine that reads from its own feed file (via 9P) and submits new data as prompts. The observer processes each diff it receives, optionally reads surrounding code for context, and produces terse observations.
Multiple observers
Nothing stops you from running N observers on the same coder:
# Security-focused observer:
o myproj/security new /path/to/repo
o myproj/security ctl agent observer
# Performance-focused observer (custom prompt):
o myproj/perf new /path/to/repo
# ... configure with a different prompt
# Same feed wiring for both:
while :; do git diff HEAD --; sleep 5; done | tee >(o myproj/security write feed) | o myproj/perf write feed
Other front-ends
- Session clients — shell, KDE, and other 9P clients
- KDE — plasmoid, standalone GUI, Kate plugin, KRunner
- acme — Plan 9 editor (scripts in
data/scripts/acme/)
For technical details on the raw 9P filesystem, see doc/architecture-9p.md.
For tool architecture and authoring, see architecture-tools.md.


