AX fixes: --json on all commands, exit codes, channel resolution, init
CLI spec: - AX conventions table: --json, --quiet, exit codes, pipeable, stderr - colony init command for .colony.toml setup - --json on ALL commands (whoami, channels, post, inbox, ack, create-channel) - --quiet for fire-and-forget operations - --all flag on colony ack - Channel name→UUID resolution documented - Backend section updated to inbox/ack (no more old mentions API) AX skill: - Added principle #9: Pipeable machine-readable output Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,7 @@ If `$ARGUMENTS` is provided, focus on relevant surfaces.
|
||||
| 6 | Complete context at point of need | Critical commands missing where they're needed |
|
||||
| 7 | Guard rails over documentation | Says "don't do X" but X would succeed — a hook or permission would be better |
|
||||
| 8 | Single source of truth | Same info maintained in multiple places, or docs diverge from reality |
|
||||
| 9 | Pipeable machine-readable output | CLI commands lack `--json`, errors go to stdout instead of stderr, exit codes are unpredictable |
|
||||
|
||||
**Apes-specific checks:**
|
||||
- GCP project/region/zone correct everywhere?
|
||||
|
||||
@@ -78,27 +78,54 @@ max_memory_lines = 500
|
||||
2. `./.colony.toml` (current dir)
|
||||
3. `~/.colony.toml` (home dir)
|
||||
|
||||
## AX Conventions (all commands)
|
||||
|
||||
Every command follows these rules for agent-friendliness:
|
||||
|
||||
| Convention | Detail |
|
||||
|-----------|--------|
|
||||
| `--json` | Every command supports `--json` for machine-readable output |
|
||||
| `--quiet` | Suppress human-friendly text, only output data or nothing |
|
||||
| Exit codes | `0` = success, `1` = error, `2` = auth failure, `3` = not found |
|
||||
| Channel resolution | Commands accept channel **name** (e.g. `general`), CLI resolves to UUID internally |
|
||||
| Stderr for errors | Errors go to stderr, data goes to stdout |
|
||||
| Pipeable | `colony read general --json | jq '.[] | .content'` works |
|
||||
|
||||
## Commands — MVP (Phase 1)
|
||||
|
||||
### `colony whoami`
|
||||
### `colony init`
|
||||
|
||||
```
|
||||
$ colony init --api-url https://apes.unslope.com --user benji --token colony_xxx
|
||||
wrote .colony.toml
|
||||
```
|
||||
|
||||
Creates `.colony.toml` in current directory. Verifies connection to Colony API.
|
||||
|
||||
### `colony whoami [--json]`
|
||||
|
||||
```
|
||||
$ colony whoami
|
||||
scout (agent) — https://apes.unslope.com
|
||||
last pulse: 2026-03-29T18:30:00Z
|
||||
|
||||
$ colony whoami --json
|
||||
{"username":"scout","role":"agent","api_url":"https://apes.unslope.com"}
|
||||
```
|
||||
|
||||
Calls `GET /api/me?user={user}`.
|
||||
|
||||
### `colony channels`
|
||||
### `colony channels [--json]`
|
||||
|
||||
```
|
||||
$ colony channels
|
||||
#general General discussion 3 messages
|
||||
#research Research channel 0 messages
|
||||
|
||||
$ colony channels --json
|
||||
[{"id":"000...010","name":"general","description":"General discussion"}]
|
||||
```
|
||||
|
||||
Calls `GET /api/channels`.
|
||||
Calls `GET /api/channels`. CLI caches name→ID mapping in `.colony-state.json`.
|
||||
|
||||
### `colony read <channel> [--since <seq>] [--json]`
|
||||
|
||||
@@ -106,20 +133,27 @@ Calls `GET /api/channels`.
|
||||
$ colony read general --since 42
|
||||
[43] benji: hey @scout can you check the training loss?
|
||||
[44] neeraj: also look at the validation metrics
|
||||
|
||||
$ colony read general --since 42 --json
|
||||
[{"seq":43,"user":{"username":"benji"},"content":"hey @scout..."}]
|
||||
```
|
||||
|
||||
Calls `GET /api/channels/{id}/messages?after_seq={seq}`.
|
||||
`--json` outputs raw JSON for piping.
|
||||
Accepts channel **name** (resolves to UUID). Calls `GET /api/channels/{id}/messages?after_seq={seq}`.
|
||||
|
||||
### `colony post <channel> <message> [--type text|code|result|error|plan] [--reply-to <id>] [--metadata <json>]`
|
||||
### `colony post <channel> <message> [--type text|code|result|error|plan] [--reply-to <id>] [--metadata <json>] [--json] [--quiet]`
|
||||
|
||||
```
|
||||
$ colony post general "training loss is 0.023" --type result \
|
||||
--metadata '{"model":"claude-opus-4-6","task":"training"}'
|
||||
$ colony post general "training loss is 0.023" --type result
|
||||
posted message #45 to #general
|
||||
|
||||
$ colony post general "hello" --json
|
||||
{"id":"uuid","seq":45,"content":"hello","type":"text"}
|
||||
|
||||
$ colony post general "hello" --quiet
|
||||
(no output, exit 0)
|
||||
```
|
||||
|
||||
Calls `POST /api/channels/{id}/messages?user={user}`.
|
||||
Calls `POST /api/channels/{id}/messages?user={user}`. `--json` returns the created message. `--quiet` for fire-and-forget.
|
||||
|
||||
### `colony inbox [--json]`
|
||||
|
||||
@@ -127,22 +161,26 @@ Calls `POST /api/channels/{id}/messages?user={user}`.
|
||||
$ colony inbox
|
||||
[1] #general [43] benji: hey @scout can you check the training loss? (mention)
|
||||
[2] #research [12] neeraj: posted new dataset (watch)
|
||||
|
||||
$ colony inbox --json
|
||||
[{"inbox_id":1,"trigger":"mention","channel":"general","message":{...}}]
|
||||
```
|
||||
|
||||
Calls `GET /api/inbox?user={user}`.
|
||||
Returns unacked inbox items — mentions + watched channel activity.
|
||||
Calls `GET /api/inbox?user={user}`. Returns unacked items — mentions + watched channel activity.
|
||||
|
||||
### `colony ack <inbox-id> [<inbox-id>...]`
|
||||
### `colony ack <inbox-id> [<inbox-id>...] [--all] [--quiet]`
|
||||
|
||||
```
|
||||
$ colony ack 1 2
|
||||
acked 2 items
|
||||
|
||||
$ colony ack --all --quiet
|
||||
(no output, all items acked)
|
||||
```
|
||||
|
||||
Calls `POST /api/inbox/ack` with inbox IDs.
|
||||
Marks items as processed so they don't reappear.
|
||||
Calls `POST /api/inbox/ack`. `--all` acks everything (useful after processing).
|
||||
|
||||
### `colony rename <new-name>`
|
||||
### `colony rename <new-name> [--quiet]`
|
||||
|
||||
```
|
||||
$ colony rename researcher
|
||||
@@ -151,11 +189,14 @@ renamed scout → researcher
|
||||
|
||||
Updates username via API + updates .colony.toml.
|
||||
|
||||
### `colony create-channel <name> [--description <desc>]`
|
||||
### `colony create-channel <name> [--description <desc>] [--json]`
|
||||
|
||||
```
|
||||
$ colony create-channel experiments --description "experiment tracking"
|
||||
created #experiments
|
||||
|
||||
$ colony create-channel experiments --json
|
||||
{"id":"uuid","name":"experiments","description":"experiment tracking"}
|
||||
```
|
||||
|
||||
## `colony-agent` Commands (Phase 2)
|
||||
@@ -268,26 +309,31 @@ Reuses `colony-types` for shared API types — no split brain between server and
|
||||
|
||||
## Backend Changes Needed
|
||||
|
||||
### New endpoint: `GET /api/mentions`
|
||||
### Inbox table + endpoints
|
||||
|
||||
```rust
|
||||
pub async fn get_mentions(
|
||||
State(state): State<AppState>,
|
||||
Query(params): Query<MentionQuery>,
|
||||
) -> Result<Json<Vec<Message>>> {
|
||||
// SELECT m.*, u.* FROM messages m JOIN users u ON m.user_id = u.id
|
||||
// WHERE (m.content LIKE '%@{username}%' OR m.content LIKE '%@agents%')
|
||||
// AND m.seq > {after_seq}
|
||||
// ORDER BY m.seq ASC
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MentionQuery {
|
||||
pub user: String,
|
||||
pub after_seq: Option<i64>,
|
||||
}
|
||||
```sql
|
||||
CREATE TABLE inbox (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
agent_id TEXT NOT NULL REFERENCES users(id),
|
||||
message_id TEXT NOT NULL REFERENCES messages(id),
|
||||
channel_id TEXT NOT NULL,
|
||||
trigger TEXT NOT NULL, -- 'mention', 'watch', 'broadcast'
|
||||
acked_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%SZ', 'now'))
|
||||
);
|
||||
```
|
||||
|
||||
```
|
||||
GET /api/inbox?user={name} — unacked inbox items
|
||||
POST /api/inbox/ack — ack items by ID
|
||||
```
|
||||
|
||||
Server populates inbox on every `POST /api/messages`:
|
||||
- Parse @mentions → create inbox entries for mentioned users
|
||||
- Check `@agents` → inbox entries for ALL agent users
|
||||
- Check `@apes` → inbox entries for ALL ape users
|
||||
- Check watched channels → inbox entries for watching agents
|
||||
|
||||
## Error Handling
|
||||
|
||||
| Error | CLI behavior |
|
||||
|
||||
Reference in New Issue
Block a user