@imbrace/cli 0.1.0 → 0.3.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.
- package/README.md +443 -0
- package/dist/commands/ai-agent/create.d.ts +5 -0
- package/dist/commands/ai-agent/create.js +11 -0
- package/dist/commands/ai-agent/list-files.d.ts +10 -0
- package/dist/commands/ai-agent/list-files.js +40 -0
- package/dist/commands/ai-agent/list-folders.d.ts +10 -0
- package/dist/commands/ai-agent/list-folders.js +39 -0
- package/dist/commands/ai-agent/list-providers.js +1 -1
- package/dist/commands/ai-agent/update.d.ts +5 -0
- package/dist/commands/ai-agent/update.js +16 -0
- package/dist/commands/docs.d.ts +10 -0
- package/dist/commands/docs.js +39 -0
- package/dist/commands/workflow/conn/create.d.ts +15 -0
- package/dist/commands/workflow/conn/create.js +69 -0
- package/dist/commands/workflow/conn/delete.d.ts +13 -0
- package/dist/commands/workflow/conn/delete.js +39 -0
- package/dist/commands/workflow/conn/get.d.ts +12 -0
- package/dist/commands/workflow/conn/get.js +42 -0
- package/dist/commands/workflow/conn/list.d.ts +9 -0
- package/dist/commands/workflow/conn/list.js +37 -0
- package/dist/commands/workflow/create.d.ts +1 -0
- package/dist/commands/workflow/create.js +4 -0
- package/dist/commands/workflow/disable.d.ts +12 -0
- package/dist/commands/workflow/disable.js +30 -0
- package/dist/commands/workflow/enable.d.ts +12 -0
- package/dist/commands/workflow/enable.js +34 -0
- package/dist/commands/workflow/folder/create.d.ts +12 -0
- package/dist/commands/workflow/folder/create.js +43 -0
- package/dist/commands/workflow/folder/delete.d.ts +13 -0
- package/dist/commands/workflow/folder/delete.js +39 -0
- package/dist/commands/workflow/folder/get.d.ts +12 -0
- package/dist/commands/workflow/folder/get.js +38 -0
- package/dist/commands/workflow/folder/list.d.ts +9 -0
- package/dist/commands/workflow/folder/list.js +35 -0
- package/dist/commands/workflow/folder/update.d.ts +13 -0
- package/dist/commands/workflow/folder/update.js +30 -0
- package/dist/commands/workflow/list.d.ts +1 -0
- package/dist/commands/workflow/list.js +7 -1
- package/dist/commands/workflow/mcp/create.d.ts +12 -0
- package/dist/commands/workflow/mcp/create.js +44 -0
- package/dist/commands/workflow/mcp/delete.d.ts +13 -0
- package/dist/commands/workflow/mcp/delete.js +39 -0
- package/dist/commands/workflow/mcp/get.d.ts +12 -0
- package/dist/commands/workflow/mcp/get.js +40 -0
- package/dist/commands/workflow/mcp/list.d.ts +9 -0
- package/dist/commands/workflow/mcp/list.js +36 -0
- package/dist/commands/workflow/mcp/rotate-token.d.ts +13 -0
- package/dist/commands/workflow/mcp/rotate-token.js +46 -0
- package/dist/commands/workflow/move.d.ts +13 -0
- package/dist/commands/workflow/move.js +35 -0
- package/dist/commands/workflow/node/add-raw.d.ts +15 -0
- package/dist/commands/workflow/node/add-raw.js +70 -0
- package/dist/commands/workflow/publish.d.ts +12 -0
- package/dist/commands/workflow/publish.js +30 -0
- package/dist/commands/workflow/run.d.ts +14 -0
- package/dist/commands/workflow/run.js +50 -0
- package/llms.txt +625 -0
- package/package.json +12 -2
package/README.md
ADDED
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
# Imbrace CLI
|
|
2
|
+
|
|
3
|
+
> CLI tool for interacting with the Imbrace CRM platform from the terminal. Designed for both developers and coding agents (Claude, Cursor, Copilot, etc.).
|
|
4
|
+
|
|
5
|
+
## Quick Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# 1. Start the API server (in one terminal, keep running)
|
|
9
|
+
cd api
|
|
10
|
+
bun install
|
|
11
|
+
bun run dev # runs on http://localhost:3456
|
|
12
|
+
|
|
13
|
+
# 2. Install the CLI (in another terminal — one-shot)
|
|
14
|
+
./install.sh
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`install.sh` runs `npm install`, `npm run build`, `npm link`, and then symlinks `imbrace` into `/opt/homebrew/bin` (Apple Silicon) or `/usr/local/bin` so the command is available even from shells that don't load nvm — for example conda's `(base)` env.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Authentication
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
# API Key (recommended for coding agents and CI/CD)
|
|
25
|
+
imbrace login --api-key api_xxx...
|
|
26
|
+
|
|
27
|
+
# Email + Password
|
|
28
|
+
imbrace login --email user@example.com --password mypass
|
|
29
|
+
|
|
30
|
+
# Check current login
|
|
31
|
+
imbrace whoami --json
|
|
32
|
+
|
|
33
|
+
# Logout
|
|
34
|
+
imbrace logout
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Credentials are stored via the `conf` package — exact path depends on OS:
|
|
38
|
+
|
|
39
|
+
| OS | Path |
|
|
40
|
+
|---|---|
|
|
41
|
+
| macOS | `~/Library/Preferences/imbrace-nodejs/config.json` |
|
|
42
|
+
| Linux | `~/.config/imbrace-nodejs/config.json` |
|
|
43
|
+
| Windows | `%APPDATA%\imbrace-nodejs\Config\config.json` |
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Commands
|
|
48
|
+
|
|
49
|
+
### Data Board
|
|
50
|
+
|
|
51
|
+
A board is a CRM pipeline — leads, deals, tasks, or any structured data.
|
|
52
|
+
|
|
53
|
+
**Step 1 — List boards** (get Board IDs)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
imbrace data-board list --json
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Step 2 — Create a board**
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
imbrace data-board create --name "Sales Pipeline" --json
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The `create` command is interactive (without `--json`) — after entering the board name you can attach freestyle key-value pairs (e.g. `description`, `email`, or any custom property). With `--json`, only `--name` is required.
|
|
66
|
+
|
|
67
|
+
**Step 3 — Add schema fields to a board**
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
# Valid field types (16):
|
|
71
|
+
# ShortText, LongText, Number, Date, Email, Phone, Currency,
|
|
72
|
+
# SingleSelection, MultipleSelection, Checkbox,
|
|
73
|
+
# Assignee, MultipleAssignee, Link, Notes, Origin, Priority
|
|
74
|
+
# DO NOT use `Dropdown` — backend rejects it (use `SingleSelection` instead).
|
|
75
|
+
|
|
76
|
+
imbrace data-board create-field <boardId> --name "Company" --type ShortText --json
|
|
77
|
+
imbrace data-board create-field <boardId> --name "Revenue" --type Number --json
|
|
78
|
+
imbrace data-board create-field <boardId> --name "Status" --type SingleSelection --json
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
**Step 4 — Create items (records)**
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
imbrace data-board create-item <boardId> --fields '[
|
|
85
|
+
{"board_field_id": "<fieldId1>", "value": "Acme Corp"},
|
|
86
|
+
{"board_field_id": "<fieldId2>", "value": "50000"},
|
|
87
|
+
{"board_field_id": "<fieldId3>", "value": "Active"}
|
|
88
|
+
]' --json
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Step 5 — List / search items**
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
# List all items (paginated)
|
|
95
|
+
imbrace data-board list-items --board-id <boardId> --limit 20 --skip 0 --json
|
|
96
|
+
|
|
97
|
+
# Full-text search
|
|
98
|
+
imbrace data-board list-items --board-id <boardId> --q "Acme" --json
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
**Update an item**
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
imbrace data-board update-item <boardId> <itemId> --data '[
|
|
105
|
+
{"key": "<fieldId>", "value": "Acme Corp — Closed Won"}
|
|
106
|
+
]' --json
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
**Delete an item**
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
imbrace data-board delete-item <boardId> <itemId> --yes --json
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
**Export to CSV**
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
imbrace data-board export-csv --board-id <boardId> --out ./board.csv
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
### AI Agent
|
|
124
|
+
|
|
125
|
+
An AI agent is a configured assistant (LLM + prompt + behavior) that appears as a card on `cloud.imbrace.co/ai-agent`. Creating one atomically provisions the assistant, a web channel for the chat widget, and the use-case template.
|
|
126
|
+
|
|
127
|
+
> **All content (name, description, instructions, behavior fields) must be in English.** The slug for `workflow_name` is derived from the name; Vietnamese diacritics get stripped and produce unreadable slugs.
|
|
128
|
+
|
|
129
|
+
**CRUD**
|
|
130
|
+
|
|
131
|
+
```bash
|
|
132
|
+
imbrace ai-agent list --json
|
|
133
|
+
imbrace ai-agent get <agentId> --json
|
|
134
|
+
imbrace ai-agent create --name "Sales Bot" --json
|
|
135
|
+
imbrace ai-agent update <agentId> --name "New Name" --json
|
|
136
|
+
imbrace ai-agent delete <agentId> --yes --json
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Discovery (LLM providers + Knowledge Hub)**
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# LLM providers + models
|
|
143
|
+
imbrace ai-agent list-providers --json # 3 providers
|
|
144
|
+
imbrace ai-agent list-models --provider-id system --json # models per provider
|
|
145
|
+
|
|
146
|
+
# Knowledge Hub folders + files
|
|
147
|
+
imbrace ai-agent list-folders [--search support] --json
|
|
148
|
+
imbrace ai-agent list-files --folder-id <folderId> --json
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
**Full create — all settings populated**
|
|
152
|
+
|
|
153
|
+
```bash
|
|
154
|
+
imbrace ai-agent create \
|
|
155
|
+
--name "Customer Support Specialist" \
|
|
156
|
+
--description "Senior AI customer support agent for an e-commerce company" \
|
|
157
|
+
--instructions "You are a senior customer support specialist..." \
|
|
158
|
+
--personality "Friendly and professional senior customer support agent" \
|
|
159
|
+
--core-task "Answer product inquiries, help track orders" \
|
|
160
|
+
--tone "Polite, professional, warm" \
|
|
161
|
+
--response-length "medium" \
|
|
162
|
+
--banned-words "stupid, idiot" \
|
|
163
|
+
--category "Support" \
|
|
164
|
+
--provider-id "e2629292-7e9f-4d55-ba18-6827747eab33" \
|
|
165
|
+
--model "gpt-4o-mini" \
|
|
166
|
+
--temperature 0.3 \
|
|
167
|
+
--folder-ids "69bb82faa2cc764639bc6bdb" \
|
|
168
|
+
--board-ids "brd_e5450d76-84d4-4c34-8b13-3d0f1873b53b" \
|
|
169
|
+
--json
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
**Available flags** (`create` + `update` accept the same set; `update` preserves unchanged fields via PUT-merge)
|
|
173
|
+
|
|
174
|
+
| Flag | Maps to | Notes |
|
|
175
|
+
|---|---|---|
|
|
176
|
+
| **Identity** | | |
|
|
177
|
+
| `--name` / `-n` | `name` + `title` | Required for create |
|
|
178
|
+
| `--description` / `-d` | `description` + `short_description` | Shown under title in UI |
|
|
179
|
+
| `--instructions` / `-i` | `instructions` | System prompt |
|
|
180
|
+
| **Model** | | |
|
|
181
|
+
| `--model` | `model_id` | Default `Default` (system provider). Discover via `list-models`. |
|
|
182
|
+
| `--provider-id` | `provider_id` | UUID, default `system`. **Use UUID — not the MongoDB `_id`.** |
|
|
183
|
+
| `--mode` | `mode` | `standard` / `advanced` |
|
|
184
|
+
| `--temperature` | `temperature` | 0.0–2.0, default 0.1 |
|
|
185
|
+
| **Behavior Settings** | | |
|
|
186
|
+
| `--personality` | `personality_role` | |
|
|
187
|
+
| `--core-task` | `core_task` | |
|
|
188
|
+
| `--tone` | `tone_and_style` | |
|
|
189
|
+
| `--response-length` | `response_length` | `short` / `medium` / `long` |
|
|
190
|
+
| `--banned-words` | `banned_words` | Comma-separated, word-level filter on output |
|
|
191
|
+
| `--category` | `category` | `Support` / `Sales` / `Marketing` / `Team` / `Other` |
|
|
192
|
+
| `--guardrail-id` | `guardrail_id` | Attach a guardrail |
|
|
193
|
+
| `--preload-information` | `preload_information` | Static info auto-injected into context |
|
|
194
|
+
| **Knowledge Support** | | |
|
|
195
|
+
| `--folder-ids` | `folder_ids` | Comma-separated KH folder IDs |
|
|
196
|
+
| `--default-folder-id` | `default_folder_id` | |
|
|
197
|
+
| `--knowledge-hubs` | `knowledge_hubs` | Comma-separated KH IDs |
|
|
198
|
+
| `--board-ids` | `board_ids` | Comma-separated data board IDs (Document Models) |
|
|
199
|
+
| `--file-ids` | `file_ids` | Comma-separated file IDs |
|
|
200
|
+
| **Runtime toggles** (boolean, support `--no-X`) | | |
|
|
201
|
+
| `--show-thinking` | `show_thinking_process` | Default false |
|
|
202
|
+
| `--streaming` | `streaming` | Default true |
|
|
203
|
+
| `--use-memory` | `use_memory` | Default true |
|
|
204
|
+
| **Output** | | |
|
|
205
|
+
| `--yes` / `-y` | — | Skip confirm on delete |
|
|
206
|
+
| `--json` | — | Machine-readable output |
|
|
207
|
+
| `--id-only` | — | Print only the new agent ID (pipe-friendly) |
|
|
208
|
+
| `-h` / `--help` | — | Show usage on any command |
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
### Workflow
|
|
213
|
+
|
|
214
|
+
A workflow (Activepieces) is a chain of nodes: a trigger fires, then actions run in sequence. Use it for automation — e.g. "Slack message arrives → ask AI → reply to thread".
|
|
215
|
+
|
|
216
|
+
**Anatomy:** A workflow has 6 layers — `Flow` (container) → `Version` (snapshot) → `Nodes` (trigger + actions) → `Connections` (credentials) → `Runs` (history) → `Pieces` (catalog of 126 integrations).
|
|
217
|
+
|
|
218
|
+
**Node types:**
|
|
219
|
+
|
|
220
|
+
| Type | Role | CLI support |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| `PIECE_TRIGGER` | "When does the flow run" — Slack message, webhook, cron, ... | ✅ `node add --type trigger` |
|
|
223
|
+
| `PIECE` | "What runs after" — send Slack, ask AI, HTTP call, ... | ✅ `node add --type action` |
|
|
224
|
+
| `EMPTY` | Placeholder before trigger is set | ✅ Read-only |
|
|
225
|
+
| `ROUTER` | Multi-condition switch (replaces legacy BRANCH) | ✅ `node add-raw` |
|
|
226
|
+
| `LOOP_ON_ITEMS` | Loop over an array | ✅ `node add-raw` |
|
|
227
|
+
| `CODE` | Inline JavaScript | ✅ `node add-raw` |
|
|
228
|
+
|
|
229
|
+
**Flow CRUD + run history**
|
|
230
|
+
```bash
|
|
231
|
+
imbrace workflow list [--folder-id <id|NULL>] # filter by category folder
|
|
232
|
+
imbrace workflow get <id>
|
|
233
|
+
imbrace workflow create --name "X" [--folder-id <id>]
|
|
234
|
+
imbrace workflow move <flowId> --folder-id <id|NULL> # NULL = unfile
|
|
235
|
+
imbrace workflow delete <id> --yes
|
|
236
|
+
imbrace workflow runs # recent runs
|
|
237
|
+
imbrace workflow run-detail <runId>
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
**Build nodes**
|
|
241
|
+
```bash
|
|
242
|
+
# Discover integrations
|
|
243
|
+
imbrace workflow piece list [--search slack]
|
|
244
|
+
imbrace workflow piece detail <pieceName> [--only actions|triggers]
|
|
245
|
+
|
|
246
|
+
# Manage nodes
|
|
247
|
+
imbrace workflow node list <flowId>
|
|
248
|
+
imbrace workflow node add <flowId> --type trigger --piece <name> --trigger-name <id> --input '{...}'
|
|
249
|
+
imbrace workflow node add <flowId> --type action --piece <name> --action-name <id> --after <parent> --input '{...}'
|
|
250
|
+
imbrace workflow node update <flowId> <nodeName> --input '{...}'
|
|
251
|
+
imbrace workflow node delete <flowId> <nodeName> --yes
|
|
252
|
+
imbrace workflow node add-raw <flowId> --op-file <path> # advanced types: ROUTER, LOOP_ON_ITEMS, CODE
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
**Connections (OAuth/API keys for external services)**
|
|
256
|
+
```bash
|
|
257
|
+
imbrace workflow conn list
|
|
258
|
+
imbrace workflow conn get <connId>
|
|
259
|
+
imbrace workflow conn create --piece slack --type SECRET_TEXT --value "xoxb-..." [--display-name <X>]
|
|
260
|
+
imbrace workflow conn delete <connId> --yes
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Lifecycle**
|
|
264
|
+
```bash
|
|
265
|
+
imbrace workflow publish <flowId> # lock current draft as production
|
|
266
|
+
imbrace workflow enable <flowId> # auto-trigger on (requires publish first)
|
|
267
|
+
imbrace workflow disable <flowId> # stop auto-trigger
|
|
268
|
+
imbrace workflow run <flowId> --payload '{...}' [--sync]
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
**Folders (organize flows — UI calls them "Categories")**
|
|
272
|
+
```bash
|
|
273
|
+
imbrace workflow folder list / get <id> / create --name / update <id> --name / delete <id> --yes
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
The platform auto-creates 4 system folders that show up as Categories in the UI:
|
|
277
|
+
|
|
278
|
+
| UI Category | Purpose | Folder name in API |
|
|
279
|
+
|---|---|---|
|
|
280
|
+
| Channel Workflow | Messaging / channel automation | `Channel Workflow` |
|
|
281
|
+
| Board Automation | Triggered by data-board events | `Board Automation` |
|
|
282
|
+
| AI Agent Skills | Skills callable by AI agents | `AI Agent Capabilities` |
|
|
283
|
+
| Others | Everything else | `Others` |
|
|
284
|
+
|
|
285
|
+
Use `workflow folder list` to discover their IDs, then `workflow create --folder-id <id>` or `workflow move <flowId> --folder-id <id>` to place a flow in a category. Pass `--folder-id NULL` to unfile.
|
|
286
|
+
|
|
287
|
+
**MCP servers (Model Context Protocol — let AI agents call Activepieces tools)**
|
|
288
|
+
```bash
|
|
289
|
+
imbrace workflow mcp list / get <id> / create --name / delete <id> --yes
|
|
290
|
+
imbrace workflow mcp rotate-token <mcpId> --yes # token shown once at create + rotate
|
|
291
|
+
```
|
|
292
|
+
|
|
293
|
+
**Variable syntax inside node `input`**
|
|
294
|
+
|
|
295
|
+
- `{{trigger.body.X}}` — field `X` from webhook payload
|
|
296
|
+
- `{{trigger.X}}` — top-level trigger field (for piece triggers)
|
|
297
|
+
- `{{step_1.output.Y}}` — output field `Y` from step_1
|
|
298
|
+
- `{{connections.<id>.access_token}}` — connection field
|
|
299
|
+
|
|
300
|
+
**Known issue:** `workflow run --sync` may time out at ~30s even when the flow finishes faster. Workaround: use `workflow runs` + `run-detail <runId>` to fetch the result.
|
|
301
|
+
|
|
302
|
+
---
|
|
303
|
+
|
|
304
|
+
## For Coding Agents
|
|
305
|
+
|
|
306
|
+
Set up a CRM pipeline with sample data:
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# 1. Verify login
|
|
310
|
+
imbrace whoami --json
|
|
311
|
+
|
|
312
|
+
# 2. Create a board (--json skips interactive field prompts)
|
|
313
|
+
imbrace data-board create --name "Leads" --json
|
|
314
|
+
# → note the board _id from response
|
|
315
|
+
|
|
316
|
+
# 3. Add schema fields
|
|
317
|
+
imbrace data-board create-field <boardId> --name "Company" --type ShortText --json
|
|
318
|
+
imbrace data-board create-field <boardId> --name "Contact" --type ShortText --json
|
|
319
|
+
imbrace data-board create-field <boardId> --name "Deal Value" --type Number --json
|
|
320
|
+
imbrace data-board create-field <boardId> --name "Stage" --type SingleSelection --json
|
|
321
|
+
# → note each field _id from response
|
|
322
|
+
|
|
323
|
+
# 4. Add records
|
|
324
|
+
imbrace data-board create-item <boardId> --fields '[
|
|
325
|
+
{"board_field_id": "<companyFieldId>", "value": "Acme Corp"},
|
|
326
|
+
{"board_field_id": "<contactFieldId>", "value": "John Doe"},
|
|
327
|
+
{"board_field_id": "<dealValueFieldId>", "value": "75000"},
|
|
328
|
+
{"board_field_id": "<stageFieldId>", "value": "Negotiation"}
|
|
329
|
+
]' --json
|
|
330
|
+
|
|
331
|
+
# 5. Verify
|
|
332
|
+
imbrace data-board list-items --board-id <boardId> --json
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
> Always use `--json` flag so output can be parsed programmatically.
|
|
336
|
+
> If a command returns 401, run `imbrace login --api-key api_xxx...` again.
|
|
337
|
+
|
|
338
|
+
For complete CLI reference for coding agents, see [`llms.txt`](./llms.txt).
|
|
339
|
+
|
|
340
|
+
**Tip — one-shot setup for an AI agent:**
|
|
341
|
+
```bash
|
|
342
|
+
imbrace docs > /tmp/imbrace-llms.txt # ~30 KB reference, bundled with the package
|
|
343
|
+
# then feed /tmp/imbrace-llms.txt into your agent's context (Claude Code, Cursor, ...)
|
|
344
|
+
```
|
|
345
|
+
The `imbrace docs` command prints the full `llms.txt` shipped inside the npm package — no network or repo clone needed.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
349
|
+
## Project Structure
|
|
350
|
+
|
|
351
|
+
```
|
|
352
|
+
imbrace-cli/
|
|
353
|
+
├── README.md ← This file
|
|
354
|
+
├── llms.txt ← Reference for coding agents (Claude/Cursor/...)
|
|
355
|
+
├── install.sh ← One-shot installer (npm link + cross-shell PATH)
|
|
356
|
+
├── report/ ← Reports (BUG_REPORT, SDK_REPORT, PROMPT_GUIDE)
|
|
357
|
+
│
|
|
358
|
+
├── api/ ← Hono REST API (proxy to Imbrace platform)
|
|
359
|
+
│ └── src/
|
|
360
|
+
│ ├── index.ts ← Entry point, port 3456
|
|
361
|
+
│ ├── middleware/auth.ts ← Auth via @imbrace/sdk
|
|
362
|
+
│ └── routes/
|
|
363
|
+
│ ├── auth.ts ← POST /auth/login
|
|
364
|
+
│ ├── data-board.ts ← CRUD /data-board/*
|
|
365
|
+
│ ├── ai-agent.ts ← CRUD /ai-agent/* (uses client.agent.createUseCase)
|
|
366
|
+
│ └── workflow.ts ← CRUD /workflow/*, /workflow/piece/*, /workflow/:id/nodes/*
|
|
367
|
+
│
|
|
368
|
+
└── cli/ ← oclif CLI
|
|
369
|
+
└── src/
|
|
370
|
+
├── base-command.ts ← Auto-prompts login if not authenticated
|
|
371
|
+
├── config.ts ← Credential store (via `conf` package)
|
|
372
|
+
├── http.ts ← HTTP client → API server
|
|
373
|
+
└── commands/
|
|
374
|
+
├── login.ts
|
|
375
|
+
├── logout.ts
|
|
376
|
+
├── whoami.ts
|
|
377
|
+
├── data-board/
|
|
378
|
+
│ ├── list.ts
|
|
379
|
+
│ ├── create.ts
|
|
380
|
+
│ ├── create-field.ts
|
|
381
|
+
│ ├── create-item.ts
|
|
382
|
+
│ ├── list-items.ts
|
|
383
|
+
│ ├── update-item.ts
|
|
384
|
+
│ ├── delete-item.ts
|
|
385
|
+
│ └── export-csv.ts
|
|
386
|
+
├── ai-agent/
|
|
387
|
+
│ ├── list.ts
|
|
388
|
+
│ ├── get.ts
|
|
389
|
+
│ ├── create.ts
|
|
390
|
+
│ ├── update.ts
|
|
391
|
+
│ ├── delete.ts
|
|
392
|
+
│ ├── list-providers.ts ← LLM providers discovery
|
|
393
|
+
│ ├── list-models.ts ← Models per provider
|
|
394
|
+
│ ├── list-folders.ts ← Knowledge Hub folders
|
|
395
|
+
│ └── list-files.ts ← Files in a KH folder
|
|
396
|
+
└── workflow/
|
|
397
|
+
├── list.ts
|
|
398
|
+
├── get.ts
|
|
399
|
+
├── create.ts
|
|
400
|
+
├── delete.ts
|
|
401
|
+
├── runs.ts
|
|
402
|
+
├── run-detail.ts
|
|
403
|
+
├── publish.ts ← Lifecycle
|
|
404
|
+
├── enable.ts
|
|
405
|
+
├── disable.ts
|
|
406
|
+
├── run.ts ← Trigger flow [--sync]
|
|
407
|
+
├── piece/
|
|
408
|
+
│ ├── list.ts
|
|
409
|
+
│ └── detail.ts
|
|
410
|
+
├── node/
|
|
411
|
+
│ ├── add.ts
|
|
412
|
+
│ ├── update.ts
|
|
413
|
+
│ ├── delete.ts
|
|
414
|
+
│ ├── list.ts
|
|
415
|
+
│ └── add-raw.ts ← ROUTER / LOOP_ON_ITEMS / CODE
|
|
416
|
+
├── conn/ ← Connections (OAuth/API keys)
|
|
417
|
+
│ ├── list.ts
|
|
418
|
+
│ ├── get.ts
|
|
419
|
+
│ ├── create.ts
|
|
420
|
+
│ └── delete.ts
|
|
421
|
+
├── folder/ ← Organize flows
|
|
422
|
+
│ ├── list.ts
|
|
423
|
+
│ ├── get.ts
|
|
424
|
+
│ ├── create.ts
|
|
425
|
+
│ ├── update.ts
|
|
426
|
+
│ └── delete.ts
|
|
427
|
+
└── mcp/ ← Model Context Protocol servers
|
|
428
|
+
├── list.ts
|
|
429
|
+
├── get.ts
|
|
430
|
+
├── create.ts
|
|
431
|
+
├── delete.ts
|
|
432
|
+
└── rotate-token.ts
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
---
|
|
436
|
+
|
|
437
|
+
## Adding a New Service
|
|
438
|
+
|
|
439
|
+
1. Create `api/src/routes/<service>.ts`
|
|
440
|
+
2. Mount in `api/src/index.ts` with `authMiddleware`
|
|
441
|
+
3. Create `cli/src/commands/<service>/*.ts`
|
|
442
|
+
4. Add topic in `cli/package.json` under `oclif.topics`
|
|
443
|
+
5. Rebuild CLI: `cd cli && npm run build` (or re-run `./install.sh`)
|
|
@@ -18,6 +18,11 @@ export default class AiAgentCreate extends BaseCommand {
|
|
|
18
18
|
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
19
19
|
"guardrail-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
20
20
|
"preload-information": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
|
+
"folder-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
|
+
"default-folder-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
|
+
"knowledge-hubs": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
"board-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
|
+
"file-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
21
26
|
"show-thinking": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
22
27
|
streaming: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
23
28
|
"use-memory": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -31,6 +31,12 @@ export default class AiAgentCreate extends BaseCommand {
|
|
|
31
31
|
}),
|
|
32
32
|
"guardrail-id": Flags.string({ description: "Attach a guardrail by ID" }),
|
|
33
33
|
"preload-information": Flags.string({ description: "Static info auto-injected into context every chat" }),
|
|
34
|
+
// Knowledge Support (UI tab) — comma-separated IDs
|
|
35
|
+
"folder-ids": Flags.string({ description: "Comma-separated Knowledge Hub folder IDs (RAG sources)" }),
|
|
36
|
+
"default-folder-id": Flags.string({ description: "Default folder ID for new files" }),
|
|
37
|
+
"knowledge-hubs": Flags.string({ description: "Comma-separated Knowledge Hub IDs" }),
|
|
38
|
+
"board-ids": Flags.string({ description: "Comma-separated Document Model (data board) IDs" }),
|
|
39
|
+
"file-ids": Flags.string({ description: "Comma-separated file IDs already uploaded to Knowledge Hub" }),
|
|
34
40
|
// Behavior runtime toggles
|
|
35
41
|
"show-thinking": Flags.boolean({ description: "Show model's thinking process (default: false)", allowNo: true }),
|
|
36
42
|
streaming: Flags.boolean({ description: "Stream response token-by-token (default: true)", allowNo: true }),
|
|
@@ -60,6 +66,11 @@ export default class AiAgentCreate extends BaseCommand {
|
|
|
60
66
|
...(flags.category && { category: [flags.category] }),
|
|
61
67
|
...(flags["guardrail-id"] && { guardrail_id: flags["guardrail-id"] }),
|
|
62
68
|
...(flags["preload-information"] && { preload_information: flags["preload-information"] }),
|
|
69
|
+
...(flags["folder-ids"] && { folder_ids: flags["folder-ids"].split(",").map(s => s.trim()).filter(Boolean) }),
|
|
70
|
+
...(flags["default-folder-id"] && { default_folder_id: flags["default-folder-id"] }),
|
|
71
|
+
...(flags["knowledge-hubs"] && { knowledge_hubs: flags["knowledge-hubs"].split(",").map(s => s.trim()).filter(Boolean) }),
|
|
72
|
+
...(flags["board-ids"] && { board_ids: flags["board-ids"].split(",").map(s => s.trim()).filter(Boolean) }),
|
|
73
|
+
...(flags["file-ids"] && { file_ids: flags["file-ids"].split(",").map(s => s.trim()).filter(Boolean) }),
|
|
63
74
|
...(flags["show-thinking"] !== undefined && { show_thinking_process: flags["show-thinking"] }),
|
|
64
75
|
...(flags.streaming !== undefined && { streaming: flags.streaming }),
|
|
65
76
|
...(flags["use-memory"] !== undefined && { use_memory: flags["use-memory"] }),
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class AiAgentListFiles extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
"folder-id": import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { apiRequest } from "../../http.js";
|
|
4
|
+
export default class AiAgentListFiles extends BaseCommand {
|
|
5
|
+
static description = "List files inside a Knowledge Hub folder (use IDs with --file-ids on create/update)";
|
|
6
|
+
static examples = [
|
|
7
|
+
"imbrace ai-agent list-files --folder-id <folderId>",
|
|
8
|
+
"imbrace ai-agent list-files --folder-id <folderId> --json",
|
|
9
|
+
];
|
|
10
|
+
static flags = {
|
|
11
|
+
"folder-id": Flags.string({
|
|
12
|
+
description: "Knowledge Hub folder ID. Use 'imbrace ai-agent list-folders' to discover.",
|
|
13
|
+
required: true,
|
|
14
|
+
}),
|
|
15
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
16
|
+
};
|
|
17
|
+
async run() {
|
|
18
|
+
const { flags } = await this.parse(AiAgentListFiles);
|
|
19
|
+
try {
|
|
20
|
+
const res = await apiRequest(`/ai-agent/folders/${encodeURIComponent(flags["folder-id"])}/files`);
|
|
21
|
+
if (flags.json) {
|
|
22
|
+
this.log(JSON.stringify(res, null, 2));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.log(`\n Found ${res.count} file(s) in folder "${flags["folder-id"]}":\n`);
|
|
26
|
+
this.log(" ID NAME STATUS");
|
|
27
|
+
this.log(" ─────────────────────────────────────────────────────────────────────────────────────");
|
|
28
|
+
for (const f of res.data || []) {
|
|
29
|
+
const id = (f._id || f.id || "").padEnd(40);
|
|
30
|
+
const name = (f.original_name || f.name || "").padEnd(36);
|
|
31
|
+
const status = f.embedding_status || f.status || "";
|
|
32
|
+
this.log(` ${id} ${name} ${status}`);
|
|
33
|
+
}
|
|
34
|
+
this.log("");
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
this.error(`Failed: ${error.message}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { BaseCommand } from "../../base-command.js";
|
|
2
|
+
export default class AiAgentListFolders extends BaseCommand {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
search: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
7
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Flags } from "@oclif/core";
|
|
2
|
+
import { BaseCommand } from "../../base-command.js";
|
|
3
|
+
import { apiRequest } from "../../http.js";
|
|
4
|
+
export default class AiAgentListFolders extends BaseCommand {
|
|
5
|
+
static description = "List Knowledge Hub folders (use IDs with --folder-ids on create/update)";
|
|
6
|
+
static examples = [
|
|
7
|
+
"imbrace ai-agent list-folders",
|
|
8
|
+
"imbrace ai-agent list-folders --search support",
|
|
9
|
+
"imbrace ai-agent list-folders --json",
|
|
10
|
+
];
|
|
11
|
+
static flags = {
|
|
12
|
+
search: Flags.string({ char: "s", description: "Filter by name (case-insensitive)" }),
|
|
13
|
+
json: Flags.boolean({ description: "Output as JSON" }),
|
|
14
|
+
};
|
|
15
|
+
async run() {
|
|
16
|
+
const { flags } = await this.parse(AiAgentListFolders);
|
|
17
|
+
const qs = flags.search ? `?q=${encodeURIComponent(flags.search)}` : "";
|
|
18
|
+
try {
|
|
19
|
+
const res = await apiRequest(`/ai-agent/folders${qs}`);
|
|
20
|
+
if (flags.json) {
|
|
21
|
+
this.log(JSON.stringify(res, null, 2));
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
this.log(`\n Found ${res.count} folder(s):\n`);
|
|
25
|
+
this.log(" ID NAME FILES");
|
|
26
|
+
this.log(" ──────────────────────────────────────────────────────────────────────────────");
|
|
27
|
+
for (const f of res.data || []) {
|
|
28
|
+
const id = (f._id || f.id || "").padEnd(40);
|
|
29
|
+
const name = (f.name || "").padEnd(28);
|
|
30
|
+
const files = String(f.file_count ?? 0).padStart(5);
|
|
31
|
+
this.log(` ${id} ${name} ${files}`);
|
|
32
|
+
}
|
|
33
|
+
this.log(`\n Use 'imbrace ai-agent list-files --folder-id <id>' to see files.\n`);
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
this.error(`Failed: ${error.message}`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -22,7 +22,7 @@ export default class AiAgentListProviders extends BaseCommand {
|
|
|
22
22
|
this.log(" ID NAME TYPE MODELS");
|
|
23
23
|
this.log(" ─────────────────────────────────────────────────────────────────────────────");
|
|
24
24
|
for (const p of res.data || []) {
|
|
25
|
-
const id = (p._id || "").padEnd(40);
|
|
25
|
+
const id = (p.id || p.provider_id || p._id || "").padEnd(40);
|
|
26
26
|
const name = (p.name || "").padEnd(16);
|
|
27
27
|
const type = (p.type || "").padEnd(11);
|
|
28
28
|
const models = (p.models || []).slice(0, 3).join(", ") + ((p.models || []).length > 3 ? `, +${p.models.length - 3} more` : "");
|
|
@@ -21,6 +21,11 @@ export default class AiAgentUpdate extends BaseCommand {
|
|
|
21
21
|
category: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
22
22
|
"guardrail-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
23
23
|
"preload-information": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
|
+
"folder-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
25
|
+
"default-folder-id": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
26
|
+
"knowledge-hubs": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
27
|
+
"board-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
28
|
+
"file-ids": import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
|
|
24
29
|
"show-thinking": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
25
30
|
streaming: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
26
31
|
"use-memory": import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
@@ -35,6 +35,12 @@ export default class AiAgentUpdate extends BaseCommand {
|
|
|
35
35
|
}),
|
|
36
36
|
"guardrail-id": Flags.string({ description: "Guardrail ID (set to empty string to remove)" }),
|
|
37
37
|
"preload-information": Flags.string({ description: "Preload information" }),
|
|
38
|
+
// Knowledge Support
|
|
39
|
+
"folder-ids": Flags.string({ description: "Comma-separated Knowledge Hub folder IDs" }),
|
|
40
|
+
"default-folder-id": Flags.string({ description: "Default folder ID" }),
|
|
41
|
+
"knowledge-hubs": Flags.string({ description: "Comma-separated Knowledge Hub IDs" }),
|
|
42
|
+
"board-ids": Flags.string({ description: "Comma-separated Document Model (data board) IDs" }),
|
|
43
|
+
"file-ids": Flags.string({ description: "Comma-separated file IDs" }),
|
|
38
44
|
// Runtime toggles
|
|
39
45
|
"show-thinking": Flags.boolean({ description: "Show thinking process", allowNo: true }),
|
|
40
46
|
streaming: Flags.boolean({ description: "Stream response", allowNo: true }),
|
|
@@ -76,6 +82,16 @@ export default class AiAgentUpdate extends BaseCommand {
|
|
|
76
82
|
body.guardrail_id = flags["guardrail-id"];
|
|
77
83
|
if (flags["preload-information"] !== undefined)
|
|
78
84
|
body.preload_information = flags["preload-information"];
|
|
85
|
+
if (flags["folder-ids"] !== undefined)
|
|
86
|
+
body.folder_ids = flags["folder-ids"].split(",").map(s => s.trim()).filter(Boolean);
|
|
87
|
+
if (flags["default-folder-id"] !== undefined)
|
|
88
|
+
body.default_folder_id = flags["default-folder-id"];
|
|
89
|
+
if (flags["knowledge-hubs"] !== undefined)
|
|
90
|
+
body.knowledge_hubs = flags["knowledge-hubs"].split(",").map(s => s.trim()).filter(Boolean);
|
|
91
|
+
if (flags["board-ids"] !== undefined)
|
|
92
|
+
body.board_ids = flags["board-ids"].split(",").map(s => s.trim()).filter(Boolean);
|
|
93
|
+
if (flags["file-ids"] !== undefined)
|
|
94
|
+
body.file_ids = flags["file-ids"].split(",").map(s => s.trim()).filter(Boolean);
|
|
79
95
|
if (flags["show-thinking"] !== undefined)
|
|
80
96
|
body.show_thinking_process = flags["show-thinking"];
|
|
81
97
|
if (flags.streaming !== undefined)
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Command } from "@oclif/core";
|
|
2
|
+
export default class Docs extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
path: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
};
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
}
|