@withone/cli 1.16.0 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@withone/cli",
3
- "version": "1.16.0",
3
+ "version": "1.17.1",
4
4
  "description": "CLI for managing One",
5
5
  "type": "module",
6
6
  "files": [
@@ -0,0 +1,116 @@
1
+ ---
2
+ name: one
3
+ description: |
4
+ Use the One CLI (`one`) to interact with 250+ third-party platforms — Gmail, Slack, Shopify, HubSpot, Stripe, GitHub, Notion, Salesforce, and more — through their APIs. One handles authentication, request building, and execution through a single unified interface.
5
+
6
+ TRIGGER when the user wants to:
7
+ - Interact with ANY third-party platform or external service (e.g., "send an email", "create a Shopify order", "look up a HubSpot contact", "post to Slack")
8
+ - List their connected platforms or check what integrations are available
9
+ - Search for what they can do on a platform (e.g., "what can I do with Gmail")
10
+ - Execute any API call against a connected platform
11
+ - Set up webhook-driven automations between platforms (e.g., "when a Stripe payment comes in, notify Slack")
12
+ - Build multi-step workflows that chain actions across platforms (e.g., "fetch Stripe customers and email each one")
13
+ - Anything involving third-party APIs, integrations, or connected apps — even if they don't mention "One" by name
14
+
15
+ DO NOT TRIGGER for:
16
+ - Setting up One or installing MCP (that's `one init`)
17
+ - Adding new connections (that's `one add <platform>`)
18
+ - Configuring access control (that's `one config`)
19
+ ---
20
+
21
+ # One CLI
22
+
23
+ You have access to the One CLI which lets you interact with 250+ third-party platforms through their APIs. Always include the `--agent` flag right after `one` for structured JSON output.
24
+
25
+ ## Core Workflow: search -> knowledge -> execute
26
+
27
+ Always follow this sequence when the user wants to do something on a connected platform:
28
+
29
+ ### 1. List connections
30
+
31
+ ```bash
32
+ one --agent connection list
33
+ ```
34
+
35
+ Returns connected platforms with their connection keys (needed for execution) and platform names in kebab-case (needed for searching).
36
+
37
+ ### 2. Search for the right action
38
+
39
+ ```bash
40
+ one --agent actions search <platform> "<query>" -t execute
41
+ ```
42
+
43
+ - Platform names are always kebab-case: `gmail`, `hub-spot`, `ship-station`
44
+ - Use `-t execute` when performing actions, `-t knowledge` when researching or writing code
45
+ - If no results, broaden the query (e.g., `"list"` instead of `"list active premium customers"`)
46
+
47
+ ### 3. Get the action's knowledge (REQUIRED before executing)
48
+
49
+ ```bash
50
+ one --agent actions knowledge <platform> <actionId>
51
+ ```
52
+
53
+ This tells you exactly what parameters are required, how to structure the request, and which flags to use. Never skip this step — without it you'll guess wrong on parameters.
54
+
55
+ ### 4. Execute
56
+
57
+ ```bash
58
+ one --agent actions execute <platform> <actionId> <connectionKey> [options]
59
+ ```
60
+
61
+ Options:
62
+ - `-d, --data <json>` — Request body (POST, PUT, PATCH)
63
+ - `--path-vars <json>` — Path variables for URLs with `{id}` placeholders
64
+ - `--query-params <json>` — Query parameters
65
+ - `--headers <json>` — Additional headers
66
+ - `--form-data` — Send as multipart/form-data
67
+ - `--form-url-encoded` — Send as application/x-www-form-urlencoded
68
+ - `--dry-run` — Preview the request without executing
69
+
70
+ Examples:
71
+ ```bash
72
+ # Simple GET
73
+ one --agent actions execute shopify <actionId> <connectionKey>
74
+
75
+ # POST with body data
76
+ one --agent actions execute hub-spot <actionId> <connectionKey> \
77
+ -d '{"properties": {"email": "jane@example.com", "firstname": "Jane"}}'
78
+
79
+ # Path variables + query params
80
+ one --agent actions execute shopify <actionId> <connectionKey> \
81
+ --path-vars '{"order_id": "12345"}' \
82
+ --query-params '{"limit": "10"}'
83
+
84
+ # Array query params (expand to repeated keys)
85
+ one --agent actions execute gmail <actionId> <connectionKey> \
86
+ --path-vars '{"userId": "me", "id": "msg123"}' \
87
+ --query-params '{"format": "metadata", "metadataHeaders": ["From", "Subject", "Date"]}'
88
+ ```
89
+
90
+ ## Error Handling
91
+
92
+ All errors return JSON: `{"error": "message"}`. Parse output as JSON and check for the `error` key.
93
+
94
+ ## Important Rules
95
+
96
+ - Always use `--agent` flag for structured JSON output
97
+ - Platform names are always kebab-case (`hub-spot` not `HubSpot`)
98
+ - Always use the exact action ID from search results — never guess or construct them
99
+ - Always read knowledge before executing — it has required params, validation rules, and caveats
100
+ - JSON values passed to `-d`, `--path-vars`, `--query-params` must be valid JSON (use single quotes around JSON to avoid shell escaping)
101
+ - Do NOT pass path or query parameters inside the `-d` body flag
102
+
103
+ ## Beyond Single Actions
104
+
105
+ One also supports more advanced patterns. Read the relevant reference file before using these:
106
+
107
+ - **Webhook Relay** — Receive webhooks from a platform and forward to another (e.g., Stripe event -> Slack message). Read `references/relay.md` in this skill's directory for the full workflow.
108
+ - **Multi-step Workflows** — Chain actions across platforms as JSON workflow files (like n8n/Zapier but file-based). Read `references/flows.md` in this skill's directory for the schema and examples.
109
+
110
+ ## Adding New Connections
111
+
112
+ If the user needs a platform that isn't connected yet, tell them to run:
113
+ ```bash
114
+ one add <platform>
115
+ ```
116
+ This is interactive and opens the browser for OAuth. After connecting, the platform will appear in `one --agent connection list`.
@@ -0,0 +1,278 @@
1
+ # One Workflows — Multi-Step API Workflows
2
+
3
+ Workflows chain actions across platforms as JSON files stored at `.one/flows/<key>.flow.json`. Like n8n/Zapier but file-based.
4
+
5
+ ## Building a Workflow
6
+
7
+ ### Step 0: Design first
8
+
9
+ Before touching CLI commands:
10
+ 1. Clarify the end goal — what output does the user need?
11
+ 2. Map every step required to deliver that output
12
+ 3. Identify where AI analysis is needed (summarization, scoring, classification)
13
+ 4. Write the step sequence as a plain list before constructing JSON
14
+
15
+ Common mistake: jumping straight to `actions search` and building a raw data pipe. Design first.
16
+
17
+ ### Step 1: Discover connections
18
+
19
+ ```bash
20
+ one --agent connection list
21
+ ```
22
+
23
+ ### Step 2: Get knowledge for EACH action
24
+
25
+ ```bash
26
+ one --agent actions search <platform> "<query>" -t execute
27
+ one --agent actions knowledge <platform> <actionId>
28
+ ```
29
+
30
+ You MUST call knowledge for every action in the workflow — it tells you the exact body structure, required fields, and path variables.
31
+
32
+ ### Step 3: Build the workflow JSON
33
+
34
+ ### Step 4: Create
35
+
36
+ ```bash
37
+ one --agent flow create <key> --definition '<json>'
38
+ ```
39
+
40
+ Or write directly to `.one/flows/<key>.flow.json`.
41
+
42
+ ### Step 5: Validate
43
+
44
+ ```bash
45
+ one --agent flow validate <key>
46
+ ```
47
+
48
+ ### Step 6: Execute
49
+
50
+ ```bash
51
+ one --agent flow execute <key> -i connectionKey=xxx -i param=value
52
+ ```
53
+
54
+ ## Workflow JSON Schema
55
+
56
+ ```json
57
+ {
58
+ "key": "welcome-customer",
59
+ "name": "Welcome New Customer",
60
+ "description": "Look up Stripe customer, send welcome email",
61
+ "version": "1",
62
+ "inputs": {
63
+ "stripeConnectionKey": {
64
+ "type": "string",
65
+ "required": true,
66
+ "description": "Stripe connection key",
67
+ "connection": { "platform": "stripe" }
68
+ },
69
+ "customerEmail": {
70
+ "type": "string",
71
+ "required": true
72
+ }
73
+ },
74
+ "steps": [...]
75
+ }
76
+ ```
77
+
78
+ ### Input Fields
79
+
80
+ | Field | Description |
81
+ |---|---|
82
+ | `type` | `string`, `number`, `boolean`, `object`, `array` |
83
+ | `required` | Whether input must be provided (default: true) |
84
+ | `default` | Default value if not provided |
85
+ | `description` | Human-readable description |
86
+ | `connection` | `{ "platform": "gmail" }` — enables auto-resolution |
87
+
88
+ Connection inputs with a `connection` field auto-resolve if the user has exactly one connection for that platform.
89
+
90
+ ## Selector Syntax
91
+
92
+ | Pattern | Resolves To |
93
+ |---|---|
94
+ | `$.input.connectionKey` | Input value |
95
+ | `$.steps.stepId.response` | Full API response from a step |
96
+ | `$.steps.stepId.response.data[0].email` | Nested field with array index |
97
+ | `$.steps.stepId.response.data[*].id` | Wildcard — maps array to field |
98
+ | `$.env.MY_VAR` | Environment variable |
99
+ | `$.loop.item` | Current loop item |
100
+ | `$.loop.i` | Current loop index |
101
+ | `"Hello {{$.steps.getUser.response.data.name}}"` | String interpolation |
102
+
103
+ A pure `$.xxx` value resolves to the raw type. A string containing `{{$.xxx}}` does string interpolation.
104
+
105
+ ## Step Types
106
+
107
+ ### `action` — Execute a One API action
108
+
109
+ ```json
110
+ {
111
+ "id": "findCustomer",
112
+ "type": "action",
113
+ "action": {
114
+ "platform": "stripe",
115
+ "actionId": "conn_mod_def::xxx::yyy",
116
+ "connectionKey": "$.input.stripeConnectionKey",
117
+ "data": { "query": "email:'{{$.input.customerEmail}}'" }
118
+ }
119
+ }
120
+ ```
121
+
122
+ ### `transform` — JS expression (implicit return)
123
+
124
+ ```json
125
+ {
126
+ "id": "extractNames",
127
+ "type": "transform",
128
+ "transform": { "expression": "$.steps.findCustomer.response.data.map(c => c.name)" }
129
+ }
130
+ ```
131
+
132
+ ### `code` — Multi-line JS (explicit return, async, supports await)
133
+
134
+ ```json
135
+ {
136
+ "id": "processData",
137
+ "type": "code",
138
+ "code": {
139
+ "source": "const customers = $.steps.list.response.data;\nreturn customers.map(c => ({...c, tier: c.spend > 1000 ? 'gold' : 'silver'}));"
140
+ }
141
+ }
142
+ ```
143
+
144
+ ### `condition` — If/then/else branching
145
+
146
+ ```json
147
+ {
148
+ "id": "checkFound",
149
+ "type": "condition",
150
+ "condition": {
151
+ "expression": "$.steps.find.response.data.length > 0",
152
+ "then": [{ "id": "sendEmail", "type": "action", "action": {...} }],
153
+ "else": [{ "id": "logNotFound", "type": "transform", "transform": { "expression": "'Not found'" } }]
154
+ }
155
+ }
156
+ ```
157
+
158
+ ### `loop` — Iterate over an array
159
+
160
+ ```json
161
+ {
162
+ "id": "processOrders",
163
+ "type": "loop",
164
+ "loop": {
165
+ "over": "$.steps.listOrders.response.orders",
166
+ "as": "order",
167
+ "maxConcurrency": 5,
168
+ "steps": [...]
169
+ }
170
+ }
171
+ ```
172
+
173
+ ### `parallel` — Run steps concurrently
174
+
175
+ ```json
176
+ {
177
+ "id": "lookups",
178
+ "type": "parallel",
179
+ "parallel": { "maxConcurrency": 5, "steps": [...] }
180
+ }
181
+ ```
182
+
183
+ ### `file-read` / `file-write` — Filesystem access
184
+
185
+ ```json
186
+ { "id": "read", "type": "file-read", "fileRead": { "path": "./data/config.json", "parseJson": true } }
187
+ { "id": "write", "type": "file-write", "fileWrite": { "path": "./output/results.json", "content": "$.steps.transform.output" } }
188
+ ```
189
+
190
+ ### `while` — Condition-driven loop (do-while)
191
+
192
+ ```json
193
+ {
194
+ "id": "paginate",
195
+ "type": "while",
196
+ "while": {
197
+ "condition": "$.steps.paginate.output.lastResult.nextPageToken != null",
198
+ "maxIterations": 50,
199
+ "steps": [...]
200
+ }
201
+ }
202
+ ```
203
+
204
+ ### `flow` — Execute a sub-flow
205
+
206
+ ```json
207
+ {
208
+ "id": "enrich",
209
+ "type": "flow",
210
+ "flow": { "key": "enrich-customer", "inputs": { "email": "$.steps.get.response.email" } }
211
+ }
212
+ ```
213
+
214
+ ### `paginate` — Auto-collect paginated results
215
+
216
+ ```json
217
+ {
218
+ "id": "allMessages",
219
+ "type": "paginate",
220
+ "paginate": {
221
+ "action": { "platform": "gmail", "actionId": "...", "connectionKey": "$.input.gmailKey" },
222
+ "pageTokenField": "nextPageToken",
223
+ "resultsField": "messages",
224
+ "inputTokenParam": "queryParams.pageToken",
225
+ "maxPages": 10
226
+ }
227
+ }
228
+ ```
229
+
230
+ ### `bash` — Shell commands (requires `--allow-bash`)
231
+
232
+ ```json
233
+ {
234
+ "id": "analyze",
235
+ "type": "bash",
236
+ "bash": { "command": "cat /tmp/data.json | claude --print 'Analyze this' --output-format json", "timeout": 180000, "parseJson": true }
237
+ }
238
+ ```
239
+
240
+ ## Error Handling
241
+
242
+ ```json
243
+ { "onError": { "strategy": "retry", "retries": 3, "retryDelayMs": 1000 } }
244
+ ```
245
+
246
+ Strategies: `fail` (default), `continue`, `retry`, `fallback`.
247
+
248
+ Conditional execution: `"if": "$.steps.find.response.data.length > 0"`
249
+
250
+ ## AI-Augmented Pattern: file-write -> bash -> code
251
+
252
+ When raw data needs analysis, use this pattern:
253
+ 1. `file-write` — save data to temp file (API responses are too large to inline)
254
+ 2. `bash` — call `claude --print` to analyze (set timeout to 180000+, use `--output-format json`)
255
+ 3. `code` — parse and structure the AI output for downstream steps
256
+
257
+ ## CLI Commands
258
+
259
+ ```bash
260
+ one --agent flow create <key> --definition '<json>'
261
+ one --agent flow list
262
+ one --agent flow validate <key>
263
+ one --agent flow execute <key> -i key=value
264
+ one --agent flow execute <key> --dry-run -i key=value
265
+ one --agent flow execute <key> --dry-run --mock -i key=value
266
+ one --agent flow execute <key> --allow-bash -i key=value
267
+ one --agent flow runs [flowKey]
268
+ one --agent flow resume <runId>
269
+ ```
270
+
271
+ ## Important Notes
272
+
273
+ - Connection keys are inputs, not hardcoded — makes workflows portable
274
+ - Action IDs in examples are placeholders — always use `actions search` to find real IDs
275
+ - Code steps support `require('crypto')`, `require('buffer')`, `require('url')`, `require('path')` — `fs`, `http`, `child_process` are blocked
276
+ - Bash steps require `--allow-bash` flag
277
+ - State is persisted after every step — resume picks up where it left off
278
+ - For bash+Claude steps, always set timeout to 180000+ and run sequentially (not in parallel)
@@ -0,0 +1,179 @@
1
+ # One Webhook Relay
2
+
3
+ Webhook relay receives webhooks from a source platform and forwards the event data to a destination platform using passthrough actions with Handlebars templates — no middleware, no code needed.
4
+
5
+ ## Supported Source Platforms
6
+
7
+ Only these platforms can send webhooks: **Airtable**, **Attio**, **GitHub**, **Google Calendar**, **Stripe**. Any connected platform can be a destination.
8
+
9
+ ## Workflow
10
+
11
+ ### Step 1: Discover connections
12
+
13
+ ```bash
14
+ one --agent connection list
15
+ ```
16
+
17
+ Identify source (sends webhooks) and destination (receives forwarded data). Note both connection keys.
18
+
19
+ ### Step 2: Get event types
20
+
21
+ ```bash
22
+ one --agent relay event-types <source-platform>
23
+ ```
24
+
25
+ ### Step 3: Get source knowledge (understand the incoming payload)
26
+
27
+ ```bash
28
+ one --agent actions search <source-platform> "<event description>" -t knowledge
29
+ one --agent actions knowledge <source-platform> <actionId>
30
+ ```
31
+
32
+ The knowledge tells you the webhook payload structure — these fields become `{{payload.*}}` in your templates.
33
+
34
+ ### Step 4: Get destination knowledge (understand the outgoing API)
35
+
36
+ ```bash
37
+ one --agent actions search <dest-platform> "<what you want to do>" -t execute
38
+ one --agent actions knowledge <dest-platform> <actionId>
39
+ ```
40
+
41
+ The knowledge tells you required body fields — these become the keys in your passthrough action's `body`.
42
+
43
+ ### Step 5: Create the relay endpoint
44
+
45
+ ```bash
46
+ one --agent relay create \
47
+ --connection-key <source-connection-key> \
48
+ --description "Forward <event> from <source> to <dest>" \
49
+ --event-filters '["event.type"]' \
50
+ --create-webhook
51
+ ```
52
+
53
+ Always use `--create-webhook` — it registers the webhook URL with the source platform automatically.
54
+
55
+ ### Step 6: Activate with a passthrough action
56
+
57
+ ```bash
58
+ one --agent relay activate <relay-id> --actions '[{
59
+ "type": "passthrough",
60
+ "actionId": "<destination-action-id>",
61
+ "connectionKey": "<destination-connection-key>",
62
+ "body": {
63
+ "field": "{{payload.path.to.value}}"
64
+ },
65
+ "eventFilters": ["event.type"]
66
+ }]'
67
+ ```
68
+
69
+ ## Template Context
70
+
71
+ | Variable | Description |
72
+ |---|---|
73
+ | `{{relayEventId}}` | Unique relay event ID |
74
+ | `{{platform}}` | Source platform name |
75
+ | `{{eventType}}` | Webhook event type |
76
+ | `{{payload}}` | Full incoming webhook body |
77
+ | `{{timestamp}}` | When event was received |
78
+ | `{{connectionId}}` | Source connection UUID |
79
+
80
+ Access nested fields with dot notation: `{{payload.data.object.email}}`
81
+
82
+ Use `{{json payload}}` to embed a full object as a JSON string.
83
+
84
+ ## Action Types
85
+
86
+ ### `passthrough` — Forward to another platform's API (primary)
87
+
88
+ ```json
89
+ {
90
+ "type": "passthrough",
91
+ "actionId": "<action-id>",
92
+ "connectionKey": "<dest-connection-key>",
93
+ "body": { "channel": "#alerts", "text": "New: {{payload.data.object.name}}" },
94
+ "eventFilters": ["customer.created"]
95
+ }
96
+ ```
97
+
98
+ The `body`, `headers`, and `query` fields all support Handlebars templates.
99
+
100
+ ### `url` — Forward raw event to a URL
101
+
102
+ ```json
103
+ {
104
+ "type": "url",
105
+ "url": "https://your-app.com/webhooks/handler",
106
+ "secret": "optional-signing-secret",
107
+ "eventFilters": ["customer.created"]
108
+ }
109
+ ```
110
+
111
+ ### `agent` — Send to an agent
112
+
113
+ ```json
114
+ {
115
+ "type": "agent",
116
+ "agentId": "<agent-uuid>",
117
+ "eventFilters": ["customer.created"]
118
+ }
119
+ ```
120
+
121
+ ## Complete Example: Stripe customer.created -> Slack message
122
+
123
+ ```bash
124
+ # 1. Get connections
125
+ one --agent connection list
126
+ # stripe: live::stripe::default::abc123, slack: live::slack::default::xyz789
127
+
128
+ # 2. Get event types
129
+ one --agent relay event-types stripe
130
+
131
+ # 3. Get Slack send message action
132
+ one --agent actions search slack "send message" -t execute
133
+ one --agent actions knowledge slack <actionId>
134
+
135
+ # 4. Create relay
136
+ one --agent relay create \
137
+ --connection-key "live::stripe::default::abc123" \
138
+ --description "Notify Slack on new Stripe customers" \
139
+ --event-filters '["customer.created"]' \
140
+ --create-webhook
141
+
142
+ # 5. Activate
143
+ one --agent relay activate <relay-id> --actions '[{
144
+ "type": "passthrough",
145
+ "actionId": "<slack-send-message-action-id>",
146
+ "connectionKey": "live::slack::default::xyz789",
147
+ "body": {
148
+ "channel": "#alerts",
149
+ "text": "New Stripe customer: {{payload.data.object.name}} ({{payload.data.object.email}})"
150
+ },
151
+ "eventFilters": ["customer.created"]
152
+ }]'
153
+ ```
154
+
155
+ ## Management Commands
156
+
157
+ ```bash
158
+ one --agent relay list [--limit <n>] [--page <n>]
159
+ one --agent relay get <id>
160
+ one --agent relay update <id> [--actions <json>] [--description <desc>]
161
+ one --agent relay delete <id>
162
+ one --agent relay events [--platform <p>] [--event-type <t>] [--limit <n>]
163
+ one --agent relay event <id>
164
+ one --agent relay deliveries --endpoint-id <id>
165
+ one --agent relay deliveries --event-id <id>
166
+ ```
167
+
168
+ ## Debugging
169
+
170
+ 1. Check endpoint is active: `one --agent relay get <id>` — verify `active: true`
171
+ 2. Check events arriving: `one --agent relay events --platform <p> --limit 5`
172
+ 3. Check delivery status: `one --agent relay deliveries --event-id <id>`
173
+ 4. Inspect payload: `one --agent relay event <id>` — verify template paths
174
+
175
+ ## Important Notes
176
+
177
+ - Event filters on both the endpoint and individual actions must match
178
+ - Multiple actions can be attached to a single relay endpoint
179
+ - Missing template variables resolve to empty strings — verify `{{payload.*}}` paths against the actual payload