Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@ dist/
vendor/
*.test
coverage.out

# Planning artifacts
plans/
*.coverprofile

# IDE
.idea/
Expand All @@ -28,3 +26,8 @@ plans/
# OS
.DS_Store
Thumbs.db

# Tooling artifacts (local-only)
.claude/
repomix-output.xml
docs/journals/
88 changes: 88 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Changelog

All notable changes to goclaw-cli are documented here.
Format: [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

---

## [Unreleased] — Domain Coverage Expansion (P0–P2)

### Added

**P0 — Critical**
- `goclaw hooks` (list, create, update, delete, toggle, test, history) — manage event hooks via WS RPC `hooks.*`. Closes the entire hooks domain that was previously unreachable from CLI.
- `goclaw agents files` (list, get, set) — edit global agent context files (AGENTS.md, SOUL.md, IDENTITY.md, USER.md, USER_PREDEFINED.md, CAPABILITIES.md, BOOTSTRAP.md, MEMORY.json, HEARTBEAT) via WS RPC `agents.files.*`. `--propagate` pushes change to all existing user instances.

**P1 — Lifecycle & analytics**
- `goclaw agents cancel-summon <id>` — cancel an in-progress summon (`POST /v1/agents/{id}/cancel-summon`).
- `goclaw agents skills list <id>` — list skills granted to an agent (`GET /v1/agents/{id}/skills`).
- `goclaw usage timeseries` — bucketed usage over time (`GET /v1/usage/timeseries`).
- `goclaw usage breakdown` — usage broken down by agent/user/tenant (`GET /v1/usage/breakdown`).

**P2 — Coverage completion**
- `goclaw tts test-connection` — test a TTS provider end-to-end (`POST /v1/tts/test-connection`).
- `goclaw voices list` and `goclaw voices refresh` — voice catalog.
- `goclaw memory kg extract` — switched to new endpoint `POST /v1/agents/{id}/kg/extract` (legacy `/v1/knowledge-graph` path retired).
- `goclaw files sign` — generate signed URL for server-side file (`POST /v1/files/sign`).
- `goclaw teams workspace upload` and `goclaw teams workspace move` — multipart upload + rename for team workspace.
- `goclaw packages github-releases` — list GitHub releases for tracked packages.

### Notes
- All new commands honor the AI-first ergonomics contract: `--output=json` envelope, central error handler, `--yes` for destructive ops, `--quiet` for CI.
- Out of scope: OpenAI-compatible `/chat/completions` and `/v1/responses` endpoints (client APIs, not admin CLI surface).

---

## [Unreleased] — AI Ergonomics Foundation (Phase 0)

### Breaking Changes

#### Output format default changed when stdout is piped

**Before:** `goclaw agents list` always defaulted to `table` format regardless of context.

**After:** When stdout is not a terminal (piped, redirected, CI), the default format is now `json`.

**Migration:** Scripts relying on table output must add `--output=table` or `GOCLAW_OUTPUT=table`.

```bash
# Before (broke silently in CI)
goclaw agents list | grep "my-agent"

# After — explicit table for text parsing
goclaw agents list --output=table | grep "my-agent"

# Or use JSON (recommended for automation)
goclaw agents list | jq '.[] | select(.display_name == "my-agent")'
```

**Rationale:** AI tools, CI pipelines, and shell scripts consuming CLI output require
structured JSON. Table format is human-optimised and breaks piped parsing. TTY detection
ensures human operators still get tables by default.

### Added

- **`internal/output/exit.go`** — Exit code constants (0-6) + `MapServerCode(code)` + `MapHTTPStatus(status)` + `Exit(code)`
- **`internal/output/error.go`** — `ErrorDetail` / `ErrorEnvelope` types matching server `ErrorShape`; `ParseHTTPError(body, status)`; `PrintError(err, format)`; `FromError(err) int`
- **`internal/output/tty.go`** — `IsTTY(fd)` via `golang.org/x/term`; `ResolveFormat(flagVal)` with flag > `GOCLAW_OUTPUT` env > TTY precedence
- **`internal/client/follow.go`** — `FollowStream(ctx, ...)` with exponential backoff reconnect (max 5 retries) for `--follow` streaming commands
- **`--quiet` flag** — persistent flag on root command; suppresses banners and informational messages in non-TTY contexts
- **Exit code contract** — all server error codes now map deterministically to exit codes 0-6 for AI/automation consumers

### Changed

- `cmd/root.go` — output format resolved via TTY detection in `PersistentPreRunE`; central error handler in `Execute()` calls `output.PrintError` + `output.Exit(output.FromError(err))`
- `cmd/logs.go` — `logs tail --follow` migrated to `client.FollowStream` with auto-reconnect; banner gated behind `--quiet` and TTY check
- `--output` flag default changed from `"table"` to `""` (empty triggers auto-detect)
- `internal/client/errors.go` — `APIError` extended with `Details`, `Retryable`, `RetryAfterMs` fields matching server `ErrorShape`; added interface methods (`ErrorCode`, `ErrorMessage`, `ErrorDetails`, `IsRetryable`, `RetryAfter`, `HTTPStatus`) for duck-typed error handling in `output` package without import cycle

### Fixed

- Piped invocations no longer silently produce unparseable table output; they emit valid JSON
- Error details from server (`code`, `message`, `retryable`) are now fully preserved and passed through to the caller

---

## Previous releases

See git log for changes prior to this changelog.
43 changes: 42 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,48 @@ make install # Install to GOPATH/bin
cmd/ # Cobra command files (1 per resource group)
internal/
├── client/ # HTTP + WebSocket + auth clients
│ ├── errors.go # APIError (matches server ErrorShape)
│ └── follow.go # FollowStream() with exponential backoff reconnect
├── config/ # Config loader (~/.goclaw/)
├── output/ # Table/JSON/YAML formatters
├── output/ # Table/JSON/YAML formatters + AI-ergonomics foundation
│ ├── exit.go # ExitCode constants (0-6) + MapServerCode + Exit
│ ├── error.go # ErrorDetail/PrintError/ParseHTTPError/FromError
│ └── tty.go # IsTTY + ResolveFormat (TTY auto-detection)
└── tui/ # Interactive prompts
```

## AI-First Ergonomics (Phase 0 — implemented)

These patterns are **locked** — do not change without updating CHANGELOG.md.

### Output format auto-detection
Precedence: `--output` flag > `GOCLAW_OUTPUT` env > TTY detection
- stdout is TTY → `"table"` (human)
- stdout is piped/redirected → `"json"` (machine)

### Exit codes (automation contract)
| Code | Trigger |
|------|---------|
| 0 | Success |
| 1 | Generic/unknown |
| 2 | Auth (UNAUTHORIZED, NOT_PAIRED, etc.) |
| 3 | Not found |
| 4 | Validation |
| 5 | Server error |
| 6 | Resource/network/rate-limit |

### Error output shape (JSON mode)
```json
{"error": {"code": "UNAUTHORIZED", "message": "..."}}
```

### Central error handler
All command errors bubble via `return err` to `cmd.Execute()` → `output.PrintError` + `output.Exit(output.FromError(err))`. Do NOT print errors in individual commands.

### Flags
- `--quiet` — suppresses banners/tips in non-interactive contexts
- `--output` / `-o` — default empty (triggers auto-detect), not `"table"`

## Conventions

- Go snake_case file naming
Expand All @@ -47,6 +84,10 @@ internal/
- `readContent()` — read from `@filepath` or literal string
- `unmarshalMap()` / `unmarshalList()` — parse JSON responses
- `printer.Print()` — output in configured format
- `output.ResolveFormat(flagVal)` — resolve format with TTY fallback
- `output.FromError(err)` — map error to exit code
- `output.PrintError(err, format)` — format-aware error output
- `client.FollowStream(ctx, ...)` — persistent WS streaming with reconnect

## Testing

Expand Down
Loading
Loading