@imbrace/cli 0.2.0 → 0.4.0

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.
Files changed (71) hide show
  1. package/README.md +7 -0
  2. package/dist/base-command.js +20 -18
  3. package/dist/commands/ai-agent/create.js +8 -7
  4. package/dist/commands/ai-agent/delete.js +6 -4
  5. package/dist/commands/ai-agent/get.js +5 -5
  6. package/dist/commands/ai-agent/list-files.js +7 -5
  7. package/dist/commands/ai-agent/list-folders.js +7 -6
  8. package/dist/commands/ai-agent/list-models.js +5 -5
  9. package/dist/commands/ai-agent/list-providers.js +5 -5
  10. package/dist/commands/ai-agent/list.js +7 -5
  11. package/dist/commands/ai-agent/update.js +5 -4
  12. package/dist/commands/data-board/create-field.js +6 -4
  13. package/dist/commands/data-board/create-item.js +10 -8
  14. package/dist/commands/data-board/create.js +8 -6
  15. package/dist/commands/data-board/delete-item.js +6 -4
  16. package/dist/commands/data-board/export-csv.js +3 -2
  17. package/dist/commands/data-board/list-items.js +9 -11
  18. package/dist/commands/data-board/list.js +7 -5
  19. package/dist/commands/data-board/update-item.js +8 -6
  20. package/dist/commands/docs.d.ts +10 -0
  21. package/dist/commands/docs.js +39 -0
  22. package/dist/commands/login.d.ts +0 -1
  23. package/dist/commands/login.js +39 -55
  24. package/dist/commands/whoami.js +0 -2
  25. package/dist/commands/workflow/conn/create.js +33 -16
  26. package/dist/commands/workflow/conn/delete.js +6 -4
  27. package/dist/commands/workflow/conn/get.js +5 -4
  28. package/dist/commands/workflow/conn/list.js +7 -5
  29. package/dist/commands/workflow/create.js +16 -14
  30. package/dist/commands/workflow/delete.js +6 -4
  31. package/dist/commands/workflow/disable.js +9 -4
  32. package/dist/commands/workflow/enable.js +9 -4
  33. package/dist/commands/workflow/folder/create.js +11 -10
  34. package/dist/commands/workflow/folder/delete.js +6 -4
  35. package/dist/commands/workflow/folder/get.js +5 -4
  36. package/dist/commands/workflow/folder/list.js +7 -5
  37. package/dist/commands/workflow/folder/update.js +6 -4
  38. package/dist/commands/workflow/get.js +5 -4
  39. package/dist/commands/workflow/list.js +8 -6
  40. package/dist/commands/workflow/mcp/create.js +10 -9
  41. package/dist/commands/workflow/mcp/delete.js +6 -4
  42. package/dist/commands/workflow/mcp/get.js +5 -4
  43. package/dist/commands/workflow/mcp/list.js +9 -5
  44. package/dist/commands/workflow/mcp/rotate-token.js +7 -5
  45. package/dist/commands/workflow/move.js +10 -4
  46. package/dist/commands/workflow/node/add-raw.js +6 -4
  47. package/dist/commands/workflow/node/add.js +70 -21
  48. package/dist/commands/workflow/node/delete.js +12 -4
  49. package/dist/commands/workflow/node/list.js +8 -5
  50. package/dist/commands/workflow/node/update.js +44 -8
  51. package/dist/commands/workflow/piece/detail.js +5 -4
  52. package/dist/commands/workflow/piece/list.js +22 -6
  53. package/dist/commands/workflow/publish.js +9 -4
  54. package/dist/commands/workflow/run-detail.js +5 -4
  55. package/dist/commands/workflow/run.js +10 -7
  56. package/dist/commands/workflow/runs.js +7 -5
  57. package/dist/config.d.ts +5 -5
  58. package/dist/config.js +6 -12
  59. package/dist/lib/ai-agent.d.ts +40 -0
  60. package/dist/lib/ai-agent.js +150 -0
  61. package/dist/lib/client.d.ts +7 -0
  62. package/dist/lib/client.js +21 -0
  63. package/dist/lib/gateway.d.ts +3 -0
  64. package/dist/lib/gateway.js +31 -0
  65. package/dist/lib/workflow.d.ts +20 -0
  66. package/dist/lib/workflow.js +71 -0
  67. package/dist/select-board.js +4 -3
  68. package/llms.txt +626 -0
  69. package/package.json +4 -3
  70. package/dist/http.d.ts +0 -9
  71. package/dist/http.js +0 -40
package/llms.txt ADDED
@@ -0,0 +1,626 @@
1
+ # Imbrace CLI
2
+
3
+ > Imbrace CLI allows coding agents and developers to interact with the Imbrace platform via command line. Imbrace is a CRM platform supporting AI chat assistants, data boards (CRM pipelines), workflows, and more.
4
+
5
+ Things to remember when using Imbrace CLI:
6
+
7
+ - Always run `imbrace login` first. Credentials are stored via the `conf` package — exact path depends on OS:
8
+ - macOS: `~/Library/Preferences/imbrace-nodejs/config.json`
9
+ - Linux: `~/.config/imbrace-nodejs/config.json`
10
+ - Windows: `%APPDATA%\imbrace-nodejs\Config\config.json`
11
+ - If a command returns a 401 error, run `imbrace login` again to refresh credentials.
12
+ - All commands support `--json` flag for machine-readable output — always use `--json` when scripting or using a coding agent.
13
+ - Run `imbrace data-board list --json` first to get Board IDs (`brd_...`) before using other data-board commands.
14
+ - Board items use the format `{ fields: [{ board_field_id, value }] }` — field IDs are fetched automatically in interactive mode.
15
+ - Field types available (16): `ShortText`, `LongText`, `Number`, `Date`, `Email`, `Phone`, `Currency`, `SingleSelection`, `MultipleSelection`, `Checkbox`, `Assignee`, `MultipleAssignee`, `Link`, `Notes`, `Origin`, `Priority`. **Do NOT use `Dropdown`** — backend rejects it (use `SingleSelection` instead).
16
+ - Run `imbrace ai-agent list --json` first to get Agent IDs before using other ai-agent commands.
17
+
18
+ ## Authentication
19
+
20
+ - `imbrace login --api-key api_xxx...` — Login with API key (recommended for CI/CD and coding agents)
21
+ - `imbrace login --email user@example.com --password mypass` — Login with email and password
22
+ - `imbrace logout` — Clear saved credentials
23
+ - `imbrace whoami --json` — Verify current authentication status
24
+
25
+ ## Built-in commands
26
+
27
+ - `imbrace help [command]` — Show help for any command
28
+ - `imbrace autocomplete [shell]` — Display shell completion install instructions (bash, zsh, fish, powershell)
29
+ - `imbrace --version` — Print CLI version
30
+ - `imbrace docs` — Print the bundled `llms.txt` (this file). Pipe to a file (`imbrace docs > llms.txt`) and feed into a coding agent's context for one-shot reference. `--path` prints just the absolute path; `--json` outputs `{ path, content }`.
31
+
32
+ ## Data Board Commands
33
+
34
+ - `imbrace data-board list --json` — List all boards and their IDs (`brd_...`)
35
+ - `imbrace data-board create --name "Sales Pipeline" --json` — Create a new board
36
+ - `imbrace data-board create-field <boardId> --name "Company" --type ShortText --json` — Add a field to a board
37
+ - `imbrace data-board create-item <boardId> --fields '[{"board_field_id":"<id>","value":"Acme"}]' --json` — Create a record (Name field is required)
38
+ - `imbrace data-board list-items --board-id <id> --limit 20 --skip 0 --json` — List records with pagination
39
+ - `imbrace data-board list-items --board-id <id> --q "Acme" --json` — Full-text search records
40
+ - `imbrace data-board update-item <boardId> <itemId> --data '[{"key":"<fieldId>","value":"New"}]' --json` — Update a record
41
+ - `imbrace data-board delete-item <boardId> <itemId> --yes --json` — Delete a record
42
+ - `imbrace data-board export-csv --board-id <id> --out ./board.csv` — Export board to CSV file
43
+
44
+ ## AI Agent Commands
45
+
46
+ **CRUD:**
47
+ - `imbrace ai-agent list --json` — List all AI agents and their IDs
48
+ - `imbrace ai-agent get <id> --json` — Get details of an AI agent
49
+ - `imbrace ai-agent create --name "Sales Bot" --json` — Create (minimal — defaults to system provider, "Default" model)
50
+ - `imbrace ai-agent create --name "X" --instructions "..." --personality "..." --tone "..." --json` — Create with full Behavior Settings
51
+ - `imbrace ai-agent update <id> --name "New Name" --json` — Update any subset of fields (others preserved via PUT-merge)
52
+ - `imbrace ai-agent update <id> --temperature 0.7 --tone "Casual" --json` — Update Behavior Settings
53
+ - `imbrace ai-agent delete <id> --yes --json` — Delete an AI agent
54
+
55
+ **Discovery (LLM providers/models):**
56
+ - `imbrace ai-agent list-providers --json` — List LLM providers (system + custom). Returns the UUID `provider_id` to pass to `--provider-id`.
57
+ - `imbrace ai-agent list-models --provider-id <id> --json` — List models for a provider. Use `system` for the default provider.
58
+
59
+ **Discovery (Knowledge Hub):**
60
+ - `imbrace ai-agent list-folders [--search <q>] --json` — List Knowledge Hub folders for `--folder-ids`.
61
+ - `imbrace ai-agent list-files --folder-id <id> --json` — List files inside a folder for `--file-ids`.
62
+
63
+ ### AI Agent flags
64
+
65
+ `create` and `update` accept the same flags. `update` lets you change any subset; unspecified flags stay unchanged.
66
+
67
+ **Identity:**
68
+ - `--name` / `-n` — Agent name (required for create)
69
+ - `--description` / `-d` — Short description (shown under the title in UI list)
70
+ - `--instructions` / `-i` — System prompt sent on every chat
71
+
72
+ **Model:**
73
+ - `--model` — LLM model name (default: `Default` for system provider). Discover via `list-models`. **System provider only has one model named `Default`** — passing other names (like `gpt-4o`) makes the UI dropdown render empty even though the agent saves.
74
+ - `--provider-id` — LLM provider ID (default: `system`). Discover via `list-providers`. **Pass the UUID `provider_id`, NOT the MongoDB `_id`** — the UI matches dropdowns against the UUID.
75
+ - `--mode` — `standard` | `advanced` (default: standard)
76
+ - `--temperature` — 0.0–2.0 (default: 0.1). Lower = deterministic, higher = creative.
77
+
78
+ **Behavior Settings (UI tab):**
79
+ - `--personality` — Persona / role description → `personality_role`
80
+ - `--core-task` — Main tasks the agent performs → `core_task`
81
+ - `--tone` — Tone and style → `tone_and_style`
82
+ - `--response-length` — `short` | `medium` | `long`
83
+ - `--banned-words` — Comma-separated. **Word-level filter** on outputs (for topic refusal use `--instructions`).
84
+ - `--category` — `Support` | `Sales` | `Marketing` | `Team` | `Other`. Default: `Support`.
85
+ - `--guardrail-id` — Attach a guardrail by ID
86
+ - `--preload-information` — Static info auto-injected into context every chat
87
+
88
+ **Knowledge Support (UI tab) — comma-separated IDs:**
89
+ - `--folder-ids "id1,id2"` — Knowledge Hub folder IDs (RAG sources). Discover via `list-folders`.
90
+ - `--default-folder-id <id>` — Default folder for new files
91
+ - `--knowledge-hubs "id1,id2"` — Knowledge Hub IDs
92
+ - `--board-ids "brd_xxx,brd_yyy"` — Document Model (data board) IDs. Discover via `imbrace data-board list`.
93
+ - `--file-ids "id1,id2"` — Pre-uploaded file IDs. Discover via `list-files --folder-id <id>`.
94
+
95
+ **Runtime toggles (boolean, support `--no-X`):**
96
+ - `--show-thinking` / `--no-show-thinking` — Show model's thinking process (default: false)
97
+ - `--streaming` / `--no-streaming` — Stream response token-by-token (default: true)
98
+ - `--use-memory` / `--no-use-memory` — Remember conversation context across turns (default: true). **Known issue:** `--no-use-memory` at create may not stick (backend default override) — workaround: update after create.
99
+
100
+ **Other:**
101
+ - `--yes` / `-y` — Skip confirmation on delete
102
+ - `--json` — Full JSON output (machine-readable)
103
+ - `--id-only` — Print only the new agent ID (pipe-friendly, no jq). On `create` only.
104
+ - `-h` / `--help` — Show usage
105
+
106
+ ### Full create example (Behavior Settings + custom provider + Knowledge)
107
+
108
+ ```bash
109
+ # 1. Discover provider + model
110
+ imbrace ai-agent list-providers --json
111
+ imbrace ai-agent list-models --provider-id e2629292-7e9f-4d55-ba18-6827747eab33 --json
112
+
113
+ # 2. Discover Knowledge Hub folder + board (Document Model)
114
+ imbrace ai-agent list-folders --search support --json
115
+ imbrace data-board list --json
116
+
117
+ # 3. Create with full settings
118
+ imbrace ai-agent create \
119
+ --name "Customer Support Specialist" \
120
+ --description "Senior AI customer support agent" \
121
+ --instructions "You are a senior customer support specialist..." \
122
+ --personality "Friendly and professional" \
123
+ --core-task "Answer product inquiries, help track orders" \
124
+ --tone "Polite, professional, warm" \
125
+ --response-length "medium" \
126
+ --banned-words "stupid, idiot" \
127
+ --category "Support" \
128
+ --provider-id "e2629292-7e9f-4d55-ba18-6827747eab33" \
129
+ --model "gpt-4o-mini" \
130
+ --temperature 0.3 \
131
+ --folder-ids "69bb82faa2cc764639bc6bdb" \
132
+ --board-ids "brd_e5450d76-84d4-4c34-8b13-3d0f1873b53b" \
133
+ --json
134
+ ```
135
+
136
+ ### How AI Agent create works (under the hood)
137
+
138
+ `imbrace ai-agent create` calls `client.agent.createUseCase({ usecase, assistant })` from `@imbrace/sdk`, which atomically creates:
139
+ 1. An AI assistant (model, instructions, prompt)
140
+ 2. A web channel (for chat widget demo)
141
+ 3. A use-case template (the card shown on `cloud.imbrace.co/ai-agent`)
142
+
143
+ The `workflow_name` field is auto-generated as `<slug>_v<timestamp>` to ensure uniqueness — required by backend, must be snake_case (no spaces or special characters).
144
+
145
+ ### Full request body sent to backend
146
+
147
+ The route mirrors the frontend `createCustomUseCase` payload (see `new-frontend/src/pages/AIAssistantManagement/useAIAssistantFormHook.tsx`):
148
+
149
+ ```ts
150
+ {
151
+ usecase: { title, short_description, agent_type, demo_url, supported_channels },
152
+ assistant: {
153
+ // Identity
154
+ name, description, instructions, workflow_name, credential_name,
155
+ // Model
156
+ provider_id: "system", model_id: "gpt-4o",
157
+ // Agent scope
158
+ agent_type: "agent", mode: "standard", version: 2, channel, category,
159
+ // Behavior (Behavior Settings tab in UI)
160
+ personality_role, core_task, tone_and_style, response_length,
161
+ banned_words, preload_information, guardrail_id, show_thinking_process,
162
+ // Runtime
163
+ streaming: true, use_memory: true, temperature: 0.1,
164
+ // Knowledge (Knowledge Support tab in UI)
165
+ knowledge_hubs: [], folder_ids: [], default_folder_id, board_ids: [], file_ids: [],
166
+ // Advanced (Advanced Settings tab in UI)
167
+ workflow_function_call: [], sub_agents: [], team_leads: [],
168
+ // RAG / tooling
169
+ metadata: {
170
+ other_requirements: [], channel_id: "", team_ids: [], tool_server: null,
171
+ enable_echart: false, top_k_relevant_results: 3, top_k: 40, max_steps: 10
172
+ }
173
+ }
174
+ }
175
+ ```
176
+
177
+ **Fields not yet exposed via CLI flags** (set to defaults — modify via UI or future CLI updates): `channel`, `preload_information`, `knowledge_hubs`, `folder_ids`, `default_folder_id`, `board_ids`, `file_ids`, `workflow_function_call`, `sub_agents`, `team_leads`, `metadata.tool_server`, `metadata.team_ids`, `metadata.other_requirements`.
178
+
179
+ **IMPORTANT — All AI Agent content must be in English.** This includes `--name`, `--description`, and `--instructions`. Reasons:
180
+ 1. The slug for `workflow_name` is derived from the name. Vietnamese diacritics get stripped and produce unreadable slugs (e.g. `"Trợ lý hỗ trợ"` → `tr_l_h_tr_v...`).
181
+ 2. English content keeps logs, search, and downstream LLM behavior consistent.
182
+
183
+ If the user describes an agent in Vietnamese, translate the full payload to English before calling `imbrace ai-agent create`.
184
+
185
+ ## Workflow Commands
186
+
187
+ A workflow (powered by Activepieces) is a chain of nodes: a trigger fires, then actions run in sequence. Use it for automation — e.g. "when Slack message arrives → ask AI → reply to thread".
188
+
189
+ **Flow CRUD:**
190
+
191
+ - `imbrace workflow list --json` — List all workflows and their IDs
192
+ - `imbrace workflow list --folder-id <folderId> --json` — Filter to flows in one folder/category
193
+ - `imbrace workflow list --folder-id NULL --json` — Only flows that aren't in any folder
194
+ - `imbrace workflow get <flowId> --json` — Get details (including node tree)
195
+ - `imbrace workflow create --name "My Flow" --json` — Create an empty workflow
196
+ - `imbrace workflow create --name "X" --folder-id <folderId> --json` — Create directly inside a category folder
197
+ - `imbrace workflow move <flowId> --folder-id <folderId>` — Move a flow into a folder. Pass `NULL` to unfile.
198
+ - `imbrace workflow delete <flowId> --yes --json` — Delete a workflow
199
+
200
+ **Discover available integrations (pieces):**
201
+
202
+ - `imbrace workflow piece list --json` — List all 126 integrations (Slack, Gmail, OpenAI, ...)
203
+ - `imbrace workflow piece list --search slack --json` — Search integrations
204
+ - `imbrace workflow piece detail <pieceName> --json` — Get full schema (actions, triggers, input fields)
205
+
206
+ **Build node tree:**
207
+
208
+ - `imbrace workflow node list <flowId> --json` — Show the trigger + action chain
209
+ - `imbrace workflow node add <flowId> --type trigger --piece <name> --trigger-name <id> --input '{...}' --json` — Add trigger
210
+ - `imbrace workflow node add <flowId> --type action --piece <name> --action-name <id> --after <parent> --input '{...}' --json` — Add action
211
+ - `imbrace workflow node update <flowId> <nodeName> --input '{...}' --json` — Update node input
212
+ - `imbrace workflow node delete <flowId> <nodeName> --yes --json` — Remove a node
213
+ - `imbrace workflow node add-raw <flowId> --op-file <path>` — Apply raw flow operation. Use for advanced node types (`ROUTER`, `LOOP_ON_ITEMS`, `CODE`) that `node add` doesn't expose. Body shape: `{ type: "ADD_ACTION" \| "UPDATE_ACTION" \| "UPDATE_TRIGGER" \| "DELETE_ACTION", request: {...} }`. Also accepts `--op '<inline JSON>'` or `--stdin`.
214
+
215
+ **Run history:**
216
+
217
+ - `imbrace workflow runs --json` — List recent runs
218
+ - `imbrace workflow run-detail <runId> --json` — Get run details (status, failed step, logs)
219
+
220
+ **Connections (OAuth / API keys for external services):**
221
+
222
+ - `imbrace workflow conn list --json` — List saved connections
223
+ - `imbrace workflow conn get <connId> --json` — Get details of a single connection
224
+ - `imbrace workflow conn create --piece <name> --type <T> --value "<token>" --json` — Save credential. `--type`: `SECRET_TEXT` | `OAUTH2` | `CLOUD_OAUTH2` | `BASIC_AUTH` | `CUSTOM_AUTH`
225
+ - `imbrace workflow conn delete <connId> --yes` — Delete a connection
226
+
227
+ **Folders (organize flows — UI calls them "Categories"):**
228
+
229
+ - `imbrace workflow folder list --json` — List all folders
230
+ - `imbrace workflow folder get <folderId> --json` — Folder details
231
+ - `imbrace workflow folder create --name "Sales" --json` — Create (auto-resolves projectId)
232
+ - `imbrace workflow folder update <folderId> --name "Renamed" --json` — Rename
233
+ - `imbrace workflow folder delete <folderId> --yes` — Delete (flows inside become unfiled, NOT deleted)
234
+
235
+ The platform auto-creates 4 system folders that show up as Categories in the UI. Use `workflow folder list` to discover their IDs:
236
+
237
+ | UI Category | Backend folder name | Purpose |
238
+ |---|---|---|
239
+ | `Channel Workflow` | `Channel Workflow` | Messaging / channel automation |
240
+ | `Board Automation` | `Board Automation` | Triggered by data-board events; flows usually use the `automate-data-board` action with a `boardId` |
241
+ | `AI Agent Skills` | `AI Agent Capabilities` | Skills callable by AI agents |
242
+ | `Others` | `Others` | Default catch-all |
243
+
244
+ To make a flow appear in a UI Category, place it in the matching system folder via `workflow create --folder-id <id>` or `workflow move <flowId> --folder-id <id>`. Flows created with no folder land in "All flows" only (not in any Category).
245
+
246
+ **MCP servers (Model Context Protocol — let AI agents call piece tools):**
247
+
248
+ - `imbrace workflow mcp list --json` — List MCP servers for the project
249
+ - `imbrace workflow mcp get <mcpId> --json` — Server details (token NOT shown for security)
250
+ - `imbrace workflow mcp create --name "My MCP" --json` — Create. **Token is shown once at creation — save it immediately.**
251
+ - `imbrace workflow mcp rotate-token <mcpId> --yes` — Issue a new token. Old token stops working immediately.
252
+ - `imbrace workflow mcp delete <mcpId> --yes` — Delete the server
253
+
254
+ **Lifecycle:**
255
+
256
+ - `imbrace workflow publish <flowId>` — Lock current draft as published version (REQUIRED before enable)
257
+ - `imbrace workflow enable <flowId>` — Enable auto-trigger
258
+ - `imbrace workflow disable <flowId>` — Stop auto-trigger (keeps published version)
259
+
260
+ **Trigger flow manually:**
261
+
262
+ - `imbrace workflow run <flowId> --payload '{...}' --json` — Trigger async (fire-and-forget)
263
+ - `imbrace workflow run <flowId> --payload '{...}' --sync --json` — Trigger and wait. ⚠️ Sync polling may time out at ~30s even when the run finishes faster — fall back to `imbrace workflow runs` + `run-detail <runId>` to verify.
264
+
265
+ **Order matters:** create flow → add nodes → **publish** → **enable** → run. Trying to `enable` before `publish` returns 500 "publishedFlowVersionId is required".
266
+
267
+ ### Workflow flags
268
+
269
+ **Flow-level:**
270
+ - `--name` / `-n` — Workflow display name (required for create)
271
+ - `--folder-id` — Folder to place flow in
272
+ - `--yes` / `-y` — Skip confirmation on delete
273
+ - `--json` — Machine-readable output
274
+
275
+ **Node-level:**
276
+ - `--type` — `trigger` or `action`
277
+ - `--piece` — Piece name (e.g. `@activepieces/piece-slack`)
278
+ - `--trigger-name` — Trigger identifier from piece (when `--type trigger`)
279
+ - `--action-name` — Action identifier from piece (when `--type action`)
280
+ - `--after` — Place node after this step name (default: append at end)
281
+ - `--input` — JSON string with field values (use `{{trigger.X}}` or `{{step_N.output.Y}}` for variables)
282
+ - `--connection` — Connection ID to authenticate the piece
283
+
284
+ **Run flags:**
285
+ - `--payload` — JSON payload to send (becomes `trigger.body` in flow)
286
+ - `--sync` — Wait for flow to finish (timeout 60s); without it, fire-and-forget
287
+ - `--limit` — Max runs to list (default 10)
288
+
289
+ ### How Workflow create works (under the hood)
290
+
291
+ `imbrace workflow create` calls `client.activepieces.createFlow({ displayName, projectId })`. The route auto-discovers `projectId` from existing flows so the user doesn't pass it.
292
+
293
+ Adding/editing nodes calls `client.activepieces.applyFlowOperation(flowId, { type, request })` with operation types:
294
+ - `UPDATE_TRIGGER` — replace trigger node
295
+ - `ADD_ACTION` — add an action after a parent step
296
+ - `UPDATE_ACTION` — change input of an existing action
297
+ - `DELETE_ACTION` — remove a node and re-link parent → child
298
+ - `LOCK_AND_PUBLISH` — finalize current version (used by `workflow publish`)
299
+ - `CHANGE_STATUS` — toggle ENABLED/DISABLED (used by `workflow enable/disable`)
300
+
301
+ Piece schemas (`piece detail`) come from a raw `GET /activepieces/v1/pieces/<pieceName>` because SDK's `listPieces()` only returns counts (`actions: 25`, `triggers: 12`), not field schemas.
302
+
303
+ ### Flow JSON anatomy
304
+
305
+ A workflow stores its node tree under `version.trigger`, with `nextAction` linking the chain:
306
+
307
+ ```ts
308
+ {
309
+ id: "06oWoBQpL...",
310
+ status: "ENABLED" | "DISABLED",
311
+ version: {
312
+ displayName: "My Flow",
313
+ trigger: {
314
+ name: "trigger",
315
+ type: "PIECE_TRIGGER", // or BRANCH, LOOP_ON_ITEMS, CODE
316
+ settings: { pieceName, triggerName, input },
317
+ nextAction: {
318
+ name: "step_1",
319
+ type: "PIECE",
320
+ settings: { pieceName, actionName, input },
321
+ nextAction: { name: "step_2", ... }
322
+ }
323
+ }
324
+ }
325
+ }
326
+ ```
327
+
328
+ ### Variable syntax inside node `input`
329
+
330
+ - `{{trigger.body.X}}` — field X from trigger payload
331
+ - `{{trigger.X}}` — top-level trigger field (for piece triggers)
332
+ - `{{step_1.output.Y}}` — output field Y from step_1
333
+ - `{{connections.<connId>.access_token}}` — connection field
334
+
335
+ ### Workflow anatomy — 6 layers
336
+
337
+ ```
338
+ Project
339
+ └─ Flow (container — id, name, status: ENABLED/DISABLED)
340
+ └─ Version (snapshot — DRAFT or LOCKED, contains the node tree)
341
+ └─ Nodes (cây trigger + actions, linked via nextAction)
342
+ ├─ trigger (always 1, type PIECE_TRIGGER or EMPTY)
343
+ └─ step_1, step_2, ... (0..N actions)
344
+ └─ Runs (execution history — status, logs per run)
345
+
346
+ Cross-flow shared:
347
+ ├─ Connections (OAuth / API keys, reused across flows)
348
+ └─ Pieces (catalog of 126 integrations: Slack, Gmail, OpenAI, ...)
349
+ ```
350
+
351
+ ### Node types
352
+
353
+ A node's `type` field determines its role in the flow:
354
+
355
+ | Type | Role | CLI support |
356
+ |---|---|---|
357
+ | `PIECE_TRIGGER` | "When does the flow run" — Slack message, webhook, cron, ... | ✅ `node add --type trigger` |
358
+ | `PIECE` | "What runs after" — send Slack, ask AI, HTTP request, ... | ✅ `node add --type action` |
359
+ | `EMPTY` | Placeholder before a real trigger is set (default after `workflow create`) | ✅ Read-only |
360
+ | `ROUTER` | Multi-condition switch (replaces legacy BRANCH) | ✅ `node add-raw` |
361
+ | `LOOP_ON_ITEMS` | Loop over an array | ✅ `node add-raw` |
362
+ | `CODE` | Inline JavaScript | ✅ `node add-raw` |
363
+
364
+ Most flows use only `PIECE_TRIGGER` + `PIECE`. For the other 3 types use `node add-raw` with a full Activepieces operation payload — see shapes below.
365
+
366
+ **Constraints when composing advanced nodes:**
367
+ 1. `LOOP_ON_ITEMS` and `CODE` must have a `parentStep` of type `trigger` or `PIECE`. Setting parent to a `ROUTER` (or another LOOP) returns 400 `Router step parent undefined not found`. To put a LOOP/CODE inside a router branch, build the inner action as part of the ROUTER's `children` array, not as a separate ADD_ACTION.
368
+ 2. `node list` only walks the linear `trigger → nextAction → nextAction` chain. Children of `ROUTER` (in `children: []`) and the body of `LOOP_ON_ITEMS` (in `firstLoopAction`) are stored server-side but not displayed by the flat list. Use `workflow get <flowId> --json` to see the full nested tree.
369
+
370
+ **Gotchas when updating live flows:**
371
+ - **Flow lock** — if the user has the flow open in their browser, CLI updates may be rejected with `"edited at the last minute, try again later"` or silently overwritten when the UI auto-saves. Ask the user to close the flow editor tab before bulk-updating via CLI; verify with `workflow get --json` that your changes stuck.
372
+ - **AI Connector `assistant-request` prompt field** — the `prompt` input is a NESTED object, not a plain string. The UI form binds to `input.prompt.prompt`. Plain string values like `input.prompt = "text"` are accepted by the API but the UI renders the field as empty. Always send `{ "prompt": { "prompt": "actual text" } }`. The separate `custom_instructions` field IS a plain string and maps to the UI's "Custom Instructions" section.
373
+
374
+ ### Raw operation shapes for advanced nodes
375
+
376
+ For `ROUTER`, `LOOP_ON_ITEMS`, `CODE` use `imbrace workflow node add-raw <flowId> --op-file <path>`. The op file contains `{ type, request }` — the full Activepieces flow-operation body. Examples:
377
+
378
+ **ROUTER** — multi-condition switch:
379
+ ```json
380
+ {
381
+ "type": "ADD_ACTION",
382
+ "request": {
383
+ "parentStep": "trigger",
384
+ "action": {
385
+ "name": "step_1",
386
+ "type": "ROUTER",
387
+ "displayName": "Check priority",
388
+ "settings": {
389
+ "branches": [
390
+ {
391
+ "branchName": "High",
392
+ "branchType": "CONDITION",
393
+ "conditions": [[{
394
+ "operator": "TEXT_EXACTLY_MATCHES",
395
+ "firstValue": "{{trigger.body.priority}}",
396
+ "secondValue": "high",
397
+ "caseSensitive": false
398
+ }]]
399
+ },
400
+ { "branchName": "Default", "branchType": "FALLBACK" }
401
+ ],
402
+ "executionType": "EXECUTE_FIRST_MATCH",
403
+ "sampleData": {}
404
+ },
405
+ "children": [null, null],
406
+ "valid": true
407
+ }
408
+ }
409
+ }
410
+ ```
411
+
412
+ **LOOP_ON_ITEMS** — loop over an array. `parentStep` must be a `trigger` or `PIECE` (not a ROUTER):
413
+ ```json
414
+ {
415
+ "type": "ADD_ACTION",
416
+ "request": {
417
+ "parentStep": "trigger",
418
+ "action": {
419
+ "name": "step_1",
420
+ "type": "LOOP_ON_ITEMS",
421
+ "displayName": "Loop users",
422
+ "settings": { "items": "{{trigger.body.users}}" },
423
+ "firstLoopAction": null,
424
+ "valid": true
425
+ }
426
+ }
427
+ }
428
+ ```
429
+
430
+ **CODE** — inline JavaScript:
431
+ ```json
432
+ {
433
+ "type": "ADD_ACTION",
434
+ "request": {
435
+ "parentStep": "step_1",
436
+ "action": {
437
+ "name": "step_2",
438
+ "type": "CODE",
439
+ "displayName": "Transform",
440
+ "settings": {
441
+ "input": { "x": "{{trigger.body.value}}" },
442
+ "sourceCode": {
443
+ "code": "export const code = async (inputs) => ({ doubled: inputs.x * 2 });",
444
+ "packageJson": "{\"dependencies\":{}}"
445
+ }
446
+ },
447
+ "valid": true
448
+ }
449
+ }
450
+ }
451
+ ```
452
+
453
+ **Common operation types** for `add-raw`:
454
+ - `ADD_ACTION` — add a new node (with `parentStep` + `action` shape above)
455
+ - `UPDATE_ACTION` — replace an existing node's settings (request: `{ name, type, displayName, settings, valid }`)
456
+ - `UPDATE_TRIGGER` — replace the trigger node
457
+ - `DELETE_ACTION` — remove a node (request: `{ names: ["step_X"] }`)
458
+
459
+ ### Connection types
460
+
461
+ When calling `workflow conn create --type <X>` (Sprint 3), valid types are:
462
+
463
+ | Type | Use case |
464
+ |---|---|
465
+ | `SECRET_TEXT` | Simple API key (Slack bot token, OpenAI key) |
466
+ | `OAUTH2` | OAuth flow with custom app (Google, Slack OAuth) |
467
+ | `CLOUD_OAUTH2` | OAuth via Activepieces hosted apps (no custom app setup needed) |
468
+ | `BASIC_AUTH` | username + password |
469
+ | `CUSTOM_AUTH` | Custom format defined by the piece |
470
+
471
+ Use `imbrace workflow piece detail <pieceName>` to see which auth type a piece accepts.
472
+
473
+ ### Workflow lifecycle
474
+
475
+ ```
476
+ DRAFT (editing) → publish → LOCKED (production) → enable → ENABLED (auto-running)
477
+
478
+ disable (back to DISABLED but still LOCKED)
479
+ ```
480
+
481
+ - `workflow publish` locks the current draft version and marks it as the production version.
482
+ - `workflow enable` turns on auto-trigger — fires the flow whenever its trigger condition is met.
483
+ - `workflow disable` stops auto-trigger but keeps the published version intact.
484
+ - Edit after publish: backend creates a new DRAFT version; previous LOCKED version keeps running until you publish the new draft.
485
+
486
+ ## Setup
487
+
488
+ ```bash
489
+ # 1. Start the API
490
+ cd api && bun install && bun run dev
491
+
492
+ # 2. Install the CLI (one-shot — handles build, link, and cross-shell PATH)
493
+ cd .. && ./install.sh
494
+
495
+ # 3. Login
496
+ imbrace login --api-key api_xxx...
497
+
498
+ # 4. Verify
499
+ imbrace whoami --json
500
+ ```
501
+
502
+ The `install.sh` script symlinks `imbrace` into `/opt/homebrew/bin` (Apple Silicon) or `/usr/local/bin` so the command works even from shells that don't load nvm — for example conda's `(base)` env.
503
+
504
+ ## Quick Start for Coding Agents
505
+
506
+ ### Data Board
507
+ ```bash
508
+ # Get available boards
509
+ imbrace data-board list --json
510
+
511
+ # Create a board
512
+ imbrace data-board create --name "Leads" --json
513
+
514
+ # Add a field
515
+ imbrace data-board create-field <boardId> --name "Company" --type ShortText --json
516
+
517
+ # Add a record (Name field is required — use its field ID)
518
+ imbrace data-board create-item <boardId> --fields '[{"board_field_id":"<nameFieldId>","value":"John Doe"},{"board_field_id":"<fieldId>","value":"Acme Corp"}]' --json
519
+
520
+ # List records
521
+ imbrace data-board list-items --board-id <boardId> --json
522
+
523
+ # Export to CSV
524
+ imbrace data-board export-csv --board-id <boardId> --out ./leads.csv
525
+ ```
526
+
527
+ ### AI Agent
528
+ ```bash
529
+ # Discover what's available
530
+ imbrace ai-agent list --json
531
+ imbrace ai-agent list-providers --json
532
+ imbrace ai-agent list-models --provider-id system --json
533
+ imbrace ai-agent list-folders --json
534
+
535
+ # Create an agent (minimal)
536
+ imbrace ai-agent create --name "Sales Bot" --instructions "You are a sales assistant" --json
537
+
538
+ # Create with custom provider + Knowledge Hub folder
539
+ imbrace ai-agent create --name "RAG Bot" \
540
+ --instructions "Answer using the provided knowledge" \
541
+ --provider-id e2629292-7e9f-4d55-ba18-6827747eab33 \
542
+ --model gpt-4o-mini \
543
+ --folder-ids 69bb82faa2cc764639bc6bdb \
544
+ --json
545
+
546
+ # Update — partial (other fields preserved)
547
+ imbrace ai-agent update <agentId> --instructions "Updated" --temperature 0.7 --json
548
+
549
+ # Delete
550
+ imbrace ai-agent delete <agentId> --yes --json
551
+ ```
552
+
553
+ ### Workflow — build a Slack auto-reply bot end-to-end
554
+
555
+ **Note:** Steps 1, 3, 4, 5, 6, 7 use Sprint 1+2 commands (already implemented).
556
+ Steps 2, 8, 9 use Sprint 3 commands (**not yet implemented** — for now, do them via the [UI builder](https://cloud.imbrace.co/workflow-v2)).
557
+
558
+ ```bash
559
+ # 1. Discover Slack + AI integrations (schemas) ✅ Sprint 2
560
+ imbrace workflow piece list --search slack --json
561
+ imbrace workflow piece detail @activepieces/piece-slack --json
562
+ imbrace workflow piece detail @activepieces/piece-ai-connector --json
563
+
564
+ # 2. Save Slack token (one-time per workspace) ✅ Sprint 3
565
+ imbrace workflow conn create \
566
+ --piece @activepieces/piece-slack \
567
+ --type SECRET_TEXT \
568
+ --value "xoxb-actual-token" \
569
+ --json
570
+ # → note conn._id
571
+
572
+ # 3. Create empty flow ✅ Sprint 1
573
+ imbrace workflow create --name "Slack AI Reply Bot" --json
574
+ # → note flow._id
575
+
576
+ # 4. Add Slack trigger (catch new messages) ✅ Sprint 2
577
+ imbrace workflow node add <flowId> \
578
+ --type trigger \
579
+ --piece @activepieces/piece-slack \
580
+ --trigger-name new_message_in_channel \
581
+ --connection <connId> \
582
+ --input '{"channel":"C0XXXXX"}' \
583
+ --json
584
+
585
+ # 5. Add AI action (draft a reply) ✅ Sprint 2
586
+ imbrace workflow node add <flowId> \
587
+ --type action \
588
+ --piece @activepieces/piece-ai-connector \
589
+ --action-name ask \
590
+ --after trigger \
591
+ --input '{"modelName":"gpt-4o","prompt":"Draft a friendly reply to: {{trigger.text}}"}' \
592
+ --json
593
+
594
+ # 6. Add Slack reply (post answer back to thread) ✅ Sprint 2
595
+ imbrace workflow node add <flowId> \
596
+ --type action \
597
+ --piece @activepieces/piece-slack \
598
+ --action-name send_channel_message \
599
+ --after step_1 \
600
+ --connection <connId> \
601
+ --input '{"channel":"{{trigger.channel}}","text":"{{step_1.output.text}}","thread_ts":"{{trigger.ts}}"}' \
602
+ --json
603
+
604
+ # 7. Verify the node tree ✅ Sprint 2
605
+ imbrace workflow node list <flowId> --json
606
+
607
+ # 8. Test run with sample payload ✅ Sprint 3
608
+ # --sync may time out (~30s) even if the run finishes faster.
609
+ # If it times out, use 'workflow runs' + 'run-detail' to fetch the result.
610
+ imbrace workflow run <flowId> --sync \
611
+ --payload '{"text":"How do I reset my password?","channel":"C0XXXXX","ts":"1234.5"}' \
612
+ --json
613
+
614
+ # 9. Publish & enable so it runs automatically ✅ Sprint 3
615
+ imbrace workflow publish <flowId> --json
616
+ imbrace workflow enable <flowId> --json
617
+ ```
618
+
619
+ ## Adding a New Service
620
+
621
+ To add a new service (e.g. `workflow`):
622
+
623
+ 1. Create route in `api/src/routes/workflow.ts`
624
+ 2. Mount in `api/src/index.ts` with `authMiddleware`
625
+ 3. Create CLI commands in `cli/src/commands/workflow/`
626
+ 4. Add topic in `cli/package.json` under `oclif.topics`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imbrace/cli",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "description": "CLI tool for interacting with the Imbrace CRM platform from the terminal",
6
6
  "repository": {
@@ -24,7 +24,7 @@
24
24
  "prepack": "oclif manifest"
25
25
  },
26
26
  "dependencies": {
27
- "@imbrace/sdk": "1.0.2",
27
+ "@imbrace/sdk": "^1.0.3",
28
28
  "@inquirer/prompts": "^7.10.1",
29
29
  "@oclif/core": "^4.2.0",
30
30
  "@oclif/plugin-autocomplete": "^3.2.0",
@@ -75,6 +75,7 @@
75
75
  },
76
76
  "files": [
77
77
  "/bin",
78
- "/dist"
78
+ "/dist",
79
+ "/llms.txt"
79
80
  ]
80
81
  }
package/dist/http.d.ts DELETED
@@ -1,9 +0,0 @@
1
- /**
2
- * HTTP client for the local Hono API server
3
- * Automatically attaches the Bearer token from config
4
- */
5
- export declare function apiRequest<T = any>(path: string, opts?: {
6
- method?: string;
7
- body?: any;
8
- }): Promise<T>;
9
- export declare function apiRequestText(path: string): Promise<string>;