@runneth/cli 0.0.0-sha.08ddca3b68de.production
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 +345 -0
- package/dist/build-defaults.d.ts +6 -0
- package/dist/build-defaults.js +36 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +3732 -0
- package/dist/index.d.ts +28760 -0
- package/dist/index.js +2 -0
- package/dist/src.js +20806 -0
- package/package.json +48 -0
- package/skills/runneth/SKILL.md +318 -0
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runneth/cli",
|
|
3
|
+
"version": "0.0.0-sha.08ddca3b68de.production",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Fast persistent local shell sessions for coding agents",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Motion-Creative/agent-builder.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/Motion-Creative/agent-builder",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Motion-Creative/agent-builder/issues"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=24.0.0"
|
|
17
|
+
},
|
|
18
|
+
"bin": {
|
|
19
|
+
"runneth": "dist/cli.js",
|
|
20
|
+
"runneth-cli": "dist/cli.js"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public",
|
|
24
|
+
"registry": "https://registry.npmjs.org"
|
|
25
|
+
},
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"default": "./dist/index.js"
|
|
30
|
+
},
|
|
31
|
+
"./package.json": "./package.json"
|
|
32
|
+
},
|
|
33
|
+
"types": "./dist/index.d.ts",
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"README.md",
|
|
37
|
+
"skills"
|
|
38
|
+
],
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"ws": "^8.21.0",
|
|
41
|
+
"zod": "4.3.6"
|
|
42
|
+
},
|
|
43
|
+
"runnethCliUpdate": {
|
|
44
|
+
"mode": "registry",
|
|
45
|
+
"packageName": "@runneth/cli",
|
|
46
|
+
"tag": "latest"
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: runneth
|
|
3
|
+
description: Use the Runneth CLI for conversation automation, interactive chat, VM access over SSH, saved targets, and persistent local shells. Use when working with Runneth conversations, connecting to a conversation VM, running remote commands through JSONL, setting up CLI authentication or agent skills, or inspecting the runtime filesystem.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Runneth
|
|
7
|
+
|
|
8
|
+
## CLI Package
|
|
9
|
+
|
|
10
|
+
Use the package spec the user gives you when one is provided. By default, use the public npm package:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npx @runneth/cli ...
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
If the package is already installed on PATH, use `runneth ...`.
|
|
17
|
+
|
|
18
|
+
## CLI updates
|
|
19
|
+
|
|
20
|
+
The promoted CLI checks for updates automatically and asks before installing.
|
|
21
|
+
Use these commands when the user asks about the installed version or wants to
|
|
22
|
+
update:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
runneth --version
|
|
26
|
+
runneth update
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
An update refuses to start while this installation has an active local daemon.
|
|
30
|
+
Let persistent sessions finish, close them, and run `runneth shutdown` in
|
|
31
|
+
each CLI home before retrying the update. Do not end active sessions merely to
|
|
32
|
+
update the CLI unless the user explicitly approves it. The next daemon-backed
|
|
33
|
+
command starts the updated daemon.
|
|
34
|
+
|
|
35
|
+
The first manual package-manager upgrade that installs the updater requires
|
|
36
|
+
this shutdown step in every CLI home and custom socket before installation.
|
|
37
|
+
If an unregistered daemon remains afterward, use `close` and `shutdown` to
|
|
38
|
+
finish the cutover; other daemon commands and updates in that home refuse it.
|
|
39
|
+
`shutdown` succeeds when the selected daemon is already stopped.
|
|
40
|
+
|
|
41
|
+
A crashed updater can leave a durable `replacement.json` record in the
|
|
42
|
+
account-home `.runneth-cli-daemon-gates` directory. It blocks new daemons and
|
|
43
|
+
updates even after heartbeat locks expire. Do not delete it because its PID
|
|
44
|
+
is gone or its timestamp is old. Recovery requires a computer restart, direct
|
|
45
|
+
package-manager repair of the recorded installation, successful `--version`
|
|
46
|
+
and `--help` checks, then removal of only the reported replacement record.
|
|
47
|
+
Follow the installed package README's interrupted-update recovery procedure.
|
|
48
|
+
|
|
49
|
+
## Command discovery
|
|
50
|
+
|
|
51
|
+
Run `runneth help --json` to read the public command catalog. It includes command
|
|
52
|
+
paths, audience, execution location, output format, flags, required inputs, and
|
|
53
|
+
effects. Use `runneth help <command> --json` to narrow the catalog and
|
|
54
|
+
`runneth <command> --help` for examples. Help does not start sign-in or execute commands.
|
|
55
|
+
|
|
56
|
+
Choose the interface for the task:
|
|
57
|
+
|
|
58
|
+
- `chat`: interactive terminal conversations for humans.
|
|
59
|
+
- `conversation`: remote conversation automation through JSON or a persistent JSONL process.
|
|
60
|
+
- `ssh` and `ssh stdio`: commands and processes on a remote VM.
|
|
61
|
+
- `open`, `send`, `status`, `list`, `close`, and `shutdown`: local shells on the user's computer.
|
|
62
|
+
|
|
63
|
+
## Conversations
|
|
64
|
+
|
|
65
|
+
Use an explicit workspace for conversation commands. Check existing sign-in with
|
|
66
|
+
`runneth oauth status`; use `runneth oauth login` when sign-in is needed. Login
|
|
67
|
+
returns an access token, so do not include its output in logs or user-facing
|
|
68
|
+
summaries. Read `runneth help conversation --json` for authentication options.
|
|
69
|
+
|
|
70
|
+
Create a conversation:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
runneth conversation create --workspace <workspace-id> --title "Review the latest report" --json
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Read `conversation.id` from the result, then use that ID for later requests:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
runneth conversation send --workspace <workspace-id> --conversation <conversation-id> --message "Summarize the latest report" --json
|
|
80
|
+
runneth conversation state --workspace <workspace-id> --conversation <conversation-id> --json
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
These commands require `--json`. There is no implicit active conversation.
|
|
84
|
+
`send` waits for the assistant response; use `--stdin` instead of `--message`
|
|
85
|
+
when the message comes from a file or pipe. Inspect the returned assistant
|
|
86
|
+
message's status before reporting success.
|
|
87
|
+
|
|
88
|
+
### Persistent conversation session
|
|
89
|
+
|
|
90
|
+
Keep one process open for repeated conversation operations:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
runneth conversation session --workspace <workspace-id> --jsonl
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Wait for the `ready` event. It reports connection and workspace context, not an
|
|
97
|
+
active conversation. Send one complete JSON object per line, followed by a
|
|
98
|
+
newline. Match response events to the request `id`.
|
|
99
|
+
|
|
100
|
+
<!-- prettier-ignore -->
|
|
101
|
+
```jsonl
|
|
102
|
+
{"id":"1","method":"create","params":{"title":"Review the latest report"}}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Wait for `created`, read `conversation.id`, and replace `<conversation-id>` in
|
|
106
|
+
each request below. Send requests as needed, rather than sending the whole block
|
|
107
|
+
at once:
|
|
108
|
+
|
|
109
|
+
```jsonl
|
|
110
|
+
{"id":"2","method":"send","params":{"conversationId":"<conversation-id>","text":"Summarize the latest report"}}
|
|
111
|
+
{"id":"3","method":"state","params":{"conversationId":"<conversation-id>"}}
|
|
112
|
+
{"id":"4","method":"ping"}
|
|
113
|
+
{"id":"5","method":"close"}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
`send` emits `sent`, state updates, then `complete`. Set `params.wait` to `false`
|
|
117
|
+
to return after `sent`, then use `state` to inspect progress. Treat `error`
|
|
118
|
+
events as failures. `close` ends this local JSONL session; it does not delete the
|
|
119
|
+
remote conversation.
|
|
120
|
+
|
|
121
|
+
## Remote SSH
|
|
122
|
+
|
|
123
|
+
Use the CLI OAuth SSH flow for normal VM access. It handles login, token refresh,
|
|
124
|
+
key generation, public-key installation, SSH configuration, and the tunnel.
|
|
125
|
+
Use Azure, daemon APIs, Datadog, or direct host administration when the user asks
|
|
126
|
+
for fleet, VM, image, daemon, or control-plane debugging, or when debugging the
|
|
127
|
+
CLI path itself.
|
|
128
|
+
|
|
129
|
+
Place remote command arguments after `--` so their flags, including `--help`,
|
|
130
|
+
reach the remote process.
|
|
131
|
+
|
|
132
|
+
### Connect through a conversation
|
|
133
|
+
|
|
134
|
+
When you have a conversation ID and its workspace, let the CLI discover the VM:
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
runneth ssh --workspace <workspace-id> --conversation <conversation-id> -- 'pwd'
|
|
138
|
+
runneth ssh stdio --workspace <workspace-id> --conversation <conversation-id>
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
This resolves the conversation's public SSH target through the API. Do not
|
|
142
|
+
combine `--conversation` with `--target`, `--host`, or `--ssh-url`. Use saved
|
|
143
|
+
targets below when you already have a VM host or SSH app URL.
|
|
144
|
+
|
|
145
|
+
### Saved targets
|
|
146
|
+
|
|
147
|
+
A target stores the OAuth resource URL and the SSH app URL for a VM.
|
|
148
|
+
|
|
149
|
+
Add a target from a full host:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
runneth ssh target add <target-name> \
|
|
153
|
+
--host <full-host> \
|
|
154
|
+
--default
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`--host` is the entire host. Do not infer or append a suffix. If the user gives the complete SSH app URL, use `--ssh-url`:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
runneth ssh target add <target-name> \
|
|
161
|
+
--ssh-url https://<full-host>/runneth/ssh \
|
|
162
|
+
--default
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
List and select targets:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
runneth ssh target list
|
|
169
|
+
runneth ssh target use <target-name>
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Import multiple targets from JSON:
|
|
173
|
+
|
|
174
|
+
```bash
|
|
175
|
+
runneth ssh target import ./runneth-targets.json
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
Example import file:
|
|
179
|
+
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"resourceUrl": "https://projects.motionapp.com/mcp",
|
|
183
|
+
"defaultTarget": "primary",
|
|
184
|
+
"targets": [
|
|
185
|
+
{
|
|
186
|
+
"name": "primary",
|
|
187
|
+
"host": "e0da08e2-cf18-457f-80e3-48745967dedf.app.runneth.com"
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
"name": "worker",
|
|
191
|
+
"sshUrl": "https://example.internal/runneth/ssh"
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### Run a command or shell
|
|
198
|
+
|
|
199
|
+
Run a one-off command:
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
runneth ssh --target <target-name> -- 'whoami && pwd && hostname'
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
Open an interactive shell:
|
|
206
|
+
|
|
207
|
+
```bash
|
|
208
|
+
runneth ssh --target <target-name>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
The CLI reads the target VM's authenticated `/runneth/ssh/api` metadata before
|
|
212
|
+
connecting, independently of app catalog health. VMs
|
|
213
|
+
that advertise `runneth-ssh-v1` authorize one WebSocket upgrade and stream SSH
|
|
214
|
+
bytes over that full-duplex socket. Older VMs continue through the HTTPS
|
|
215
|
+
tunnel. Transport selection is automatic.
|
|
216
|
+
|
|
217
|
+
For agents that need to run multiple operations without reconnecting, keep one
|
|
218
|
+
authenticated SSH session open with stdio mode.
|
|
219
|
+
|
|
220
|
+
### Persistent SSH session
|
|
221
|
+
|
|
222
|
+
Use stdio mode for Claude Code, Codex, and other agents that need to keep one SSH session available without reopening SSH for every command.
|
|
223
|
+
|
|
224
|
+
Start the process:
|
|
225
|
+
|
|
226
|
+
```bash
|
|
227
|
+
runneth ssh stdio --target <target-name>
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
Wait for the `ready` event. Send one complete JSON request per line on stdin,
|
|
231
|
+
followed by a newline, and read one JSON event per line on stdout.
|
|
232
|
+
|
|
233
|
+
One-off command:
|
|
234
|
+
|
|
235
|
+
<!-- prettier-ignore -->
|
|
236
|
+
```jsonl
|
|
237
|
+
{"id":"1","method":"exec","params":{"command":"pwd && ls -la","timeoutMs":600000}}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Spawn a persistent process and write to it:
|
|
241
|
+
|
|
242
|
+
```jsonl
|
|
243
|
+
{"id":"2","method":"spawn","params":{"command":"bash"}}
|
|
244
|
+
{"id":"2","method":"stdin","params":{"data":"pwd\n"}}
|
|
245
|
+
{"id":"2","method":"stdin","params":{"data":"exit\n"}}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
Other supported requests:
|
|
249
|
+
|
|
250
|
+
```jsonl
|
|
251
|
+
{"id":"5","method":"list"}
|
|
252
|
+
{"id":"2","method":"signal","params":{"signal":"SIGINT"}}
|
|
253
|
+
{"id":"2","method":"close"}
|
|
254
|
+
{"id":"7","method":"ping"}
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
For `spawn`, the request `id` is the process id. Wait for `started`, then use the
|
|
258
|
+
same `id` for that process's `stdin`, `signal`, and `close` requests. Match output
|
|
259
|
+
and `exit` events by `id`. A successful remote command has exit `code: 0` and
|
|
260
|
+
`ok: true`; `ok: true` alone does not mean the command succeeded.
|
|
261
|
+
|
|
262
|
+
Keep the stdio process open for the duration of a task. Do not repeatedly reopen SSH for a sequence of commands unless the stdio process is unavailable.
|
|
263
|
+
|
|
264
|
+
## Auth And Keys
|
|
265
|
+
|
|
266
|
+
SSH uses OAuth. On first use it opens a browser or prints an authorization URL; the user must complete that login. Use CLI flags such as `--no-open` only when browser opening is not possible.
|
|
267
|
+
|
|
268
|
+
The CLI generates one shared default Runneth key pair and reuses it across targets by default. The public key is installed into the VM through the OAuth-protected SSH app API.
|
|
269
|
+
|
|
270
|
+
Use `--unique-key` when the user wants a separate key for one target. Use `--identity-file <path>` when the user provides an existing private key and matching public key.
|
|
271
|
+
|
|
272
|
+
The default OAuth resource should be baked into the published CLI from `MONDRIAN_API_URL/mcp`. If a package was built without the correct default, pass `--resource https://projects.motionapp.com/mcp` explicitly and treat that as a package/build issue to fix.
|
|
273
|
+
|
|
274
|
+
## Runtime Filesystem
|
|
275
|
+
|
|
276
|
+
Runtime SSH enters as the `runneth-ssh` user.
|
|
277
|
+
|
|
278
|
+
Useful paths inside a Runneth VM:
|
|
279
|
+
|
|
280
|
+
- `/agent` - workspace shared with the runtime.
|
|
281
|
+
- `/agent/.runtime` - runtime-owned state.
|
|
282
|
+
- `/daemon` - process-daemon HTTP API and runtime controls.
|
|
283
|
+
- `/daemon/ssh/authorized_keys` - Runneth SSH authorized keys on the VM OS disk.
|
|
284
|
+
- `/runneth` - app code and app_core runtime.
|
|
285
|
+
|
|
286
|
+
## Validation
|
|
287
|
+
|
|
288
|
+
For a smoke test, run:
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
runneth ssh --target <target-name> -- 'printf "user=%s pwd=%s host=%s\n" "$(whoami)" "$(pwd)" "$(hostname)"'
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
Expected result: the command exits successfully, the user is usually `runneth-ssh`, and the VM hostname is returned.
|
|
295
|
+
|
|
296
|
+
## Refresh installed skills
|
|
297
|
+
|
|
298
|
+
After updating the CLI, run:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
runneth skills install --agent all
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
This replaces the Runneth skill for both Claude Code and Codex with the copy
|
|
305
|
+
bundled in that CLI version. Use `--agent claude` or `--agent codex` to update
|
|
306
|
+
only one. Updating the CLI alone does not refresh installed skills. Start a new
|
|
307
|
+
agent session to load the refreshed instructions.
|
|
308
|
+
|
|
309
|
+
## Troubleshooting
|
|
310
|
+
|
|
311
|
+
Common failures:
|
|
312
|
+
|
|
313
|
+
- `401` or `403`: OAuth is missing, expired, or the user does not have access to the VM organization.
|
|
314
|
+
- Capability request failure: verify the authenticated `/runneth/ssh/api` endpoint is reachable and returns valid SSH metadata. Discovery allows 70 seconds for authorization and response delivery.
|
|
315
|
+
- `503`: public app routing, daemon health, runtime app startup, or the tunnel limit is blocking access.
|
|
316
|
+
- Slow interactive I/O on a VM without the WebSocket capability: the CLI uses the HTTPS polling transport for that VM.
|
|
317
|
+
- Slow interactive I/O over WebSocket: inspect public network latency and VM load.
|
|
318
|
+
- Unexpected idle disconnects: inspect public app and daemon health plus WebSocket heartbeat failures.
|