@kaiba-cloud/cli 0.1.0 → 0.2.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/README.md +112 -39
- package/action.yml +57 -3
- package/dist/cli.js +8941 -172
- package/package.json +14 -7
- package/skills/kaiba-cli/SKILL.md +239 -0
- package/dist/client.js +0 -52
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kaiba-cloud/cli",
|
|
3
|
-
"version": "0.1
|
|
4
|
-
"description": "Kaiba CLI
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Kaiba CLI \u2014 build and deploy your apps from CI or a terminal.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|
|
7
7
|
"bin": {
|
|
@@ -10,19 +10,26 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"dist",
|
|
12
12
|
"action.yml",
|
|
13
|
-
"README.md"
|
|
13
|
+
"README.md",
|
|
14
|
+
"skills"
|
|
14
15
|
],
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public"
|
|
17
18
|
},
|
|
18
19
|
"scripts": {
|
|
19
|
-
"build": "
|
|
20
|
-
"
|
|
21
|
-
"
|
|
20
|
+
"build": "node scripts/build.mjs",
|
|
21
|
+
"check-types": "tsc --noEmit -p tsconfig.json",
|
|
22
|
+
"test": "vitest run",
|
|
23
|
+
"prepublishOnly": "node scripts/build.mjs && node scripts/verify-tarball.mjs"
|
|
22
24
|
},
|
|
23
25
|
"devDependencies": {
|
|
26
|
+
"@ai-agents/redis-protocol": "workspace:*",
|
|
27
|
+
"@kaiba/sdk": "workspace:*",
|
|
24
28
|
"@types/node": "^20.19.43",
|
|
25
|
-
"typescript": "^5.9.3"
|
|
29
|
+
"typescript": "^5.9.3",
|
|
30
|
+
"esbuild": "^0.25.0",
|
|
31
|
+
"vitest": "^4.1.10",
|
|
32
|
+
"tsx": "^4.19.2"
|
|
26
33
|
},
|
|
27
34
|
"engines": {
|
|
28
35
|
"node": ">=18"
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: kaiba-cli
|
|
3
|
+
description: Use when working with the Kaiba platform from a shell — dispatching a managed agent and waiting for its result, deploying campus skills, agents or blueprints, operating a dev environment, uploading or fetching artifacts, running workflows, or diagnosing a `kaiba` command that failed. Prefer this over the Kaiba MCP tools for anything that has to wait.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# The Kaiba CLI
|
|
7
|
+
|
|
8
|
+
`kaiba` reaches the Kaiba platform as **you**, not as an organisation key. One
|
|
9
|
+
login covers every organisation you belong to, and the platform's own permissions
|
|
10
|
+
decide each request.
|
|
11
|
+
|
|
12
|
+
## First moves
|
|
13
|
+
|
|
14
|
+
Never guess a flag. The CLI describes itself, and the description is generated
|
|
15
|
+
from the same declarations that parse your arguments, so it cannot be out of date:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
kaiba describe # the top-level commands, one line each
|
|
19
|
+
kaiba describe campus agents # one group's commands
|
|
20
|
+
kaiba schema campus agents sessions run # one command's full schema
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`describe` and `schema` need no credential and make no network call. They are
|
|
24
|
+
safe to run first, before you know whether you are logged in.
|
|
25
|
+
|
|
26
|
+
## The shape of the tree
|
|
27
|
+
|
|
28
|
+
Two trees, and everything sits in one of them.
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
campus agents the agent definitions list get create update delete sync
|
|
32
|
+
campus agents sessions the runs of one run list get result history logs message stop close delete
|
|
33
|
+
campus skills what an agent loads list get sync
|
|
34
|
+
campus blueprints a skill plus a scaffold list get sync
|
|
35
|
+
campus artifacts the files agents make list get upload replace download delete tags
|
|
36
|
+
campus workflows graphs that dispatch list get pull push run runs status cancel delete
|
|
37
|
+
|
|
38
|
+
env the dev environment status services logs exec query deploy compose vars …
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`login`, `logout`, `whoami`, `orgs` and `org` sit outside both, and so do the
|
|
42
|
+
four CI commands, which take a different credential.
|
|
43
|
+
|
|
44
|
+
## The output contract
|
|
45
|
+
|
|
46
|
+
Output is **JSON whenever stdout is not a terminal**, so a pipe, a CI job or an
|
|
47
|
+
agent gets machine-readable output with no flag. Add `--output json` to force it,
|
|
48
|
+
or `--output ndjson` for a stream.
|
|
49
|
+
|
|
50
|
+
**Exit codes:**
|
|
51
|
+
|
|
52
|
+
| Code | Meaning |
|
|
53
|
+
|---|---|
|
|
54
|
+
| 0 | Success. Under `--wait`, the agent run also succeeded. |
|
|
55
|
+
| 1 | The CLI or the hub failed. State may be partly changed. |
|
|
56
|
+
| 2 | Auth: no credential, the wrong one, or refused. |
|
|
57
|
+
| 3 | Validation. Refused **before** anything happened. |
|
|
58
|
+
| 4 | Confirmation required. Nothing changed. |
|
|
59
|
+
| 5 | Every write landed, and something a human must fix remains. |
|
|
60
|
+
|
|
61
|
+
Branch on the exit code first. For the sub-case, read `error.code` — it is a
|
|
62
|
+
closed, documented set.
|
|
63
|
+
|
|
64
|
+
Errors go to **stderr** and carry a `hint`, and often a `nextCommand`. **When
|
|
65
|
+
`nextCommand` is present, run it.** It is exact and already quoted.
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{"ok":false,"command":"agents.get",
|
|
69
|
+
"error":{"code":"not-found","message":"Managed agent not found.",
|
|
70
|
+
"hint":"List the agents in this organisation.",
|
|
71
|
+
"nextCommand":"kaiba campus agents list --output json","exitCode":1}}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
**NDJSON streams:** read lines, ignore a `type` you do not recognise, stop at
|
|
75
|
+
`type:"result"`, then read the exit code. That one sentence is the whole contract.
|
|
76
|
+
|
|
77
|
+
## Credentials
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
kaiba login # prints a code, you approve it in a browser, done
|
|
81
|
+
kaiba whoami # which credential, from where, which organisation
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`login` uses a device code, so it works over SSH, in a container and in a sandbox
|
|
85
|
+
— anywhere without a browser. The credential is stored in your OS keychain where
|
|
86
|
+
one is available, and `whoami` always tells you which store was used.
|
|
87
|
+
|
|
88
|
+
**Never pass a token as a flag.** There is no flag for one. A token on a command
|
|
89
|
+
line reaches your shell history, the process table, and an agent's transcript. For
|
|
90
|
+
CI, set `KAIBA_API_TOKEN`.
|
|
91
|
+
|
|
92
|
+
There are two credential classes and they are not interchangeable. `kaiba login`
|
|
93
|
+
gives you a **user** credential for everything under `campus` and `env`. `build`,
|
|
94
|
+
`deploy`, `registry-login` and `status` are the **CI** commands and want a `kaiba_deploy_` token in
|
|
95
|
+
`KAIBA_API_TOKEN`. Present the wrong one and the CLI exits 2 and names the command
|
|
96
|
+
that wants the other.
|
|
97
|
+
|
|
98
|
+
## Choosing an organisation
|
|
99
|
+
|
|
100
|
+
One rule: `--org` beats `KAIBA_ORG_ID`, which beats the stored default, which is
|
|
101
|
+
used only when you belong to exactly one organisation.
|
|
102
|
+
|
|
103
|
+
If none of those resolves and you belong to several, the CLI **refuses** rather
|
|
104
|
+
than picking. Every command reports `data.org.resolvedFrom`, so which source won
|
|
105
|
+
is never a guess.
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
kaiba orgs # list them
|
|
109
|
+
kaiba org use acme # set a default once
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Recipe: run an agent and get its answer
|
|
113
|
+
|
|
114
|
+
This is what the CLI is for. An MCP tool call cannot block for twenty minutes;
|
|
115
|
+
this can.
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
kaiba campus agents sessions run --agent ag-123 --message-file task.md --wait
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**There is no timeout.** It waits until the run is done, however long that takes,
|
|
122
|
+
and heartbeats every minute so you can see it is alive. Read the exit code:
|
|
123
|
+
|
|
124
|
+
- **0** — the agent finished and succeeded. The answer is in `data.result`.
|
|
125
|
+
- **1** with `error.code: "agent-failed"` — it ran and failed. Read the transcript:
|
|
126
|
+
`kaiba campus agents sessions history <id>`.
|
|
127
|
+
- **1** with `error.code: "timeout"` — only possible if you passed `--timeout`.
|
|
128
|
+
`data.sessionId` comes back, so **resume rather than starting again**:
|
|
129
|
+
`kaiba campus agents sessions result <id> --wait`.
|
|
130
|
+
|
|
131
|
+
To start work and collect it later, drop `--wait`: you get a `sessionId`
|
|
132
|
+
immediately.
|
|
133
|
+
|
|
134
|
+
## Recipe: watch a run as it happens
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
kaiba campus agents sessions run --agent ag-123 --message "check the build" --follow --wait --output ndjson
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
`--follow` narrates, `--wait` decides. With both, the exit code comes from the
|
|
141
|
+
result, never from the stream — a terminated session with no result is a failure.
|
|
142
|
+
A dropped connection resumes from the last event with nothing lost or repeated.
|
|
143
|
+
|
|
144
|
+
## Recipe: deploy campus artifacts
|
|
145
|
+
|
|
146
|
+
**Always dry-run first.**
|
|
147
|
+
|
|
148
|
+
```bash
|
|
149
|
+
kaiba campus skills sync --dry-run # read the plan
|
|
150
|
+
kaiba campus skills sync # then do it
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
`--scope system` targets the platform registry and is update-only: it never
|
|
154
|
+
creates. If a sync refuses because an artifact was promoted to system scope, that
|
|
155
|
+
is the cross-scope guard doing its job — do not work around it, use `--scope system`.
|
|
156
|
+
|
|
157
|
+
## Recipe: workflows as files in git
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
kaiba campus workflows pull # graphs to *.trigger.json
|
|
161
|
+
kaiba campus workflows push --dry-run # preview
|
|
162
|
+
kaiba campus workflows push # deploy
|
|
163
|
+
kaiba campus workflows run wf-1 --node dispatch --wait # run from ONE node
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
`push` never arms or disarms anything. Deploying a graph and turning it on are two
|
|
167
|
+
decisions, and the file's `enabled` key is reported against the live state rather
|
|
168
|
+
than applied.
|
|
169
|
+
|
|
170
|
+
## Recipe: operate a dev environment
|
|
171
|
+
|
|
172
|
+
Every `devEnv*` MCP tool has a command here:
|
|
173
|
+
|
|
174
|
+
| MCP tool | Command |
|
|
175
|
+
|---|---|
|
|
176
|
+
| `devEnvConnect`, `devEnvServiceStatus` | `kaiba env status` |
|
|
177
|
+
| `devEnvGetCompose` / `devEnvSetCompose` | `kaiba env compose get` / `set` |
|
|
178
|
+
| `devEnvSetVars` | `kaiba env vars set` |
|
|
179
|
+
| `devEnvDeploy` | `kaiba env deploy` |
|
|
180
|
+
| `devEnvServiceLogs` | `kaiba env logs --service X` |
|
|
181
|
+
| `devEnvExec` | `kaiba env exec --service X -- <cmd>` |
|
|
182
|
+
| `devEnvQuery` | `kaiba env query --service X --engine postgres --sql "..."` |
|
|
183
|
+
| `devEnvRestartService` | `kaiba env restart --service X` |
|
|
184
|
+
| `devEnvResetVolume` / `devEnvResizeVolume` | `kaiba env volume reset` / `resize` |
|
|
185
|
+
| `devEnvRunJob` / `devEnvListJobs` | `kaiba env jobs run` / `list` |
|
|
186
|
+
|
|
187
|
+
`env exec` is one shot and returns captured output. **Its exit code is the remote
|
|
188
|
+
command's**, labelled `exitCodeSource: "remote"` — the one place the exit code is
|
|
189
|
+
not from the table above.
|
|
190
|
+
|
|
191
|
+
## Recipe: artifacts
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
kaiba campus artifacts upload --file report.md --title "Q3 report" --tags finance
|
|
195
|
+
kaiba campus artifacts download art-1 --output-file report.md
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Upload is a two-step presigned PUT and the CLI handles both steps. If it reports
|
|
199
|
+
`error.code: "transport"`, the row exists with no bytes — run the
|
|
200
|
+
`kaiba campus artifacts replace` command it gives you.
|
|
201
|
+
|
|
202
|
+
## Destructive commands
|
|
203
|
+
|
|
204
|
+
There is no interactive prompt, because you cannot answer one. Instead a
|
|
205
|
+
destructive command **exits 4 and changes nothing**, printing what it would do:
|
|
206
|
+
|
|
207
|
+
```json
|
|
208
|
+
{"ok":false,"command":"env.volume.reset",
|
|
209
|
+
"error":{"code":"confirmation-required","exitCode":4},
|
|
210
|
+
"confirmation":{
|
|
211
|
+
"changes":[{"action":"delete","resource":"volume","target":"db",
|
|
212
|
+
"detail":"Every byte in db's volume is lost. This cannot be undone."}],
|
|
213
|
+
"confirmCommand":"kaiba env volume reset --service db --confirm --output json"}}
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
**Show `confirmation.changes` to your human. If they approve, run
|
|
217
|
+
`confirmation.confirmCommand` verbatim.** Do not reconstruct it and do not add
|
|
218
|
+
`--confirm` yourself to a command they have not seen.
|
|
219
|
+
|
|
220
|
+
## What introspection cannot tell you
|
|
221
|
+
|
|
222
|
+
- **Prefer this CLI over the Kaiba MCP tools for anything that waits.** An MCP
|
|
223
|
+
call cannot block and has no cursor to resume from.
|
|
224
|
+
- **A managed-agent pod has no `kaiba` binary.** Inside a pod, use the MCP tools.
|
|
225
|
+
This CLI is for a developer machine, a CI runner, or an agent with a shell.
|
|
226
|
+
- **Always `--dry-run` a campus sync first.**
|
|
227
|
+
- **Never put a token on a command line.**
|
|
228
|
+
|
|
229
|
+
## When something fails
|
|
230
|
+
|
|
231
|
+
| Symptom | What it means |
|
|
232
|
+
|---|---|
|
|
233
|
+
| exit 2, `no-credential` | Run `kaiba login`. |
|
|
234
|
+
| exit 2, `wrong-credential-class` | You have the CI token and want the user one, or the reverse. The error names the right command. |
|
|
235
|
+
| exit 3, no organisation | Pass `--org`, or run `kaiba org use <id>` once. |
|
|
236
|
+
| exit 3, `invalid-input` with a `codePoint` | A value contains a control character. It is refused, not cleaned, because cleaning would change what you named. |
|
|
237
|
+
| exit 3, `cli-too-old` | The platform needs a newer CLI. The hint carries the upgrade command. |
|
|
238
|
+
| exit 4 | Nothing happened. See the confirmation section above. |
|
|
239
|
+
| exit 5 | Every write landed. Something still needs a human — read `data`. |
|
package/dist/client.js
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* HTTP client for the Kaiba CI surface (`/ci/*` on the hub). Authenticates with
|
|
3
|
-
* a scoped deploy token via `x-api-key`. Uses only the Node 18+ global `fetch`,
|
|
4
|
-
* so the CLI ships with no runtime dependencies.
|
|
5
|
-
*/
|
|
6
|
-
export class KaibaApiError extends Error {
|
|
7
|
-
status;
|
|
8
|
-
constructor(status, message) {
|
|
9
|
-
super(message);
|
|
10
|
-
this.status = status;
|
|
11
|
-
this.name = 'KaibaApiError';
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
export class KaibaClient {
|
|
15
|
-
base;
|
|
16
|
-
token;
|
|
17
|
-
constructor(opts) {
|
|
18
|
-
this.base = opts.hubUrl.replace(/\/$/, '');
|
|
19
|
-
this.token = opts.token;
|
|
20
|
-
}
|
|
21
|
-
async request(method, path, body) {
|
|
22
|
-
const res = await fetch(`${this.base}${path}`, {
|
|
23
|
-
method,
|
|
24
|
-
headers: {
|
|
25
|
-
'x-api-key': this.token,
|
|
26
|
-
...(body ? { 'content-type': 'application/json' } : {}),
|
|
27
|
-
},
|
|
28
|
-
...(body ? { body: JSON.stringify(body) } : {}),
|
|
29
|
-
});
|
|
30
|
-
const text = await res.text();
|
|
31
|
-
const data = text ? JSON.parse(text) : {};
|
|
32
|
-
if (!res.ok) {
|
|
33
|
-
throw new KaibaApiError(res.status, data.error ?? `${res.status} ${res.statusText}`);
|
|
34
|
-
}
|
|
35
|
-
return data;
|
|
36
|
-
}
|
|
37
|
-
startBuild(req) {
|
|
38
|
-
return this.request('POST', '/ci/builds', req);
|
|
39
|
-
}
|
|
40
|
-
getBuild(buildId, clusterId) {
|
|
41
|
-
return this.request('GET', `/ci/builds/${encodeURIComponent(buildId)}?clusterId=${encodeURIComponent(clusterId)}`);
|
|
42
|
-
}
|
|
43
|
-
getBuildLogs(buildId, clusterId) {
|
|
44
|
-
return this.request('GET', `/ci/builds/${encodeURIComponent(buildId)}/logs?clusterId=${encodeURIComponent(clusterId)}`);
|
|
45
|
-
}
|
|
46
|
-
deploy(service, image) {
|
|
47
|
-
return this.request('POST', '/ci/deploy', { service, image });
|
|
48
|
-
}
|
|
49
|
-
status() {
|
|
50
|
-
return this.request('GET', '/ci/status');
|
|
51
|
-
}
|
|
52
|
-
}
|