Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
3 changes: 3 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@ coverage/
pnpm-lock.yaml
.superpowers/
.codegraph/
*.toml
tests/fixtures/setup/claude-code/malformed.json
tests/fixtures/setup/metadata/malformed.json
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# Relay

Safe installed setup is documented in [setup and configuration](docs/setup-and-configuration.md). Use an explicit absolute `--config-file` and preview before `--apply`; generic MCP is snippet-only.

For Linux-only Claude Desktop MCPB evaluation, see [the MCPB guide](integrations/claude-desktop/README.md) and [verification record](docs/claude-desktop-mcpb-verification.md).

**Testing Relay for the first time?** Follow the [source-checkout installation and usage guide](docs/source-checkout-guide.md) to clone, run, connect an AI client, and complete a safe smoke test.
Expand Down
8 changes: 5 additions & 3 deletions docs/agent-integration.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Agent Integration

## Supported source-checkout model
## Supported installed model

Relay integrations run the built entries from an absolute source checkout: `node __RELAY_CHECKOUT__/dist/mcp/main.js` or `node __RELAY_CHECKOUT__/dist/cli/main.js`. `relay mcp` is a future packaged command owned by Epic #18 and is not available.
Installed integrations invoke the stable command `relay mcp`. Use `relay setup --client codex --config-file <absolute-path>` or the equivalent Claude Code command to preview a change, then add `--apply` only after reviewing the exact target, operation, and snippet. Generic MCP remains snippet-only.

For source development only, run the built entries from an absolute source checkout: `node __RELAY_CHECKOUT__/dist/mcp/main.js` or `node __RELAY_CHECKOUT__/dist/cli/main.js`. These source-checkout examples are intentionally separate from installed templates.

For source development only, run `pnpm dev:mcp` from the checkout; vendor configuration should use the built Node entry so it is independent of the current working directory.

Expand All @@ -25,7 +27,7 @@ Set `RELAY_DB_PATH` to `__RELAY_CHECKOUT__/.relay-validation/relay.db` for first

## Canonical MCP and CLI entry points

See [generic MCP](../integrations/generic-mcp/README.md) and [generic CLI](../integrations/generic-cli/README.md). The canonical MCP server is `node __RELAY_CHECKOUT__/dist/mcp/main.js`; `relay mcp` remains future-only and unavailable until Epic #18.
See [generic MCP](../integrations/generic-mcp/README.md) and [generic CLI](../integrations/generic-cli/README.md). Installed configuration uses `relay mcp`; source-checkout validation uses the explicit built Node entry above.

## Session and provenance example

Expand Down
5 changes: 5 additions & 0 deletions docs/distribution/npm-package.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ configuration, and cache paths are independent of the current directory.
platform default, and whitespace or relative values fail with usage/validation
exit code 2. CLI, MCP, and UI use the same effective database path.

After installation, initialize Relay with `relay setup`. To configure Codex or
Claude Code, preview with an explicit absolute `--config-file` and add
`--apply` only after reviewing the exact entry; see [safe setup and
configuration](../setup-and-configuration.md). Generic MCP is snippet-only.

## Supported runtime

The initial release claim is Node.js 24 on Windows x64, macOS arm64, and
Expand Down
49 changes: 49 additions & 0 deletions docs/setup-and-configuration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Safe setup and agent configuration

`relay setup` initializes Relay's data and configuration roots and opens the canonical database runtime so forward migrations run. It never replaces, resets, or deletes an existing database. Re-running it is safe.

Mutable client setup is preview-first:

```text
relay setup --client codex --config-file <absolute-path>
relay setup --client codex --config-file <absolute-path> --apply
relay setup --client claude-code --config-file <absolute-path> [--apply]
relay setup --client generic-mcp
```

Codex and Claude Code require an explicit absolute configuration path. Relay never scans home directories or infers a client file. Generic MCP produces a reviewed snippet only.

Before applying, inspect the target, operation, entry identifier, and snippet. Relay proves ownership using the exact `relay` entry, the `relay` command, `['mcp']` arguments, client, and normalized path. Unknown or conflicting entries fail closed. A changed client file receives a collision-safe sibling backup and a validated atomic replacement; Relay ownership metadata is updated only after the replacement is reparsed successfully.

Use `relay config paths` and `relay config integrations` to inspect effective paths and Relay-owned records. `relay config disable` removes an exact owned entry while retaining disabled ownership; setup can safely re-enable it. `relay config remove` removes only the exact owned entry and ownership record. These operations retain the database, tasks, backups, and unrelated configuration.

The complete inspection and mutation surface is:

```text
relay config paths
relay config paths --output json
relay config integrations
relay config integrations --output json
relay config snippet --client codex
relay config snippet --client claude-code
relay config snippet --client generic-mcp
relay config disable --client codex --config-file <absolute-path>
relay config disable --client codex --config-file <absolute-path> --apply
relay config remove --client codex --config-file <absolute-path>
relay config remove --client codex --config-file <absolute-path> --apply
```

The client configuration path is always explicit and absolute. `--apply` is required for a mutation; without it, setup, disable, and remove return a preview. Generic MCP is snippet-only and has no mutation mode.

For the human safety gate, use this checklist with a disposable absolute path and an isolated `RELAY_DB_PATH`:

1. Copy a real Codex or Claude Code configuration to a disposable file; never start with the only live configuration copy.
2. Run the preview and record the reported operation and exact snippet.
3. Apply the setup and verify the configured entry is exact.
4. Compare unrelated configuration bytes before and after.
5. Compare the backup with the original bytes.
6. Rerun setup and verify it reports unchanged and creates no new backup.
7. Disable the owned entry and verify unrelated content remains.
8. Re-enable it with setup and verify the entry returns.
9. Remove it and verify the ownership record is gone while the database remains.
10. Query a task created before setup and confirm it still exists.
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,7 @@ export interface RelayIntegrationOwnership {
readonly lastBackupPath?: string;
}

export type IntegrationOperation =
| 'created'
| 'updated'
| 'unchanged'
| 'disabled'
| 'removed';
export type IntegrationOperation = 'created' | 'updated' | 'unchanged' | 'disabled' | 'removed';

export interface IntegrationChangePlan {
readonly client: MutableIntegrationClient;
Expand Down Expand Up @@ -584,14 +579,27 @@ git commit -m "feat: apply owned configuration changes atomically"

```ts
export type OperationalCommand =
| { readonly kind: 'setup'; readonly client?: IntegrationClient; readonly configFile?: string; readonly apply: boolean }
| {
readonly kind: 'setup';
readonly client?: IntegrationClient;
readonly configFile?: string;
readonly apply: boolean;
}
| { readonly kind: 'config-paths' }
| { readonly kind: 'config-integrations' }
| { readonly kind: 'config-snippet'; readonly client: IntegrationClient }
| { readonly kind: 'config-disable' | 'config-remove'; readonly client: MutableIntegrationClient; readonly configFile: string; readonly apply: true };
| {
readonly kind: 'config-disable' | 'config-remove';
readonly client: MutableIntegrationClient;
readonly configFile: string;
readonly apply: true;
};

export function parseOperationalCommand(argv: readonly string[]): OperationalCommand;
export async function runOperationalCommand(command: OperationalCommand, dependencies: OperationalDependencies): Promise<number>;
export async function runOperationalCommand(
command: OperationalCommand,
dependencies: OperationalDependencies,
): Promise<number>;
```

- [ ] **Step 1: Write failing parser tests for the locked command grammar.**
Expand Down
8 changes: 8 additions & 0 deletions docs/troubleshooting-agent-integration.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@

**Symptom:** build fails. **Check:** `node --version` and `pnpm --version`. **Resolution:** use the documented versions.

## Setup preview or conflict failure

**Symptom:** setup refuses to apply. **Check:** run the same command without `--apply` and inspect the exact target, operation, and `relay` entry. **Resolution:** use an explicit absolute `--config-file`, resolve any conflicting or unowned `relay` entry manually, and keep the original file and Relay backup intact.

## Configuration backup or race failure

**Symptom:** an apply reports a backup, write, or concurrent-change error. **Check:** inspect the named target and sibling `.relay-backup-...` file. **Resolution:** do not delete the backup; restore or review the original, then retry after the client file is stable.

## Missing dist/mcp/main.js or dist/cli/main.js

**Symptom:** process cannot start. **Check:** run `pnpm build:node`. **Resolution:** rebuild before configuring the client.
Expand Down
7 changes: 2 additions & 5 deletions integrations/claude-code/.mcp.json.example
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
{
"mcpServers": {
"relay": {
"command": "node",
"args": ["__RELAY_CHECKOUT__/dist/mcp/main.js"],
"env": {
"RELAY_DB_PATH": "__RELAY_CHECKOUT__/.relay-validation/relay.db"
}
"command": "relay",
"args": ["mcp"]
}
}
}
2 changes: 1 addition & 1 deletion integrations/claude-code/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Claude Code integration

Build Relay and substitute an absolute checkout path. Add the stdio server with `claude mcp add --transport stdio --scope project --env RELAY_DB_PATH=ABSOLUTE_CHECKOUT/.relay-validation/relay.db relay -- node ABSOLUTE_CHECKOUT/dist/mcp/main.js`, or copy the template to the project root as `.mcp.json`. `local` is private to the current project, `project` is shared through `.mcp.json`, and `user` applies across projects; local takes priority. Set the same isolated `RELAY_DB_PATH` in the selected configuration.
Use `relay setup --client claude-code --config-file <absolute-path>` to preview the exact JSON entry, then add `--apply` only after reviewing a disposable or reviewed file. The generated entry invokes `relay mcp`; no client-file discovery occurs. The source-checkout command remains documented separately for repository development. `local` is private to the current project, `project` is shared through `.mcp.json`, and `user` applies across projects; local takes priority.

Install the canonical [Relay Capture](../../skills/relay-capture/SKILL.md) and [Relay Session Review](../../skills/relay-session-review/SKILL.md) skill directories by copying or symlinking them unchanged to `.claude/skills/relay-capture/` and `.claude/skills/relay-session-review/`. For a personal installation across projects, use the client’s documented user-scoped skills directory. Do not copy the policy text into Claude-specific documentation or use instruction-file imports as skill discovery.

Expand Down
2 changes: 1 addition & 1 deletion integrations/codex/README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Codex integration

Build Relay, replace `__RELAY_CHECKOUT__` with an absolute path, create `.relay-validation`, then add the template to trusted project or user-scoped Codex configuration. Restart Codex and use `/mcp` or `codex mcp list` to confirm Relay. Verify `relay_health`, the five read/capture tools, a disposable capture, and exact-session retrieval. The JSON CLI fallback is in [generic CLI](../generic-cli/README.md).
Use `relay setup --client codex --config-file <absolute-path>` to preview the exact Relay entry, then add `--apply` to mutate a disposable or reviewed Codex file. The generated entry is `command = "relay"` with `args = ["mcp"]`; no client-file discovery occurs. Restart Codex and use `/mcp` or `codex mcp list` to confirm Relay. The source-checkout fallback and JSON CLI are documented in [generic CLI](../generic-cli/README.md).

Install the canonical [Relay Capture](../../skills/relay-capture/SKILL.md) and [Relay Session Review](../../skills/relay-session-review/SKILL.md) as repository skills by copying their complete directories unchanged to `.agents/skills/relay-capture/` and `.agents/skills/relay-session-review/`; Codex discovers repository skills from `.agents/skills` after a new session. Do not copy their policy into this README. Remove the Relay configuration and those skill directories to disable it. The SQLite database remains untouched.
7 changes: 2 additions & 5 deletions integrations/codex/config.toml.example
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
[mcp_servers.relay]
command = "node"
args = ["__RELAY_CHECKOUT__/dist/mcp/main.js"]

[mcp_servers.relay.env]
RELAY_DB_PATH = "__RELAY_CHECKOUT__/.relay-validation/relay.db"
command = "relay"
args = ["mcp"]
4 changes: 3 additions & 1 deletion integrations/generic-mcp/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
# Generic MCP integration

Build Relay with `pnpm build:node`, replace `__RELAY_CHECKOUT__` in [server-config.json.example](server-config.json.example) with an absolute checkout path, then copy the command, arguments, and optional environment map into the client configuration. Keep command and arguments separate: do not use a shell or interpolation. Validation flows must set the isolated `RELAY_DB_PATH` shown in the template; omitting `RELAY_DB_PATH` is permitted only for non-validation use and then selects Relay's platform default.
Run `relay setup --client generic-mcp` or `relay config snippet --client generic-mcp` to print the reviewed snippet. Generic MCP is snippet-only in this issue and never mutates a client file. The installed snippet invokes `relay mcp`; source-checkout validation remains documented separately and must use an explicitly isolated `RELAY_DB_PATH`.

Validation RELAY_DB_PATH must be explicit and isolated; omitting RELAY_DB_PATH is permitted only for non-validation use and selects Relay's platform default.

The stdio protocol requires clean stdout. Relay exposes exactly these MCP tools: `relay_health`, `task_capture`, `task_list`, `task_get`, `task_find_similar`, `session_captures_list`, `task_edit`, `task_triage`, `task_start`, `task_complete`, and `task_archive`. Restart or reload the client, capture one disposable task, and retrieve it by the same exact session ID.

Expand Down
7 changes: 2 additions & 5 deletions integrations/generic-mcp/server-config.json.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
{
"command": "node",
"args": ["__RELAY_CHECKOUT__/dist/mcp/main.js"],
"env": {
"RELAY_DB_PATH": "__RELAY_CHECKOUT__/.relay-validation/relay.db"
}
"command": "relay",
"args": ["mcp"]
}
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,6 @@
},
"devDependencies": {
"@anthropic-ai/mcpb": "2.1.2",
"@iarna/toml": "2.2.5",
"@testing-library/jest-dom": "^7.0.0",
"@testing-library/react": "^16.3.2",
"@types/better-sqlite3": "^7.6.13",
Expand All @@ -97,8 +96,10 @@
"vitest": "^4.1.10"
},
"dependencies": {
"@iarna/toml": "2.2.5",
"@modelcontextprotocol/sdk": "^1.29.0",
"better-sqlite3": "^13.0.1",
"jsonc-parser": "3.3.1",
"react": "^19.2.8",
"react-dom": "^19.2.8",
"zod": "^4.4.3"
Expand Down
14 changes: 11 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading