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
12 changes: 11 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Relay

The approved agent-integration contract is documented in the [decision record](docs/decisions/0002-agent-integration-contracts.md), [MCP tool reference](docs/mcp-tools.md), [CLI reference](docs/cli-reference.md), and [session semantics](docs/session-semantics.md). The production MCP task tools are shipped; CLI task handlers remain downstream work.
The approved agent-integration contract is documented in the [decision record](docs/decisions/0002-agent-integration-contracts.md), [MCP tool reference](docs/mcp-tools.md), [CLI reference](docs/cli-reference.md), and [session semantics](docs/session-semantics.md). The production MCP task tools and source-checkout CLI are shipped.

Relay is a local task sidecar for human–AI workflows. The current MVP is usable through its local web UI and through five safe local stdio MCP task tools.

Expand Down Expand Up @@ -43,6 +43,15 @@ To run the MCP server after building:
node dist/mcp/main.js
```

To use the source-checkout CLI from any working directory, run `pnpm build:node` from the repository checkout root first (or use `pnpm --dir /absolute/path/to/relay build:node` from another working directory):

```bash
pnpm build:node
RELAY_DB_PATH=/tmp/relay.db node /absolute/path/to/relay/dist/cli/main.js task list --output json
```

The CLI calls `TaskApplication` directly; it does not start HTTP or MCP processes. Its JSON envelope is authoritative: stdout contains one JSON document and newline, success writes no stderr, and failures also print one human-readable diagnostic to stderr. See the [CLI reference](docs/cli-reference.md) for all commands and stable exit codes.

It exposes five task tools—`task_capture`, `task_list`, `task_get`, `task_find_similar`, and `session_captures_list`—plus the separate `relay_health` tool. MCP task results use structured schema-versioned payloads; capture records AGENT provenance and reports possible duplicates as advisory warnings.

## Database and safe development data
Expand Down Expand Up @@ -96,6 +105,7 @@ src/
interfaces/
http/ # Loopback HTTP adapter and compiled UI serving
mcp/ # MCP health and production task-tool adapter
cli/ # Source-checkout JSON CLI adapter
web/ # React UI that calls the HTTP API only
```

Expand Down
142 changes: 103 additions & 39 deletions docs/cli-reference.md
Original file line number Diff line number Diff line change
@@ -1,59 +1,123 @@
# Relay CLI Contract Reference

Issue #19 reserves a deterministic, versioned CLI contract. Production command handlers are implemented later; the stable executable surface is one `relay` command:

```text
relay mcp
relay ui
relay doctor
relay task ...
relay session ...
The source-checkout CLI is a built Node entry point at `dist/cli/main.js`. It supports ten task/session commands and always uses JSON mode.

## Build and invoke

From the repository root:

```bash
pnpm build:node
```

Invoke the built file with an absolute path from any working directory:

```bash
RELAY_DB_PATH=/tmp/relay.db node /absolute/path/to/relay/dist/cli/main.js task list --output json
```

`relay-mcp` may remain as a compatibility entry point, but new integrations target `relay mcp`.
On Windows PowerShell:

```powershell
$env:RELAY_DB_PATH = 'C:\temp\relay.db'
node C:\absolute\path\to\relay\dist\cli\main.js task list --output json
```

`RELAY_DB_PATH` selects the SQLite database. If it is blank or unset, Relay uses the platform default from `src/database/database-config.ts`. The working directory does not affect storage or migration lookup.

The CLI calls `TaskApplication` directly. It never starts an HTTP server or MCP process and does not access SQLite from the adapter.

## JSON protocol

Every agent-facing command accepts `--output json`. JSON mode writes one JSON document followed by a newline to stdout; diagnostics are written to stderr. No caller needs to parse decorative output.
Every command requires the exact option `--output json`. Stdout contains exactly one JSON document followed by one newline. Success writes no stderr; failures write one public JSON failure envelope to stdout and one human-readable diagnostic to stderr. Stack traces, SQL, secrets, and local paths are not part of the public error contract.

Success envelope:

```json
{ "schemaVersion": 1, "ok": true, "data": {}, "warnings": [] }
```

Error details are optional and never expose SQL, stacks, secrets, or local paths.
Failure envelope:

```json
{
"schemaVersion": 1,
"ok": false,
"error": { "code": "VALIDATION_ERROR", "message": "sessionId has an invalid format" }
"error": { "code": "VALIDATION_ERROR", "message": "A task id is required." }
}
```

| Exit code | Meaning | Error codes |
| --------- | ------------------------------------ | --------------------------- |
| 0 | Success, warnings, or approved no-op | — |
| 1 | Unexpected internal failure | `INTERNAL_ERROR` |
| 2 | Usage or validation failure | `VALIDATION_ERROR` |
| 3 | Task absent | `NOT_FOUND` |
| 4 | Invalid lifecycle operation | `CONFLICT`, `ARCHIVED_TASK` |
| 5 | Storage failure | `STORAGE_ERROR` |

## Commands

| Command | Required arguments | Optional arguments | Result |
| -------------------------- | ------------------------------------------- | --------------------------------------------------------------------------------- | --------------------------------------------------------------- |
| `relay task capture` | `--title`, `--agent`, `--session` | `--description`, `--priority`, `--workspace`, `--source-context`, `--output json` | `{ task, change: { action: "CREATED" } }` and optional warnings |
| `relay task list` | — | repeatable `--status`, `--workspace`, `--limit 1..100`, `--output json` | `{ tasks, count }` |
| `relay task get <id>` | ID | `--output json` | `{ task }` |
| `relay task find-similar` | `--title` | `--workspace`, `--limit 1..5`, `--output json` | `{ candidates }` |
| `relay session captures` | `--session` | `--limit 1..100`, `--output json` | `{ sessionId, tasks, count }` |
| `relay task edit <id>` | ID and an editable field | clear flags and `--output json` | `{ task, change }` |
| `relay task triage <id>` | ID and `--to INBOX`, `ACTIVE`, or `BACKLOG` | `--output json` | `{ task, change }` |
| `relay task start <id>` | ID | `--output json` | `{ task, change }` |
| `relay task complete <id>` | ID | `--output json` | `{ task, change }` |
| `relay task archive <id>` | ID | `--output json` | `{ task, change }` |

Editing accepts existing editable fields only. Clear nullable fields with explicit flags such as `--clear-description`; empty strings and MCP `null` values are rejected rather than treated as clearing requests. A value and its corresponding clear flag cannot be supplied together. `task triage` excludes `IN_PROGRESS`, `DONE`, and `ARCHIVED`, because those transitions have dedicated intent-specific commands.

CLI commands call application services and reuse `src/database/database-config.ts`; they never access SQLite directly. Database path precedence is explicit command/injected path, non-blank `RELAY_DB_PATH`, then the platform default. The working directory is never production storage configuration.
Duplicate detection during capture is advisory. A duplicate warning is included in `warnings`, but the command still succeeds with exit code `0`.

## Commands and options

Options shown as required must appear exactly once. Options shown as repeatable may appear more than once. Unknown options and positional arguments are usage errors.

### `task capture`

Required: `--title TEXT`, `--agent NAME`, `--session ID`, `--output json`.

Optional: `--description TEXT`, `--priority LOW|NORMAL|HIGH`, `--workspace NAME`, `--source-context TEXT`.

Creates an `AGENT` task, performs an advisory similar-task lookup first, and preserves agent, session, workspace, and source context.

### `task list`

Required: `--output json`.

Optional: repeatable `--status INBOX|ACTIVE|IN_PROGRESS|BACKLOG|DONE|ARCHIVED`, `--workspace NAME`, and `--limit INTEGER` from `1` through `100`.

Without `--status`, all task statuses are selected. The default limit is `100`.

### `task get ID`

Required: a task `ID` and `--output json`.

No other options are accepted.

### `task find-similar`

Required: `--title TEXT`, `--output json`.

Optional: `--workspace NAME` and `--limit INTEGER` from `1` through `5`. The default limit is `5`.

### `task edit ID`

Required: a task `ID`, at least one edit operation, and `--output json`.

Editable values: `--title TEXT`, `--description TEXT`, `--priority LOW|NORMAL|HIGH`, `--workspace NAME`, and `--source-context TEXT`.

Clear flags: `--clear-description`, `--clear-priority`, `--clear-workspace`, and `--clear-source-context`. A value and its matching clear flag cannot be supplied together. Empty strings are rejected rather than interpreted as clears. A no-op edit is valid when an edit operation is supplied and returns `change.action` `NO_CHANGE`.

### `task triage ID`

Required: a task `ID`, `--to INBOX|ACTIVE|BACKLOG`, and `--output json`.

No other options are accepted. Triage uses the corresponding focused application mutation.

### `task start ID`, `task complete ID`, and `task archive ID`

Required: a task `ID` and `--output json`.

No other options are accepted. Each command calls its matching lifecycle method and returns `STARTED`, `COMPLETED`, or `ARCHIVED` change metadata, or `NO_CHANGE` for an idempotent operation.

### `session captures`

Required: `--session ID` and `--output json`.

Optional: `--limit INTEGER` from `1` through `100`; the default is `100`.

Returns captured AGENT tasks for the session.

## Exit codes

| Exit code | Meaning | Error code |
| --------: | ------------------------------------ | --------------------------- |
| `0` | Success, warnings, or approved no-op | — |
| `1` | Unexpected internal failure | `INTERNAL_ERROR` |
| `2` | Usage or validation failure | `VALIDATION_ERROR` |
| `3` | Task was not found | `NOT_FOUND` |
| `4` | Conflict or archived-task operation | `CONFLICT`, `ARCHIVED_TASK` |
| `5` | Storage or persistence failure | `STORAGE_ERROR` |

The CLI intentionally excludes HTTP calls, MCP process spawning, direct SQLite access, publication, installers, setup/doctor/update commands, shell completion, TUI work, and vendor-specific assets.
Loading
Loading