@kilogent/runner 0.1.7 → 0.1.8
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 +127 -326
- package/dist/cli.js +7035 -4990
- package/dist/kg-session-launcher.mjs +1047 -0
- package/dist/provision-root.mjs +877 -0
- package/npm-shrinkwrap.json +1129 -0
- package/package.json +12 -6
package/README.md
CHANGED
|
@@ -1,368 +1,169 @@
|
|
|
1
1
|
# @kilogent/runner
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
**Kilogent's internal server runner.** It runs the agent jobs of [Kilogent](https://app.kilogent.com)
|
|
4
|
+
workspaces on Kilogent's own servers.
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
> **This is not something a customer installs.** A workspace never has machines: it asks for work,
|
|
7
|
+
> and Kilogent decides which of its servers runs it (PRD §15.89). There is no customer enrolment, no
|
|
8
|
+
> approval and no per-workspace setup. If you are a Kilogent customer, there is nothing here for you
|
|
9
|
+
> to do.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
kilogent-runner setup
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Which package to install
|
|
17
|
-
|
|
18
|
-
There are **two**, one per environment. They install side by side — different command names,
|
|
19
|
-
different config directories, different service labels — so one machine can run both.
|
|
20
|
-
|
|
21
|
-
| Package | Command | Workspace |
|
|
22
|
-
| --- | --- | --- |
|
|
23
|
-
| `@kilogent/runner` | `kilogent-runner` | production |
|
|
24
|
-
| `@kilogent/runner-dev` | `kilogent-runner-dev` | development |
|
|
25
|
-
|
|
26
|
-
The Machines page in your workspace prints the one that matches it. **The package IS the channel**:
|
|
27
|
-
each publishes only a `latest` tag, and a machine changes environment by installing the other one.
|
|
28
|
-
|
|
29
|
-
## Requirements
|
|
30
|
-
|
|
31
|
-
| | |
|
|
32
|
-
|---|---|
|
|
33
|
-
| **Node.js** | 20 or newer |
|
|
34
|
-
| **An engine CLI** | fetched for you — the daemon installs what your crews need (a few hundred MB each). Bring your own with `CREW_<ENGINE>_BIN`, or decline the lot with `config set autoInstallEngines off`. See [Engines](#engines). |
|
|
35
|
-
| **git / gh** | only if your agents work on GitHub repositories |
|
|
36
|
-
| **A Lumi Crew account** | with at least one Ship — [app.kilogent.com](https://app.kilogent.com) |
|
|
37
|
-
|
|
38
|
-
The daemon is a *client*. It signs in as you, and every write it makes is checked server-side
|
|
39
|
-
against your Ship membership. No service-account key ever touches your machine.
|
|
40
|
-
|
|
41
|
-
## Engines
|
|
42
|
-
|
|
43
|
-
An agent runs on an **engine** — the CLI that actually holds the session. The daemon spawns the
|
|
44
|
-
engine's binary per job, and `doctor` checks that every engine a Ship's agents use is installed.
|
|
45
|
-
|
|
46
|
-
**You do not have to install them yourself.** The daemon fetches the CLIs its crews need into its
|
|
47
|
-
own folder (`~/.kilogent-runner/tools/<engine>/`) and runs agents on that copy. A CLI you installed
|
|
48
|
-
yourself is never changed or removed, and the two stay independent: upgrade yours whenever you like,
|
|
49
|
-
the crew keeps running on the version the fleet knows works.
|
|
50
|
-
|
|
51
|
-
⚠️ **They are large.** The Codex CLI is about 284 MB installed and Claude Code about 202 MB. Each is
|
|
52
|
-
replaced rather than added to on an upgrade, so a machine running both settles around half a
|
|
53
|
-
gigabyte. To decline the whole thing and manage them yourself:
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
kilogent-runner config set autoInstallEngines off
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
Which version a machine installs comes from the fleet, not from this machine: it takes the version
|
|
60
|
-
known to work, moves to a newer release only after that release has been out for a day, and never
|
|
61
|
-
installs one another machine has proved broken. If a new version breaks a job here, this daemon puts
|
|
62
|
-
the working version back, runs the job again, and — only if that succeeds — tells the fleet, so no
|
|
63
|
-
other machine installs it.
|
|
64
|
-
|
|
65
|
-
```
|
|
66
|
-
kilogent-runner engine list what each engine needs, what this machine has, and where it came from
|
|
67
|
-
kilogent-runner engine install [engine...] install now (--check, --dry-run, --force)
|
|
68
|
-
kilogent-runner engine uninstall <engine> remove this runner's copy, never yours
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
| Engine | Binary | Credential |
|
|
72
|
-
|---|---|---|
|
|
73
|
-
| Claude Code | `claude` ([install](https://claude.com/claude-code)) | a `claude setup-token`, pasted once per Ship in the Crew app |
|
|
74
|
-
| Codex CLI | `codex` ([install](https://developers.openai.com/codex)) | a **machine sign-in**: a captain picks this machine in the Crew app, the daemon runs `codex login --device-auth`, and the captain approves the code on a phone. The login stays on this machine — see [Credentials](#credentials). |
|
|
75
|
-
|
|
76
|
-
Each engine's binary can be overridden with `CREW_<ENGINE>_BIN` (`CREW_CLAUDE_BIN`), which wins over
|
|
77
|
-
the copy the daemon installed and is the supported way to pin a machine to a particular binary. It
|
|
78
|
-
is also how the test suites substitute a deterministic fake.
|
|
79
|
-
|
|
80
|
-
## Connect a machine
|
|
11
|
+
A server is set up by the command the admin console prints for it (see [Adding a server](#adding-a-server)).
|
|
12
|
+
On a Linux server, as root:
|
|
81
13
|
|
|
82
14
|
```bash
|
|
83
|
-
|
|
15
|
+
apt-get update
|
|
16
|
+
apt-get install -y --no-install-recommends nodejs curl ca-certificates
|
|
17
|
+
curl -fsSLo kg.tgz https://registry.npmjs.org/@kilogent/runner/-/runner-<version>.tgz
|
|
18
|
+
echo "<sha512 from the console> kg.tgz" | sha512sum -c
|
|
19
|
+
tar xzf kg.tgz && node package/dist/provision-root.mjs --project <projectId> --api-key <webApiKey>
|
|
84
20
|
```
|
|
85
21
|
|
|
86
|
-
|
|
87
|
-
this machine should serve and approve it in one click. The CLI is polling and collects its session,
|
|
88
|
-
runner id and Ship list from the approval — nothing is copied or pasted. If you approve as a
|
|
89
|
-
**captain**, the machine is authorized on your Ships immediately.
|
|
90
|
-
|
|
91
|
-
`setup` then runs `doctor` and offers to install the background service.
|
|
92
|
-
|
|
93
|
-
### A server or VPS
|
|
22
|
+
## How it works
|
|
94
23
|
|
|
95
|
-
`setup` is interactive and refuses without a terminal, but it does not need a browser **on that
|
|
96
|
-
machine**:
|
|
97
|
-
|
|
98
|
-
```bash
|
|
99
|
-
kilogent-runner setup --no-browser
|
|
100
24
|
```
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
For CI or unattended provisioning, where nobody is at a terminal at all, paste a Ship key from the
|
|
106
|
-
Daemons page instead — that page prints this command with the two values already filled in:
|
|
107
|
-
|
|
108
|
-
```bash
|
|
109
|
-
kilogent-runner login --key <shipKey> --api-key <firebaseWebApiKey> --project <projectId>
|
|
25
|
+
key file ──exchangeFleetKey──▶ the server's own session (no workspace in it)
|
|
26
|
+
heartbeat every 30 s ──▶ slots, memory budget, pinned version, which leases are still ours
|
|
27
|
+
wake-up signal / a freed slot / every 15 s ──▶ leaseJobs
|
|
28
|
+
each lease ──▶ its own Firebase app, signed in with a ONE-JOB PASS ──▶ the agent session ──▶ app deleted
|
|
110
29
|
```
|
|
111
30
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
31
|
+
- **The backend places, the server leases.** The scheduler puts each queued job on one server. A
|
|
32
|
+
server can only lease the jobs placed on itself, and each lease carries a one-job pass.
|
|
33
|
+
- **The pass is the whole authority for a job.** Progress, transcript, finalize, notes, the credit
|
|
34
|
+
meter, the AI gateway key, GitHub, MCP connections and the Workspace MCP bearer all use it. It can
|
|
35
|
+
write only its own job, its own task or chat, and its own agent's status.
|
|
36
|
+
- **A job goes back to the queue only through the backend** (`returnLease`): a retry, a release, a
|
|
37
|
+
usage limit, or a shutdown.
|
|
38
|
+
- **It stops itself before the backend gives up on it.** With no accepted heartbeat for
|
|
39
|
+
`staleServerMs − 30 s` (60 s by default), or when a heartbeat is refused, it aborts every session and
|
|
40
|
+
writes nothing more for them. The backend requeues or fails those jobs by its own rules.
|
|
117
41
|
|
|
118
|
-
|
|
119
|
-
Ships, from this or another account*; the second person approves in their own browser, with their
|
|
120
|
-
own sign-in.
|
|
42
|
+
## Which package
|
|
121
43
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
44
|
+
| Package | Command | Project |
|
|
45
|
+
| --- | --- | --- |
|
|
46
|
+
| `@kilogent/runner` | `kilogent-runner` | production (`kilogent-crew-prod`) |
|
|
47
|
+
| `@kilogent/runner-dev` | `kilogent-runner-dev` | development (`lumi-afb7d`) |
|
|
48
|
+
|
|
49
|
+
They install side by side with different command names, config directories and service labels.
|
|
50
|
+
|
|
51
|
+
## Adding a server
|
|
52
|
+
|
|
53
|
+
1. In the **admin console → Fleet**, press **Add server**. It shows a one-time **enrolment code** (valid for 30
|
|
54
|
+
minutes) and the one command for a Linux server or the dev Mac.
|
|
55
|
+
2. Run that command on the machine and paste the code when asked.
|
|
56
|
+
- **Linux, as root:** it downloads the pinned release, checks its sha512, and runs
|
|
57
|
+
`node package/dist/provision-root.mjs`. That creates the service user, installs Node, Docker, gVisor and
|
|
58
|
+
the session firewall, installs the runner in the user's own prefix, enrols, and starts the service.
|
|
59
|
+
`--plan` shows what it would do and changes nothing.
|
|
60
|
+
- **The dev Mac, as the runner user:** `npx --yes @kilogent/runner-dev@<version> provision`. Before it, install
|
|
61
|
+
Node 22 and Docker Desktop, open Docker Desktop once, and set it to start when you sign in. The command
|
|
62
|
+
installs the runner into `~/.local`, enrols and installs the LaunchAgent; the image is pulled by the server
|
|
63
|
+
itself. The Mac warnings on the Fleet page (FileVault and automatic login, an administrator account, cloud
|
|
64
|
+
logins in the account) are advice for a dedicated machine and do not stop work.
|
|
65
|
+
3. The server makes its own key; only its hash leaves the machine. If it enrolled from an address the server
|
|
66
|
+
does not list, **Approve** it in Fleet with the last four characters of the key the server printed.
|
|
67
|
+
|
|
68
|
+
`kilogent-runner doctor` and the Fleet page show the same list of what is not ready yet, each with its fix.
|
|
69
|
+
**Retry sandbox** in the console makes the server check again.
|
|
70
|
+
|
|
71
|
+
**A lost, damaged or rotated key** is replaced the same way, never by hand: press **New enrolment code** on the
|
|
72
|
+
server's row and run the command it prints. That command ends in `--re-enrol`, so a machine that already has a
|
|
73
|
+
key enrols again and replaces it. The old key keeps working until then. To cut it off sooner, disable the server,
|
|
74
|
+
and enable it again just before you run the command: a code used while the server is disabled is refused.
|
|
75
|
+
|
|
76
|
+
**Disabling a server** in the console revokes its sessions and recovers its jobs. The daemon stops its
|
|
77
|
+
sessions, keeps retrying the exchange with backoff, and takes work again once it is enabled.
|
|
130
78
|
|
|
131
79
|
## Commands
|
|
132
80
|
|
|
133
81
|
| Command | What it does |
|
|
134
82
|
|---|---|
|
|
135
|
-
| `
|
|
136
|
-
| `
|
|
137
|
-
| `
|
|
138
|
-
| `doctor` |
|
|
139
|
-
| `
|
|
140
|
-
| `uninstall` |
|
|
141
|
-
| `
|
|
142
|
-
| `
|
|
143
|
-
| `
|
|
144
|
-
| `update [--check]` | Install the latest published version
|
|
145
|
-
| `config list` / `set <key>
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
Your `PATH` is captured into the unit at install time. launchd and systemd start processes with a
|
|
174
|
-
minimal environment, so without that `claude`, `git` and `gh` would not be found.
|
|
175
|
-
|
|
176
|
-
**It is captured once, and a restart does not refresh it.** `service restart` re-runs the unit
|
|
177
|
-
exactly as written, so a daemon keeps the `PATH` of whatever shell first installed it. Install a
|
|
178
|
-
tool somewhere new afterwards — `~/.local/bin`, a Homebrew prefix, an nvm switch — and the daemon
|
|
179
|
-
cannot see it, while every check you can run by hand (`which claude`, `kilogent-runner doctor`) is
|
|
180
|
-
answered by your *current* shell and looks fine. The symptom is a job that fails minutes later
|
|
181
|
-
with `spawn claude ENOENT`.
|
|
182
|
-
|
|
183
|
-
Two things close that gap: `doctor` reports it as **Service PATH**, and `kilogent-runner setup` now
|
|
184
|
-
reinstalls the service (rather than merely restarting it) when your environment has drifted from
|
|
185
|
-
the installed unit. To fix it directly, from a shell where the tool works:
|
|
186
|
-
|
|
187
|
-
```bash
|
|
188
|
-
kilogent-runner service install # rewrites the unit with your current PATH
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## How many jobs at once
|
|
192
|
-
|
|
193
|
-
One, until you say otherwise — the same behaviour this daemon has always had.
|
|
194
|
-
|
|
195
|
-
```bash
|
|
196
|
-
kilogent-runner config set parallel 3 # this machine, across every Ship
|
|
197
|
-
kilogent-runner config set parallel 1 --ship shp_abc123 # cap one Ship's share of it
|
|
198
|
-
kilogent-runner config set parallel default --ship shp_abc123 # back to the machine number
|
|
199
|
-
kilogent-runner config list # what is set, and what each Ship gets
|
|
200
|
-
```
|
|
201
|
-
|
|
202
|
-
The machine number is a ceiling, not a total: three Ships at `2` each on a machine set to `3` will
|
|
203
|
-
never run more than three sessions. A Ship with no number of its own may use the whole machine.
|
|
204
|
-
|
|
205
|
-
Each job is a separate engine process with its own empty working directory, so they don't share
|
|
206
|
-
state — but they do share your CPU, your RAM and your subscription's usage window. Start at 2 and watch a
|
|
207
|
-
real job before going higher. Restart the daemon (`kilogent-runner service restart`) to pick up a change.
|
|
208
|
-
|
|
209
|
-
## MCP servers that run on this machine
|
|
210
|
-
|
|
211
|
-
A Ship can register MCP connections its agents reach. Most are remote — an `https://` address the
|
|
212
|
-
session talks to. Two kinds are **local**: a program this machine starts (`npx -y some-mcp-server`,
|
|
213
|
-
`node ./my-server.mjs`), and a server already listening on this machine's own loopback address
|
|
214
|
-
(`http://127.0.0.1:3000/mcp`).
|
|
83
|
+
| `provision --project <id> --api-key <key> [--code-stdin] [--re-enrol]` | Set up the dev Mac as this user. A Linux server uses `dist/provision-root.mjs` as root. `--re-enrol` replaces an existing key with the code. |
|
|
84
|
+
| `enrol --project <id> --api-key <key> [--replace]` | Enrol with a one-time code read from stdin; the server makes its own key. `--replace` gives a server that has a key a new one, and puts the old one back if the code is refused. |
|
|
85
|
+
| `connect --key-file <path> --project <id> [--api-key <key>]` | Make this machine a Kilogent server from an existing key file. |
|
|
86
|
+
| `doctor [--fix]` | The readiness list with each fix, and the key exchange, engines and service. Non-zero exit only for what stops work. `--fix` repairs the key file's mode. |
|
|
87
|
+
| `start` | Run the daemon in the foreground. |
|
|
88
|
+
| `service install` / `uninstall` / `restart` / `status` | Run the daemon as an OS service. `restart`, and `install` over a running service, let running jobs finish first; `--now` does not wait. |
|
|
89
|
+
| `status` | What the daemon last wrote about itself (`<configDir>/fleet-state.json`): phase, heartbeat, slots, running jobs, engines, pin. |
|
|
90
|
+
| `logs [-n N] [-f]` | The daemon's rotating log file. |
|
|
91
|
+
| `engine list` / `install` / `uninstall` | The engine CLIs sessions run on. |
|
|
92
|
+
| `update [--check] [--dry-run]` | Install the latest published version by hand. |
|
|
93
|
+
| `config list` / `set <key> on\|off` | `notifications`, `keepAwake`, `autoInstallEngines`. |
|
|
94
|
+
| `uninstall [--purge]` | Remove the service, then print the `npm rm -g` step. `--purge` also deletes the config directory — and the key file only if it lives inside it, which the confirmation says. |
|
|
95
|
+
|
|
96
|
+
Global flags: `--json`, `-y/--yes`, `--no-color`.
|
|
97
|
+
|
|
98
|
+
Everything that decides what a server does — how many jobs it runs, its memory budget, draining,
|
|
99
|
+
which version the fleet runs, which workspaces are rolled out — is set in the **admin console**, not
|
|
100
|
+
here, and reaches the server with its heartbeat.
|
|
101
|
+
|
|
102
|
+
## The sandbox
|
|
103
|
+
|
|
104
|
+
Every Kilogent server runs every workspace's jobs, so each session runs in a container from the image its
|
|
105
|
+
release names, by digest, pulled with a short-lived token the server asks for over its own fleet session. A
|
|
106
|
+
server takes no work until it has pulled that image and a probe container has proved a session can run.
|
|
107
|
+
|
|
108
|
+
On Linux the runner's user cannot reach Docker at all: every session goes through a root-owned launcher, under
|
|
109
|
+
gVisor, on a network that cannot reach the host, the cloud metadata service or private addresses. The dev Mac
|
|
110
|
+
runs sessions with Docker Desktop and claims no such boundary.
|
|
111
|
+
|
|
112
|
+
Where the console turns it on (§15.92), a session starts at a small memory limit and the runner raises it while
|
|
113
|
+
the session runs, up to a max set in the console: the root launcher does it on Linux, the daemon itself on the
|
|
114
|
+
Mac. The heartbeat reports the memory this server has for sessions and what its sessions really use, and the
|
|
115
|
+
backend places work by those numbers. A session stopped at its max fails its job with a sentence saying so; one
|
|
116
|
+
stopped below its max goes back to the queue and runs again from its max.
|
|
117
|
+
|
|
118
|
+
A session runs directly on the machine only in a local emulator stack (both `FIRESTORE_EMULATOR_HOST` and
|
|
119
|
+
`FIREBASE_AUTH_EMULATOR_HOST` set).
|
|
215
120
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
```bash
|
|
219
|
-
kilogent-runner config set local-mcp on --ship shp_abc123 # this Ship may run programs here
|
|
220
|
-
kilogent-runner config set local-mcp off --ship shp_abc123 # stop allowing it
|
|
221
|
-
kilogent-runner doctor # which Ships have local connections, and whether they may run
|
|
222
|
-
```
|
|
223
|
-
|
|
224
|
-
There is no machine-wide form on purpose. A captain registers these in a browser and may not be the
|
|
225
|
-
person who owns this computer — and if this daemon serves several Ships, a single switch would enrol
|
|
226
|
-
every one of them, including any added later. So it is granted per Ship, by you, here.
|
|
227
|
-
|
|
228
|
-
What a Ship gets when you allow it: the connections a captain registered **on that Ship**, activated
|
|
229
|
-
on the agent running the job, and nothing else. The daemon writes them into the session's config
|
|
230
|
-
file — your own `~/.claude.json` and any `.mcp.json` lying around are still invisible to every agent
|
|
231
|
-
session, exactly as before.
|
|
121
|
+
## Engines
|
|
232
122
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
daemon (`kilogent-runner service restart`) after changing this.
|
|
123
|
+
The daemon installs every engine it has an installer for when it starts, reports each engine's state
|
|
124
|
+
on every heartbeat, and installs one on demand when a lease needs it. A binary given by
|
|
125
|
+
`CREW_<ENGINE>_BIN` is the operator's: it is reported as `unmanaged` and never installed over. Deep
|
|
126
|
+
Agents has no installer; point `CREW_DEEPAGENTS_BIN` at it.
|
|
238
127
|
|
|
239
|
-
|
|
128
|
+
Which version is installed comes from `crewConfig/engines`. If a new version breaks a job, the
|
|
129
|
+
daemon puts the known-good version back, runs the job again, and — only if that works — reports the
|
|
130
|
+
version so no other server installs it.
|
|
240
131
|
|
|
241
|
-
|
|
242
|
-
version of the package it was installed from. When there is, it stops claiming new work, lets the
|
|
243
|
-
jobs it is already running **finish**, installs the new version, and exits — launchd and systemd
|
|
244
|
-
restart it, which is what picks up the new code. A captain sees all of it on the Daemons page.
|
|
132
|
+
## The pinned version
|
|
245
133
|
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
134
|
+
The console pins one exact runner version for the fleet, and records npm's integrity for it. A server whose
|
|
135
|
+
version differs checks that npm still gives the pinned bytes, pulls and probes the next release's image while
|
|
136
|
+
it keeps working, and only then drains (finishes its jobs, takes no new ones), installs **that exact version**
|
|
137
|
+
and exits so the service restarts it. The pin reaches a few servers at a time, so the fleet never stops
|
|
138
|
+
together. When a server cannot move, the reason is shown in the console.
|
|
250
139
|
|
|
251
|
-
|
|
252
|
-
kilogent-runner update --check # is there a newer version?
|
|
253
|
-
kilogent-runner update # install it now and restart the service
|
|
254
|
-
```
|
|
140
|
+
## Shutting down
|
|
255
141
|
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
npm i -g @kilogent/runner@0.5.7
|
|
260
|
-
kilogent-runner config set autoUpdate off
|
|
261
|
-
```
|
|
262
|
-
|
|
263
|
-
Other settings, all machine-wide:
|
|
264
|
-
|
|
265
|
-
```bash
|
|
266
|
-
kilogent-runner config set checkEvery 360 # ask less often (minutes, 5–1440)
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
A version is never installed twice: three failed attempts at the same one and the machine stops
|
|
270
|
-
trying until a different version is published. `kilogent-runner doctor` reports whether you are behind,
|
|
271
|
-
always as a warning — being out of date never fails the preflight.
|
|
272
|
-
|
|
273
|
-
## While a job runs
|
|
274
|
-
|
|
275
|
-
- **Idle sleep is inhibited** (`caffeinate` / `systemd-inhibit`, best-effort on Windows), so a
|
|
276
|
-
laptop doesn't suspend mid-session. It cannot veto you choosing Shut Down — no background process
|
|
277
|
-
gets that veto on macOS, and it shouldn't.
|
|
278
|
-
- **Desktop notifications are off by default.** They fire on job start, finish, terminal failure and
|
|
279
|
-
on a daemon stopped with work in flight — which on a busy machine is an interruption every few
|
|
280
|
-
minutes carrying nothing the task board and the Daemons live log do not already show. Turn them on
|
|
281
|
-
with `kilogent-runner config set notifications on`. (Sleep inhibition is a separate setting and stays
|
|
282
|
-
on: "don't close the lid" is `keepAwake`, not a notification.)
|
|
283
|
-
- **SIGTERM releases the job.** The daemon aborts every running session, hands each job back to the
|
|
284
|
-
queue with its retry budget **unspent**, and only then writes itself offline. Stopping the daemon
|
|
285
|
-
never costs you an attempt.
|
|
286
|
-
|
|
287
|
-
## Credentials
|
|
288
|
-
|
|
289
|
-
Agent-session credentials — a pasted engine token and, if your agents use GitHub, a token for that —
|
|
290
|
-
are **not** stored on this machine. A captain saves them once per Ship in the Crew app's Ship
|
|
291
|
-
Settings, and the daemon fetches them at job time, injects them into the session environment, and
|
|
292
|
-
redacts them from the transcript before upload. `kilogent-runner doctor` tells you when a Ship is
|
|
293
|
-
missing them.
|
|
294
|
-
|
|
295
|
-
**Machine sign-ins are the exception, on purpose.** An engine whose account has no static token
|
|
296
|
-
(Codex on a ChatGPT plan: its login rotates a refresh token on every use, so a copy on a second
|
|
297
|
-
machine kills the first) is signed in ON ONE MACHINE. The daemon keeps that login in a private
|
|
298
|
-
directory, `~/.kilogent-runner/engines/<engine>/<ship>/<credential>/`, refreshes it itself, and
|
|
299
|
-
never sends it anywhere. Jobs on that credential run on this machine only; the daemon runs one
|
|
300
|
-
session per sign-in at a time. Deleting the credential in the app signs this machine out and removes
|
|
301
|
-
the directory; so does removing the machine from the Ship, and `kilogent-runner uninstall --purge`.
|
|
302
|
-
`doctor` reports each sign-in this machine holds and whether the engine still accepts it.
|
|
303
|
-
|
|
304
|
-
The only other thing stored locally is your own session, in `~/.kilogent-runner/config.json`
|
|
305
|
-
(mode `0600`).
|
|
142
|
+
SIGTERM aborts every session and hands each job back with its retry unused, then sends a last
|
|
143
|
+
heartbeat that takes the server out of placement at once. Whatever did not get back within the grace
|
|
144
|
+
period, the backend recovers.
|
|
306
145
|
|
|
307
146
|
## Uninstalling
|
|
308
147
|
|
|
309
|
-
Remove the service **before** the package
|
|
148
|
+
Remove the service **before** the package, or the service keeps restarting a binary that no longer
|
|
149
|
+
exists:
|
|
310
150
|
|
|
311
151
|
```bash
|
|
312
152
|
kilogent-runner uninstall
|
|
313
153
|
npm rm -g @kilogent/runner
|
|
314
154
|
```
|
|
315
155
|
|
|
316
|
-
Order matters, and getting it wrong is silent. The launchd plist / systemd unit records an
|
|
317
|
-
*absolute path* to the CLI inside `node_modules` — it has to, since the OS needs something to exec.
|
|
318
|
-
`npm rm -g` deletes that file but knows nothing about your service, so the service stays registered
|
|
319
|
-
and keeps respawning a binary that is no longer there, roughly every ten seconds, for as long as
|
|
320
|
-
the machine lives. npm cannot help here: since npm 7 it does not run `preuninstall`/`postuninstall`
|
|
321
|
-
scripts at all, so no package can clean up after itself.
|
|
322
|
-
|
|
323
|
-
Already removed the package? Reinstall it, uninstall properly, then remove it again:
|
|
324
|
-
|
|
325
|
-
```bash
|
|
326
|
-
npm i -g @kilogent/runner && kilogent-runner uninstall && npm rm -g @kilogent/runner
|
|
327
|
-
```
|
|
328
|
-
|
|
329
|
-
`kilogent-runner doctor` reports a machine that is already in this state, naming the missing path.
|
|
330
|
-
|
|
331
|
-
Neither command touches `~/.kilogent-runner`. That directory is this machine's **identity** — the
|
|
332
|
-
runner id each account knows it by, and its Ship keys — so uninstalling and reinstalling keeps the
|
|
333
|
-
approvals your captains already granted. Add `--purge` to delete it too, and expect to be approved
|
|
334
|
-
again from scratch, by every account.
|
|
335
|
-
|
|
336
|
-
## Upgrading from `crew-runner`
|
|
337
|
-
|
|
338
|
-
This package was previously distributed inside the Lumi monorepo as `@lumi/crew-runner`, with a
|
|
339
|
-
`crew-runner` command. If that's what you have:
|
|
340
|
-
|
|
341
|
-
```bash
|
|
342
|
-
crew-runner service uninstall
|
|
343
|
-
npm rm -g @lumi/crew-runner
|
|
344
|
-
npm i -g @kilogent/runner
|
|
345
|
-
kilogent-runner service install
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
You do **not** need to log in again. `~/.crew-runner` is migrated to `~/.kilogent-runner` automatically
|
|
349
|
-
on the first run, which keeps your machine's identity — and therefore the approvals your captain
|
|
350
|
-
already granted it. `service install` also removes the old `com.lumi.crew-runner` /
|
|
351
|
-
`crew-runner.service` unit if the uninstall above was skipped, so you never end up with two daemons
|
|
352
|
-
claiming from one queue.
|
|
353
|
-
|
|
354
156
|
## Environment variables
|
|
355
157
|
|
|
356
158
|
| Var | Effect |
|
|
357
159
|
|---|---|
|
|
358
|
-
| `
|
|
359
|
-
| `
|
|
360
|
-
| `
|
|
361
|
-
| `
|
|
362
|
-
| `
|
|
363
|
-
| `
|
|
364
|
-
|
|
365
|
-
`CREW_RUNNER_HOME` is still honoured as a fallback for machines configured before the rename.
|
|
160
|
+
| `CREW_SANDBOX_IMAGE` | A locally built session image, read **only in a local emulator stack**. A server runs its release's image. |
|
|
161
|
+
| `CREW_SANDBOX_RUNTIME` / `CREW_SANDBOX_NETWORK` / `CREW_SANDBOX_USER` | Container runtime, network and user when Docker is used directly (the dev Mac, a local stack). |
|
|
162
|
+
| `CREW_<ENGINE>_BIN` | An engine's binary, e.g. `CREW_CLAUDE_BIN`, `CREW_DEEPAGENTS_BIN`. |
|
|
163
|
+
| `LUMI_RUNNER_HOME` | Config and log directory (default `~/.kilogent-runner`). |
|
|
164
|
+
| `CREW_FUNCTIONS_URL` / `CREW_MCP_URL` | Override the Functions and Workspace MCP endpoints (emulators, e2e). |
|
|
165
|
+
| `CREW_NO_NOTIFY` / `CREW_NO_POWER` | Turn off desktop notifications / sleep inhibition. |
|
|
166
|
+
| `LUMI_RUNNER_REGISTRY` | npm registry for `update` (default `https://registry.npmjs.org`). |
|
|
366
167
|
|
|
367
168
|
## License
|
|
368
169
|
|