Edit README for clarity and concision
- Tighten architecture, requirements, and usage sections - Condense UI sections (TUI, Emacs, web, Acme) - compact key lists - Streamline 9P filesystem, beads, events, mailbox sections - Condense workflow examples and self-healing explanation - Remove redundant statements and obvious details - 78 lines removed (35% reduction)
This commit is contained in:
parent
8e421ead7d
commit
2b101355e9
222
README.md
222
README.md
|
|
@ -1,31 +1,31 @@
|
|||
# AnviLLM
|
||||
|
||||
9P-based LLM orchestrator. Front-ends for Acme, Emacs, TUI, and web.
|
||||
9P-based LLM orchestrator with multiple front-ends: Acme, Emacs, TUI, and web.
|
||||
|
||||
## Architecture
|
||||
|
||||
AnviLLM consists of:
|
||||
**Core:**
|
||||
- **anvilsrv** - Background daemon exposing sessions via 9P filesystem
|
||||
- **anvilmcp** - MCP server for Model Context Protocol integration
|
||||
|
||||
- **anvilsrv**: Background daemon managing sessions via 9P
|
||||
- **anvilmcp**: MCP server exposing AnviLLM via Model Context Protocol
|
||||
- **Assist**: Acme UI client (auto-starts daemon if needed)
|
||||
- **anvillm.el**: For our emacs friends ;)
|
||||
- **anvillm**: Terminal UI (curses-based) for everyone else
|
||||
- **anvilweb**: Web interface for browser-based access
|
||||
**Clients:**
|
||||
- **Assist** - Acme UI (auto-starts daemon)
|
||||
- **anvillm.el** - Emacs interface
|
||||
- **anvillm** - Terminal UI (curses)
|
||||
- **anvilweb** - Web interface
|
||||
|
||||
This separation allows:
|
||||
- Multiple clients to connect to the same sessions
|
||||
- Server survives client crashes/restarts
|
||||
- Scriptable workflows via 9P without UI dependencies
|
||||
- Service management (systemd/runit integration)
|
||||
- Choice of interface: Acme, terminal, Emacs, or web browser
|
||||
- Integration with MCP-compatible tools (Claude Desktop, Cline, etc.)
|
||||
**Benefits:**
|
||||
- Multiple clients share sessions
|
||||
- Sessions survive client crashes
|
||||
- Scriptable workflows via 9P
|
||||
- Service management (systemd/runit)
|
||||
- MCP integration (Claude Desktop, Cline, etc.)
|
||||
|
||||
## Requirements
|
||||
|
||||
- Go 1.21+, plan9port, tmux
|
||||
- [landrun](https://github.com/zouuup/landrun) (sandboxing, Linux kernel 5.13+)
|
||||
- Backend CLI: [Claude Code](https://github.com/anthropics/claude-code) or [Kiro CLI](https://kiro.dev)
|
||||
- [landrun](https://github.com/zouuup/landrun) for sandboxing (Linux kernel 5.13+)
|
||||
- Backend: [Claude Code](https://github.com/anthropics/claude-code) or [Kiro CLI](https://kiro.dev)
|
||||
|
||||
## Installation
|
||||
|
||||
|
|
@ -74,140 +74,87 @@ anvilsrv stop # Shutdown
|
|||
|
||||
### Multiple Namespaces
|
||||
|
||||
`anvilsrv` respects the `$NAMESPACE` environment variable, allowing multiple independent instances for different Acme sessions (similar to running multiple Acme instances with `acme -a`).
|
||||
Run multiple independent instances using `$NAMESPACE` (similar to `acme -a`).
|
||||
|
||||
**Default namespace**: `/tmp/ns.$USER.:0`
|
||||
**Default:** `/tmp/ns.$USER.:0`
|
||||
|
||||
**Example: Running multiple instances**
|
||||
**Example:**
|
||||
```sh
|
||||
# Start default instance (namespace :0)
|
||||
# Start default instance (:0)
|
||||
anvilsrv start
|
||||
|
||||
# Start second instance (namespace :1)
|
||||
# Start second instance (:1)
|
||||
NAMESPACE=/tmp/ns.$USER.:1 anvilsrv start
|
||||
|
||||
# Check status of each instance
|
||||
# Check status
|
||||
anvilsrv status # :0
|
||||
NAMESPACE=/tmp/ns.$USER.:1 anvilsrv status # :1
|
||||
|
||||
# Each instance has isolated:
|
||||
# - PID file: $NAMESPACE/anvilsrv.pid
|
||||
# - 9P socket: $NAMESPACE/agent
|
||||
# - Session list (completely independent)
|
||||
|
||||
# Connect Assist to specific instance
|
||||
NAMESPACE=/tmp/ns.$USER.:1 Assist
|
||||
```
|
||||
|
||||
This enables running separate AnviLLM environments for different projects or Acme workspaces.
|
||||
Each instance has isolated PID file, 9P socket, and session list.
|
||||
|
||||
### Terminal UI (anvillm)
|
||||
|
||||
Run `anvillm` for a curses-based interface (no Acme required):
|
||||
Curses-based interface (no Acme required):
|
||||
|
||||
```sh
|
||||
anvillm
|
||||
```
|
||||
|
||||
**Keyboard shortcuts:**
|
||||
- `s` - Start new session (shows backend menu)
|
||||
- `p` - Send prompt to selected session
|
||||
- `t` - Stop selected session
|
||||
- `R` - Restart selected session
|
||||
- `K` - Kill selected session
|
||||
- `a` - Set session alias
|
||||
- `r` - Refresh session list
|
||||
- `d` - Daemon status
|
||||
- `?` - Help
|
||||
- `q` - Quit
|
||||
**Keys:** `s` start | `p` prompt | `t` stop | `R` restart | `K` kill | `a` alias | `r` refresh | `d` daemon | `?` help | `q` quit
|
||||
|
||||
To attach to the anvillm session, simply open a different terminal and use `tmux attach`.
|
||||
**Navigation:** Arrow keys, vim (`j`/`k`), or emacs (`C-n`/`C-p`)
|
||||
|
||||
**Navigation:**
|
||||
- Arrow keys (`↑`/`↓`)
|
||||
- Vim-style (`j`/`k`)
|
||||
- Emacs-style (`C-n`/`C-p`)
|
||||
|
||||
Like Assist, the TUI reads/writes the 9P filesystem for all operations.
|
||||
Attach to tmux session from another terminal with `tmux attach`.
|
||||
|
||||
### Emacs Interface (anvillm.el)
|
||||
|
||||
Run `M-x anvillm` in Emacs for a native Emacs interface:
|
||||
|
||||
**Installation:**
|
||||
|
||||
Copy anvillm.el to ~/.emacs.d/lisp/ or wherever your elisp files live. Then, add to your emacs init:
|
||||
|
||||
```elisp
|
||||
(add-to-list 'load-path "/path/to/anvillm.el/")
|
||||
(require 'anvillm)
|
||||
```
|
||||
|
||||
**Keybindings:**
|
||||
**Usage:** `M-x anvillm`
|
||||
|
||||
- s - Start new session (select backend)
|
||||
- p - Send prompt to selected session
|
||||
- P - Send prompt to selected session using minibuffer
|
||||
- t - Stop selected session
|
||||
- R - Restart selected session
|
||||
- K - Kill selected session
|
||||
- a - Set alias for selected session
|
||||
- r - Refresh session list
|
||||
- g - Refresh session list (standard Emacs binding)
|
||||
- d - Daemon status
|
||||
- q - Quit
|
||||
- ? - Help
|
||||
**Keys:** `s` start | `p` prompt | `P` prompt (minibuffer) | `t` stop | `R` restart | `K` kill | `a` alias | `r`/`g` refresh | `d` daemon | `q` quit | `?` help
|
||||
|
||||
**Navigation:**
|
||||
- Standard Emacs navigation (`n`, `p`, `C-n`, `C-p`)
|
||||
- Sessions displayed in a sortable table (click column headers)
|
||||
|
||||
The Emacs interface uses the `9p` command from plan9port to interact with the filesystem.
|
||||
**Navigation:** Standard Emacs (`n`, `p`, `C-n`, `C-p`). Click column headers to sort.
|
||||
|
||||
### Web Interface (anvilweb)
|
||||
|
||||
Run `anvilweb` for a browser-based interface:
|
||||
|
||||
```sh
|
||||
anvilweb # starts on :8080
|
||||
anvilweb -addr :3000 # custom port
|
||||
```
|
||||
|
||||
**Features:**
|
||||
- Start new sessions (Kiro/Claude)
|
||||
- View all sessions with live state updates
|
||||
- Send prompts, edit context and aliases
|
||||
- Stop/restart/kill sessions
|
||||
- Auto-refreshes every 5 seconds
|
||||
**Features:** Start sessions, send prompts, edit context/aliases, stop/restart/kill. Auto-refreshes every 5 seconds.
|
||||
|
||||
**Security Warning:**
|
||||
**⚠️ Security Warning:**
|
||||
|
||||
⚠️ **The web interface has NO authentication.** Anyone who can reach the server port can:
|
||||
- View all sessions
|
||||
- Send prompts to any session
|
||||
- Start/stop/kill sessions
|
||||
- Modify session contexts
|
||||
**NO authentication.** Anyone with network access can control all sessions.
|
||||
|
||||
**Only run anvilweb on localhost or trusted networks.** For remote access, use SSH port forwarding:
|
||||
**Only run on localhost or trusted networks.** For remote access, use SSH port forwarding:
|
||||
|
||||
```sh
|
||||
# On remote machine
|
||||
# Remote machine
|
||||
anvilweb -addr localhost:8080
|
||||
|
||||
# On local machine
|
||||
# Local machine
|
||||
ssh -L 8080:localhost:8080 user@remote
|
||||
# Then browse to http://localhost:8080
|
||||
# Browse to http://localhost:8080
|
||||
```
|
||||
|
||||
Or use a reverse proxy with authentication (nginx, caddy, etc.).
|
||||
Or use a reverse proxy with authentication (nginx, caddy).
|
||||
|
||||
### Acme Interface (Assist)
|
||||
|
||||
Type `Assist` in Acme and middle-click to open the `/AnviLLM/` session manager.
|
||||
Type `Assist` in Acme and middle-click to open `/AnviLLM/` session manager.
|
||||
|
||||
### Commands
|
||||
|
||||
**Main window** (`/AnviLLM/`) tag: `Get Attach Stop Restart Kill Alias Context Log Daemon Inbox Archive`
|
||||
**Main window tag:** `Get Attach Stop Restart Kill Alias Context Log Daemon Inbox Archive`
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
|
|
@ -224,17 +171,13 @@ Type `Assist` in Acme and middle-click to open the `/AnviLLM/` session manager.
|
|||
| `Inbox [id]` | View inbox messages (default: user) |
|
||||
| `Archive [id]` | View archived messages (default: user) |
|
||||
|
||||
Right-click a session ID to open its prompt window. Select text anywhere and 2-1 chord on a session ID for fire-and-forget prompts.
|
||||
Right-click session ID to open prompt window. Select text and 2-1 chord on session ID for fire-and-forget prompts.
|
||||
|
||||
**Note**: Assist reconnects to the running `anvilsrv` daemon, so sessions persist across Assist restarts.
|
||||
|
||||
**Prompt window** (`+Prompt.<id>`) tag: `Send`
|
||||
|
||||
Type prompt, click `Send`.
|
||||
**Prompt window tag:** `Send`
|
||||
|
||||
## 9P Filesystem
|
||||
|
||||
The `anvilsrv` daemon exposes sessions via a 9P filesystem at `$NAMESPACE/agent` (typically `/tmp/ns.$USER/agent`).
|
||||
`anvilsrv` exposes sessions at `$NAMESPACE/agent` (typically `/tmp/ns.$USER/agent`):
|
||||
|
||||
```
|
||||
agent/
|
||||
|
|
@ -265,11 +208,11 @@ agent/
|
|||
└── archive # Archived messages (JSON)
|
||||
```
|
||||
|
||||
**Path Validation**: Session creation validates and cleans paths (e.g., `/../../../etc` → `/etc`), and rejects nonexistent directories.
|
||||
**Path Validation:** Session creation validates paths (e.g., `/../../../etc` → `/etc`) and rejects nonexistent directories.
|
||||
|
||||
### Task Tracking with Beads
|
||||
|
||||
AnviLLM integrates [beads](https://github.com/steveyegge/beads) for persistent, crash-resilient task tracking. Beads provides a dependency-aware graph that agents can use for long-horizon work.
|
||||
Persistent, crash-resilient task tracking via [beads](https://github.com/steveyegge/beads). Provides dependency-aware task graph for multi-agent workflows.
|
||||
|
||||
**Initialize beads database:**
|
||||
```sh
|
||||
|
|
@ -298,15 +241,15 @@ echo 'dep bd-child bd-parent' | 9p write agent/beads/ctl # child blocks parent
|
|||
```
|
||||
|
||||
**Configuration:**
|
||||
- Default location: `~/.beads/`
|
||||
- Override with: `ANVILLM_BEADS_PATH=/custom/path`
|
||||
- Beads database is **shared across all namespaces** (tasks exist independently of sessions)
|
||||
- Default: `~/.beads/`
|
||||
- Override: `ANVILLM_BEADS_PATH=/custom/path`
|
||||
- Shared across all namespaces
|
||||
|
||||
See `internal/beads/README.md` for details.
|
||||
|
||||
### Event Stream
|
||||
|
||||
The `/agent/events` file provides a real-time stream of session events:
|
||||
Real-time session events at `/agent/events`:
|
||||
|
||||
```sh
|
||||
9p read agent/events
|
||||
|
|
@ -314,11 +257,9 @@ The `/agent/events` file provides a real-time stream of session events:
|
|||
# {"type":"message_received","session_id":"a3f2b9d1","from":"b4e3c8f2","timestamp":"2026-02-19T22:01:00Z"}
|
||||
```
|
||||
|
||||
Clients can monitor this stream to react to session state changes and inter-agent messages.
|
||||
|
||||
### Mailbox System
|
||||
|
||||
Sessions can send messages to each other via the mailbox system:
|
||||
Inter-session messaging:
|
||||
|
||||
**Send message:**
|
||||
```sh
|
||||
|
|
@ -333,16 +274,13 @@ EOF
|
|||
9p read agent/a3f2b9d1/inbox
|
||||
```
|
||||
|
||||
**Archive messages:**
|
||||
**Archive:**
|
||||
```sh
|
||||
9p read agent/a3f2b9d1/archive
|
||||
```
|
||||
|
||||
Messages are delivered asynchronously and persist until archived.
|
||||
|
||||
### Example Usage
|
||||
|
||||
Example:
|
||||
```sh
|
||||
echo 'new claude /home/user/project' | 9p write agent/ctl
|
||||
echo 'Hello' | 9p write agent/a3f2b9d1/in
|
||||
|
|
@ -351,7 +289,7 @@ echo 'stop' | 9p write agent/a3f2b9d1/ctl
|
|||
9p read agent/a3f2b9d1/state # → "stopped"
|
||||
```
|
||||
|
||||
**Security**: See `SECURITY.md` for 9P socket authentication limitations.
|
||||
See `SECURITY.md` for 9P socket authentication details.
|
||||
|
||||
## Backends
|
||||
|
||||
|
|
@ -360,34 +298,24 @@ echo 'stop' | 9p write agent/a3f2b9d1/ctl
|
|||
| Claude | `npm install -g @anthropic-ai/claude-code` |
|
||||
| Kiro | [Kiro CLI](https://kiro.dev) |
|
||||
|
||||
Both run with full permissions inside the sandbox (`--dangerously-skip-permissions`, `--trust-all-tools`).
|
||||
Both run with full permissions (`--dangerously-skip-permissions`, `--trust-all-tools`).
|
||||
|
||||
### Adding Backends
|
||||
|
||||
Create `internal/backends/yourbackend.go`, implement `CommandHandler` and `StateInspector` interfaces, register in `main.go`. See existing backends for examples.
|
||||
**Adding backends:** Implement `CommandHandler` and `StateInspector` interfaces in `internal/backends/yourbackend.go`, register in `main.go`. See existing backends for examples.
|
||||
|
||||
## Self-Healing
|
||||
|
||||
The `anvilsrv` daemon monitors all sessions every 5 seconds and automatically restarts sessions that crash unexpectedly. This ensures long-running workflows remain resilient to backend failures.
|
||||
`anvilsrv` monitors sessions every 5 seconds and auto-restarts crashed sessions (preserves context, alias, working directory). Rate-limited to prevent restart loops (minimum 5 seconds between attempts). Does not restart sessions stopped via `Stop` command.
|
||||
|
||||
**Behavior:**
|
||||
- Detects when a session process terminates without explicit `Stop` command
|
||||
- Automatically restarts the session in the same working directory
|
||||
- Preserves session context and alias
|
||||
- Rate-limited to prevent restart loops (minimum 5 seconds between attempts)
|
||||
- Does not restart sessions stopped intentionally via `Stop` command
|
||||
|
||||
Sessions that crash are transparently restarted without user intervention. Check logs with `anvilsrv fgstart` to see auto-restart activity.
|
||||
Check logs with `anvilsrv fgstart` to see auto-restart activity.
|
||||
|
||||
## Sandboxing
|
||||
|
||||
Backends run inside [landrun](https://github.com/zouuup/landrun) sandboxes. **Sandboxing cannot be disabled** — it's the only safety layer.
|
||||
|
||||
### Defaults
|
||||
Backends run in [landrun](https://github.com/zouuup/landrun) sandboxes. **Cannot be disabled** — it's the only safety layer.
|
||||
|
||||
**Defaults:**
|
||||
- Filesystem: CWD, `/tmp`, config dirs (rw); `/usr`, `/lib`, `/bin` (ro+exec)
|
||||
- Network: disabled
|
||||
- Mode: strict (`best_effort: false`) — sessions fail if sandbox unavailable
|
||||
- Mode: strict (`best_effort: false`) — fails if sandbox unavailable
|
||||
|
||||
### Configuration
|
||||
|
||||
|
|
@ -422,52 +350,46 @@ Changes apply to new sessions. Use `Restart` command to reload configuration for
|
|||
|
||||
Set `best_effort: true` for graceful degradation on older kernels.
|
||||
|
||||
**Warning**: If landrun is missing or kernel lacks Landlock, sessions run **completely unsandboxed**. Only enable if you accept this risk.
|
||||
**⚠️ Warning:** If landrun is missing or kernel lacks Landlock, sessions run **completely unsandboxed**.
|
||||
|
||||
## Reproducible Workflows
|
||||
|
||||
The 9P filesystem enables scripted multi-agent workflows. Create sessions, set contexts, and wire agents together programmatically.
|
||||
Script multi-agent workflows via 9P filesystem.
|
||||
|
||||
### Skills System
|
||||
|
||||
AnviLLM includes a skills system for extending agent capabilities. Skills are loaded on-demand via the `anvillm-skills` command:
|
||||
Extend agent capabilities on-demand:
|
||||
|
||||
```sh
|
||||
anvillm-skills list # List available skills
|
||||
anvillm-skills list # List available skills
|
||||
anvillm-skills load anvillm-communication # Load communication skill
|
||||
```
|
||||
|
||||
Agents can discover and load skills automatically when needed. See `kiro-cli/SKILLS_PROMPT.md` for details.
|
||||
See `kiro-cli/SKILLS_PROMPT.md` for details.
|
||||
|
||||
### Example: Developer-Reviewer
|
||||
|
||||
Two agents collaborate on code changes — one implements, one reviews:
|
||||
Two-agent code review workflow:
|
||||
|
||||
```sh
|
||||
./workflows/DevReview claude /path/to/project
|
||||
```
|
||||
|
||||
Creates paired sessions with contexts that instruct agents to:
|
||||
1. Developer implements and stages changes
|
||||
2. Developer sends review request via mailbox
|
||||
3. Reviewer examines diff, sends feedback or "LGTM"
|
||||
4. Loop until approved
|
||||
Developer implements and stages changes, sends review request via mailbox. Reviewer examines diff, sends feedback or "LGTM". Loop until approved.
|
||||
|
||||
### Example: Planning
|
||||
|
||||
Three-agent workflow for documentation tasks:
|
||||
Three-agent documentation workflow:
|
||||
|
||||
```sh
|
||||
./workflows/Planning kiro /path/to/docs
|
||||
```
|
||||
|
||||
- **Research**: Queries codebase and knowledge base
|
||||
- **Engineering**: Writes/updates documentation, queries research when needed
|
||||
- **Tech-editor**: Reviews for quality, requests changes from engineering
|
||||
**Research** queries codebase, **Engineering** writes docs (queries research when needed), **Tech-editor** reviews and requests changes.
|
||||
|
||||
### Writing Your Own
|
||||
|
||||
Key patterns from the example scripts:
|
||||
Key patterns:
|
||||
|
||||
```sh
|
||||
# Create session, capture ID
|
||||
|
|
@ -508,6 +430,6 @@ See `workflows/DevReview` and `workflows/Planning` for complete examples.
|
|||
| anvilweb can't connect | Ensure anvilsrv is running; check namespace matches |
|
||||
| anvilweb port in use | Use `-addr :PORT` to specify different port |
|
||||
|
||||
**Debugging**: Run `anvilsrv fgstart` to see daemon logs in foreground.
|
||||
**Debugging:** Run `anvilsrv fgstart` for foreground logs.
|
||||
|
||||
**Terminal**: `Attach` command uses `$ANVILLM_TERMINAL` or defaults to `foot`. Configure in environment or see `cmd/Assist/main.go`.
|
||||
**Terminal:** `Attach` uses `$ANVILLM_TERMINAL` (defaults to `foot`).
|
||||
|
|
|
|||
Reference in New Issue