From bb839343079c8e60847d7f35a818b84252dd9d94 Mon Sep 17 00:00:00 2001 From: Siddharth Bhansali Date: Wed, 22 Apr 2026 21:23:30 +0530 Subject: [PATCH 1/2] fix: pass apiBase to sync's OneApi instance sync/index.ts constructed `new OneApi(apiKey)` without the apiBase argument, so sync always hit prod even when the CLI was configured for dev. This caused "Invalid or expired API key" errors on sync commands (test, run) despite the config being valid. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/lib/sync/index.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/sync/index.ts b/src/lib/sync/index.ts index e6ee7af..c600c18 100644 --- a/src/lib/sync/index.ts +++ b/src/lib/sync/index.ts @@ -1,7 +1,7 @@ import type { Command } from 'commander'; import * as output from '../output.js'; import { OneApi } from '../api.js'; -import { getApiKey, getAccessControlFromAllSources } from '../config.js'; +import { getApiKey, getApiBase, getAccessControlFromAllSources } from '../config.js'; import { discoverModels } from './models.js'; import { readProfile, writeProfile, writeDraftProfile, listProfiles, generateTemplate } from './profile.js'; import { syncModel } from './runner.js'; @@ -122,7 +122,7 @@ function getApi(): OneApi { if (!apiKey) { output.error('No API key configured. Run "one init" first.'); } - return new OneApi(apiKey); + return new OneApi(apiKey!, getApiBase()); } // ── sync profiles (built-in) ── From 3e19a0eafbf20128d1d25a21e0b80109fe932d9a Mon Sep 17 00:00:00 2001 From: Siddharth Bhansali Date: Wed, 22 Apr 2026 21:29:37 +0530 Subject: [PATCH 2/2] feat: add 'one relay platforms' to list relay-capable platforms Adds a new subcommand to discover which platforms support webhook relay and how many event types each offers. Previously users had to guess a platform and try `relay event-types ` to find out. Calls GET /webhooks/relay/platforms (no auth) and renders: - agent mode: {"platforms": [{"platform", "eventTypeCount"}, ...]} - human mode: two-column table with event type counts Updates README, `one guide relay`, and the agent-facing skill doc (skills/one/references/relay.md) to surface the new discovery path. Version bumped to 1.42.0 per release checklist. Closes withoneai/cli#123 Co-Authored-By: Claude Opus 4.7 (1M context) --- README.md | 16 +++++++++++++ package-lock.json | 7 ++++-- package.json | 2 +- skills/one/references/relay.md | 15 +++++++++++++ src/commands/relay.ts | 41 ++++++++++++++++++++++++++++++++++ src/index.ts | 9 ++++++++ src/lib/api.ts | 4 ++++ src/lib/guide-content.ts | 4 +++- 8 files changed, 94 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4440e63..2b61e84 100644 --- a/README.md +++ b/README.md @@ -349,6 +349,22 @@ one sync run stripe --full-refresh Change hooks (`onInsert`, `onUpdate`, `onChange`) fire per-page during sync — pipe to a shell command, a flow, or an event log. Root-array responses (e.g. Hacker News `/v0/topstories.json` → `[9129911, 9129199, ...]`) are supported by setting `resultsPath` to `""`, `"$"`, or `"."`; primitive elements are auto-wrapped as `{ [idField]: value }`. Run `one guide sync` for the full reference. +### `one relay` + +Receive webhooks from platforms and forward them to any connected platform via passthrough actions. + +```bash +one relay platforms # List relay-capable platforms + event type counts +one relay event-types # List supported event types for a platform +one relay create --connection-key --create-webhook --event-filters '["event.type"]' +one relay activate --actions '' # Attach passthrough forwarding actions +one relay list # List existing relay endpoints +one relay events --platform

# Inspect received events +one relay deliveries --endpoint-id # Check delivery status +``` + +Start with `one relay platforms` to discover which platforms support relay at all, then drill into `event-types ` for the specific events. Run `one guide relay` for the full reference including `--metadata` requirements per platform. + ### `one guide [topic]` Get the full CLI usage guide, designed for AI agents that only have the binary (no MCP, no IDE skills). diff --git a/package-lock.json b/package-lock.json index 96c8a0b..8deac9d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@withone/cli", - "version": "1.41.0", + "version": "1.42.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@withone/cli", - "version": "1.41.0", + "version": "1.42.0", "dependencies": { "@clack/prompts": "^0.9.1", "commander": "^13.1.0", @@ -1210,6 +1210,7 @@ "dev": true, "hasInstallScript": true, "license": "MIT", + "peer": true, "bin": { "esbuild": "bin/esbuild" }, @@ -1593,6 +1594,7 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -2144,6 +2146,7 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", + "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" diff --git a/package.json b/package.json index 0792608..36ffeb0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@withone/cli", - "version": "1.41.0", + "version": "1.42.0", "description": "CLI for managing One", "type": "module", "files": [ diff --git a/skills/one/references/relay.md b/skills/one/references/relay.md index 40ff15c..90bd370 100644 --- a/skills/one/references/relay.md +++ b/skills/one/references/relay.md @@ -16,6 +16,14 @@ one --agent connection list Identify source (sends webhooks) and destination (receives forwarded data). Note both connection keys. +If you're unsure whether the source platform supports relay at all, list relay-capable platforms first: + +```bash +one --agent relay platforms +``` + +This returns `[{ "platform": "", "eventTypeCount": }, ...]` for every platform that One can receive webhooks from. If your source isn't in the list, relay won't work for it. + ### Step 2: Get event types ```bash @@ -173,6 +181,13 @@ one --agent relay activate --actions '[{ }]' ``` +## Discovery Commands + +```bash +one --agent relay platforms # All relay-capable platforms + event type counts +one --agent relay event-types # Event types for a specific platform +``` + ## Management Commands ```bash diff --git a/src/commands/relay.ts b/src/commands/relay.ts index 638a01a..30b116e 100644 --- a/src/commands/relay.ts +++ b/src/commands/relay.ts @@ -422,6 +422,47 @@ export async function relayDeliveriesCommand(options: { } } +export async function relayPlatformsCommand(): Promise { + const { apiKey } = getConfig(); + const api = new OneApi(apiKey, getApiBase()); + const spinner = output.createSpinner(); + spinner.start('Loading relay-capable platforms...'); + + try { + const platforms = await api.listRelayPlatforms(); + + if (output.isAgentMode()) { + output.json({ platforms }); + return; + } + + spinner.stop(`${platforms.length} relay-capable platform${platforms.length === 1 ? '' : 's'} found`); + + if (platforms.length === 0) { + console.log('\n No relay-capable platforms available.\n'); + return; + } + + console.log(); + printTable( + [ + { key: 'platform', label: 'Platform' }, + { key: 'eventTypeCount', label: 'Event types', color: pc.dim }, + ], + platforms.map(p => ({ platform: p.platform, eventTypeCount: String(p.eventTypeCount) })) + ); + console.log(); + console.log( + pc.dim( + ` Run ${pc.cyan('one relay event-types ')} to see the full event list for a platform.\n` + ) + ); + } catch (error) { + spinner.stop('Failed to load relay platforms'); + output.error(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +} + export async function relayEventTypesCommand(platform: string): Promise { const { apiKey } = getConfig(); const api = new OneApi(apiKey, getApiBase()); diff --git a/src/index.ts b/src/index.ts index 5bc0e00..0cc236b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -42,6 +42,7 @@ import { relayEventGetCommand, relayDeliveriesCommand, relayEventTypesCommand, + relayPlatformsCommand, } from './commands/relay.js'; import { registerSyncCommands } from './lib/sync/index.js'; @@ -103,6 +104,7 @@ program one cache update-all Re-fetch fresh data for all cached entries Webhook Relay: + one relay platforms List platforms that support relay + event type counts one relay create Create a relay endpoint for a connection one relay list List relay endpoints one relay activate Activate with passthrough actions @@ -642,6 +644,13 @@ relay await relayEventTypesCommand(platform); }); +relay + .command('platforms') + .description('List all platforms that support webhook relay, with their event type counts') + .action(async () => { + await relayPlatformsCommand(); + }); + // ── Sync Commands ── diff --git a/src/lib/api.ts b/src/lib/api.ts index 404e6fa..523670e 100644 --- a/src/lib/api.ts +++ b/src/lib/api.ts @@ -579,6 +579,10 @@ export class OneApi { return this.requestFull({ path: '/webhooks/relay/event-types', queryParams: { platform } }); } + async listRelayPlatforms(): Promise> { + return this.requestFull({ path: '/webhooks/relay/platforms' }); + } + async waitForConnection( platform: string, diff --git a/src/lib/guide-content.ts b/src/lib/guide-content.ts index 09cc412..543a7f1 100644 --- a/src/lib/guide-content.ts +++ b/src/lib/guide-content.ts @@ -78,6 +78,7 @@ Receive webhooks from platforms (Stripe, GitHub, Airtable, Attio, Google Calenda **Quick start:** \`\`\`bash +one --agent relay platforms # See relay-capable platforms one --agent relay event-types # See available events one --agent relay create --connection-key --create-webhook --event-filters '["event.type"]' one --agent relay activate --actions '[{"type":"passthrough","actionId":"...","connectionKey":"...","body":{...}}]' @@ -228,6 +229,7 @@ Webhook relay receives events from platforms (Stripe, GitHub, Airtable, Attio, G ## Commands \`\`\`bash +one --agent relay platforms # List relay-capable platforms + event type counts one --agent relay event-types # List available events one --agent relay create --connection-key --create-webhook --event-filters '["event.type"]' one --agent relay activate --actions '' # Add forwarding actions @@ -242,7 +244,7 @@ one --agent relay deliveries --endpoint-id # Check delivery status ## Building a Relay -1. **Discover connections** — identify source and destination platforms +1. **Discover connections** — identify source and destination platforms. Use \`one --agent relay platforms\` to see which platforms support relay at all before digging into a specific one. 2. **Get event types** — \`one --agent relay event-types \` 3. **Get source knowledge** — understand the incoming webhook payload shape (\`{{payload.*}}\` paths) 4. **Get destination knowledge** — understand the outgoing API body shape