@shogo-ai/worker 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +432 -0
  3. package/bin/shogo.mjs +38 -0
  4. package/dist/cli.mjs +64 -0
  5. package/package.json +62 -0
  6. package/src/cli.ts +199 -0
  7. package/src/commands/agent.ts +123 -0
  8. package/src/commands/config.ts +29 -0
  9. package/src/commands/doctor.ts +128 -0
  10. package/src/commands/login.ts +126 -0
  11. package/src/commands/logs.ts +24 -0
  12. package/src/commands/project-checkout.ts +179 -0
  13. package/src/commands/project-pull.ts +133 -0
  14. package/src/commands/project-push.ts +89 -0
  15. package/src/commands/runtime.ts +104 -0
  16. package/src/commands/start.ts +290 -0
  17. package/src/commands/status.ts +22 -0
  18. package/src/commands/stop.ts +13 -0
  19. package/src/lib/__tests__/agent-launch.test.ts +92 -0
  20. package/src/lib/__tests__/cloud-login-coverage.test.ts +210 -0
  21. package/src/lib/__tests__/cloud-login.test.ts +218 -0
  22. package/src/lib/__tests__/cloud-sync-watcher.test.ts +214 -0
  23. package/src/lib/__tests__/config.test.ts +141 -0
  24. package/src/lib/__tests__/db-doctor.test.ts +204 -0
  25. package/src/lib/__tests__/git-cloner.test.ts +382 -0
  26. package/src/lib/__tests__/runtime-manager-auto-pull.test.ts +275 -0
  27. package/src/lib/__tests__/runtime-manager-cloud-sync-gate.test.ts +119 -0
  28. package/src/lib/__tests__/runtime-manager-coverage-gaps.test.ts +768 -0
  29. package/src/lib/__tests__/runtime-manager-describe-rejection.test.ts +42 -0
  30. package/src/lib/__tests__/runtime-manager-git-pull.test.ts +207 -0
  31. package/src/lib/__tests__/runtime-manager-idle-eviction.test.ts +196 -0
  32. package/src/lib/__tests__/runtime-manager-restart-cap.test.ts +310 -0
  33. package/src/lib/__tests__/runtime-manager-tree-sitter-env.test.ts +189 -0
  34. package/src/lib/__tests__/runtime-manager-wait-for-health.test.ts +269 -0
  35. package/src/lib/__tests__/runtime-resolver.test.ts +112 -0
  36. package/src/lib/__tests__/tunnel-coverage.test.ts +1094 -0
  37. package/src/lib/__tests__/tunnel-structured-502.test.ts +101 -0
  38. package/src/lib/__tests__/worker-commands-greenfield.test.ts +463 -0
  39. package/src/lib/__tests__/worker-libs-greenfield.test.ts +355 -0
  40. package/src/lib/__tests__/worker-transport-greenfield.test.ts +176 -0
  41. package/src/lib/api-discovery.ts +36 -0
  42. package/src/lib/cloud-login.ts +320 -0
  43. package/src/lib/cloud-sync-watcher.ts +322 -0
  44. package/src/lib/config.ts +68 -0
  45. package/src/lib/db-doctor.ts +355 -0
  46. package/src/lib/device-id.ts +27 -0
  47. package/src/lib/git-cloner.ts +354 -0
  48. package/src/lib/paths.ts +53 -0
  49. package/src/lib/preflight.ts +158 -0
  50. package/src/lib/process-manager.ts +123 -0
  51. package/src/lib/resource-limits.ts +340 -0
  52. package/src/lib/runtime-install.ts +371 -0
  53. package/src/lib/runtime-manager.ts +1873 -0
  54. package/src/lib/runtime-resolver.ts +136 -0
  55. package/src/lib/transport.ts +202 -0
  56. package/src/lib/tunnel.ts +710 -0
  57. package/src/lib/user-agent.ts +28 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Shogo Technologies, Inc.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,432 @@
1
+ # @shogo-ai/worker
2
+
3
+ Run Shogo Cloud Agents on a machine you already own — a laptop, devbox, or CI runner.
4
+ Outbound-only: the worker dials Shogo Cloud over HTTPS, never the other way around.
5
+
6
+ > Licensed **MIT**. The agent runtime it spawns is licensed AGPL-3.0-or-later
7
+ > and ships as a separate binary — see [Architecture & licensing](#architecture--licensing) below.
8
+
9
+ ## Install
10
+
11
+ **macOS / Linux**
12
+
13
+ ```bash
14
+ curl -fsSL https://install.shogo.ai | bash
15
+ ```
16
+
17
+ **Windows (PowerShell)**
18
+
19
+ ```powershell
20
+ irm https://install.shogo.ai/ps | iex
21
+ ```
22
+
23
+ The installer drops a single self-contained binary at `~/.shogo/bin/shogo`
24
+ (`%USERPROFILE%\.shogo\bin\shogo.exe` on Windows), verifies its SHA-256 against
25
+ the published sidecar, and adds the bin dir to `PATH`. No Node or Bun on the
26
+ target machine required.
27
+
28
+ ### Installer flags
29
+
30
+ ```bash
31
+ curl -fsSL https://install.shogo.ai | bash -s -- [flags]
32
+
33
+ --channel <stable|beta> release channel (default: stable)
34
+ --prefix <dir> install dir (default: $HOME/.shogo/bin)
35
+ --force overwrite existing install
36
+ --no-binary force npm install even if a prebuilt binary exists
37
+ ```
38
+
39
+ ### Alternate paths
40
+
41
+ | Method | When to use |
42
+ |--------|-------------|
43
+ | `npm i -g @shogo-ai/worker` | Node ≥ 20 already on the machine; you want lockstep with `package.json` in a project repo. |
44
+ | `gh release download v<X.Y.Z> -p 'shogo-<target>.tar.gz'` from [github.com/shogo-labs/shogo-ai/releases](https://github.com/shogo-labs/shogo-ai/releases) | Air-gapped / proxy-locked environments where `install.shogo.ai` is blocked. |
45
+ | `bash packages/shogo-worker/install.sh` from a repo checkout | Self-mirror; pass `SHOGO_RELEASE_HOST=...` to pull tarballs from your own CDN. |
46
+
47
+ The single binary, the npm package, and the GitHub Release tarballs all ship
48
+ from the same `v*` tag, so the version you get is identical regardless of
49
+ install method.
50
+
51
+ ## Quick start
52
+
53
+ ```bash
54
+ # 1. Sign in (opens your browser; falls back to --api-key for CI)
55
+ shogo login
56
+
57
+ # 2. Download the AGPL agent-runtime binary into ~/.shogo/runtime/
58
+ shogo runtime install
59
+
60
+ # 3. Start the worker (detached by default)
61
+ shogo worker start --name my-devbox
62
+
63
+ # 4. Confirm it's online
64
+ shogo worker status
65
+
66
+ # 5. Open https://studio.shogo.ai — your machine appears in the
67
+ # environment dropdown next to the desktop entries.
68
+ ```
69
+
70
+ ### Headless / CI
71
+
72
+ ```bash
73
+ # Skip the browser flow with a personal API key from
74
+ # https://studio.shogo.ai/api-keys
75
+ shogo login --api-key "shogo_sk_..."
76
+
77
+ # Or skip `login` entirely
78
+ SHOGO_API_KEY=shogo_sk_... shogo runtime install
79
+ SHOGO_API_KEY=shogo_sk_... shogo worker start --foreground
80
+ ```
81
+
82
+ ## Commands
83
+
84
+ | Command | What it does |
85
+ |---------|--------------|
86
+ | `shogo login` | Browser device-code flow against `studio.shogo.ai`. `--api-key` / `SHOGO_API_KEY` for headless. `--workspace <id>` to pre-select. `--no-browser` to print the URL only. |
87
+ | `shogo runtime install` | Download + verify + extract the AGPL agent-runtime tarball into `~/.shogo/runtime/`. Flags: `--channel stable\|beta\|nightly`, `--version`, `--force`, `--base-url`. |
88
+ | `shogo runtime version` | Print the installed agent-runtime version. |
89
+ | `shogo runtime where` | Print the resolved binary path (priority order: `--runtime-bin` → `$SHOGO_AGENT_RUNTIME_BIN` → `~/.shogo/runtime/agent-runtime` → `$PATH`). |
90
+ | `shogo runtime update` | Reinstall the latest in-channel build. |
91
+ | `shogo worker start` | Pair this machine with Shogo Cloud. `--foreground` to attach to stdout (e.g. `systemd --user`); default detaches and writes `~/.shogo/worker.pid`. |
92
+ | `shogo worker stop` | Kill the running worker via PID file. |
93
+ | `shogo worker status` | Online / offline + uptime. |
94
+ | `shogo worker logs [-f]` | Tail `~/.shogo/logs/worker.log`. |
95
+ | `shogo config show` | Print config (API key masked). |
96
+ | `shogo config set <key> <value>` | Edit a single key. |
97
+ | `shogo doctor` | Repair a wedged local **Shogo Desktop** database (clears failed migrations so the app can boot). Flags: `--check` (detect only), `--yes` (skip prompt), `--db <path>`, `--bun <path>`, `--no-backup`. See [Repair a wedged local Shogo build](#repair-a-wedged-local-shogo-build). |
98
+
99
+ ## Files & layout
100
+
101
+ ```
102
+ ~/.shogo/
103
+ ├── config.json # API key + cloud URL (mode 0600)
104
+ ├── device-id # stable per-machine UUID; dedupes re-logins
105
+ ├── worker.pid # lifecycle file for `worker start/stop/status`
106
+ ├── logs/
107
+ │ ├── worker.log
108
+ │ └── worker.err.log
109
+ ├── runtime/
110
+ │ ├── agent-runtime # AGPL binary, downloaded by `shogo runtime install`
111
+ │ ├── runtime-template/ # Vite/React/Tailwind scaffolding the runtime seeds
112
+ │ │ # into new project workspaces. MUST live next to the
113
+ │ │ # binary — `getRuntimeTemplatePath()` looks here
114
+ │ │ # second (after the `RUNTIME_TEMPLATE_DIR` env
115
+ │ │ # override). The agent-runtime release tarball
116
+ │ │ # ships binary + this directory together.
117
+ │ ├── tree-sitter-wasm/ # Tree-sitter parser core + per-language grammars
118
+ │ │ # (`tree-sitter.wasm` + `tree-sitter-${lang}.wasm`).
119
+ │ │ # `bun build --compile` bakes the build-machine path
120
+ │ │ # for these into the binary; we ship the WASMs
121
+ │ │ # next to the binary so it can dlopen them at
122
+ │ │ # runtime regardless of where the operator put it.
123
+ │ │ # The worker also exports
124
+ │ │ # `TREE_SITTER_WASM_DIR=<this dir>` to the spawned
125
+ │ │ # runtime so the resolved location is observable
126
+ │ │ # via `env | grep TREE_SITTER`.
127
+ │ └── version.json
128
+ └── projects/<projectId>/ # cloned project workspaces (auto-pulled on first
129
+ # request, override with `--projects-dir` /
130
+ # `SHOGO_PROJECTS_DIR`)
131
+ ```
132
+
133
+ ### Workspace seeding (cli-worker)
134
+
135
+ When the worker spawns the agent-runtime for a project, it MUST point that
136
+ runtime at a real on-disk workspace via `WORKSPACE_DIR` / `PROJECT_DIR`.
137
+ Three knobs control where that workspace comes from, in priority order:
138
+
139
+ 1. **Auto-pull (default).** On the first inbound request for a project,
140
+ `WorkerRuntimeManager` clones the cloud snapshot into
141
+ `<projectsDir>/<projectId>/`, watches it via `CloudSyncWatcher`, and
142
+ pushes local edits back. No operator action required.
143
+ 2. **`--projects-dir <path>` / `SHOGO_PROJECTS_DIR=<path>`.** Override the
144
+ root directory under which workspaces live. Useful when you want
145
+ workspaces on a faster disk or backed-up volume.
146
+ 3. **`shogo project pull <projectId>` (manual pre-pull).** When you've
147
+ passed `--no-auto-pull` (e.g. slow or metered connection), the worker
148
+ refuses to spawn until the canonical workspace exists at
149
+ `<projectsDir>/<projectId>/`. Pre-pulling is how you get there.
150
+
151
+ If you disable auto-pull and **don't** pre-pull, the worker fails loudly
152
+ with a multi-line error pointing you at all three options instead of
153
+ silently falling back to an empty workspace.
154
+
155
+ ## Networking
156
+
157
+ The worker needs outbound HTTPS (TCP 443) to 3 hosts. **No inbound ports required.**
158
+
159
+ | Host | Purpose | If blocked |
160
+ |------|---------|-----------|
161
+ | `studio.shogo.ai` | Sign-in, session, heartbeat, on-demand tunnel WS | **FATAL** — worker can't run |
162
+ | `api-direct.shogo.ai` | Direct tunnel fallback (when used) | Graceful — edge routing takes over |
163
+ | `github.com` / `objects.githubusercontent.com` | Runtime binary downloads (`shogo runtime install`) | Only `runtime install/update` affected; can be self-mirrored via `--base-url` |
164
+
165
+ ### Corporate proxy
166
+
167
+ ```bash
168
+ # HTTPS_PROXY / https_proxy / HTTP_PROXY / http_proxy all honoured
169
+ HTTPS_PROXY=http://proxy.corp:3128 shogo worker start
170
+
171
+ # Or pass explicitly (overrides env)
172
+ shogo worker start --proxy http://proxy.corp:3128
173
+
174
+ # TLS-inspecting proxy needs your corp root CA
175
+ NODE_EXTRA_CA_CERTS=/etc/ssl/corp-root.pem \
176
+ HTTPS_PROXY=http://proxy.corp:3128 \
177
+ shogo worker start --debug
178
+ ```
179
+
180
+ `shogo worker start --debug` runs a preflight that includes a proxy-reachability
181
+ check when `HTTPS_PROXY` is set.
182
+
183
+ ## Architecture & licensing
184
+
185
+ The worker is split into two processes that talk over localhost only:
186
+
187
+ ```
188
+ ┌────────────────────────────────────┐ ┌────────────────────────────────────┐
189
+ │ shogo (this package) │ │ agent-runtime │
190
+ │ ── MIT ────────────────────────── │ │ ── AGPL-3.0-or-later ──────────── │
191
+ │ │ │ │
192
+ │ • CLI (login / start / stop) │ │ • Runs your agents │
193
+ │ • WorkerTunnel: HTTP heartbeat + ├────► • Tools, LLM proxy, plans │
194
+ │ on-demand WS to Shogo Cloud │ │ │
195
+ │ • WorkerRuntimeManager: spawns │ │ │
196
+ │ one runtime per project │ │ │
197
+ │ │ │ │
198
+ │ Spawned by you / systemd / etc. │ │ Spawned by the worker (process │
199
+ │ │ │ boundary; not linked as library) │
200
+ └────────────────────────────────────┘ └────────────────────────────────────┘
201
+ ```
202
+
203
+ The MIT worker discovers and spawns the AGPL runtime as a separate OS process —
204
+ no library link, no dynamic import, no embed. This keeps the licenses cleanly
205
+ separated: you may consume `@shogo-ai/worker` from MIT / Apache-2.0 / proprietary
206
+ code without AGPL infecting it.
207
+
208
+ The runtime spawns themselves are managed by `WorkerRuntimeManager`: per-project
209
+ port allocation, env injection, restart-with-backoff, idle eviction, and health
210
+ checks. The same code path is consumed by Shogo Desktop (`apps/api`) for its own
211
+ agent runtimes — so any improvement made here ships to both.
212
+
213
+ ### What the cli-worker tunnel does — and doesn't — handle
214
+
215
+ A cli-worker is an **execution target**: it forwards `/agent/*` paths to
216
+ the per-project agent-runtime and nothing else. Stateful data
217
+ (`/api/projects`, `/api/chat-sessions`, etc.) lives in Shogo Cloud and
218
+ is served by the cloud backend, not by the worker. Studio's
219
+ `SDKDomainProvider` checks `instance.kind` and only tunnels stateful
220
+ APIs through the desktop adapter; for cli-workers it reads from cloud
221
+ directly.
222
+
223
+ If a request for a non-`/agent/*` path does reach the cli-worker tunnel
224
+ (e.g. an out-of-date Studio client), the worker replies with a
225
+ structured 502 body so future debuggers can read the rejection without
226
+ log access:
227
+
228
+ ```json
229
+ {
230
+ "code": "CLI_WORKER_HAS_NO_DATA_API",
231
+ "message": "cli-worker only serves /agent/* paths; tried: /api/projects",
232
+ "path": "/api/projects?workspaceId=ws-1"
233
+ }
234
+ ```
235
+
236
+ ## Programmatic use
237
+
238
+ Both core classes are exposed for direct embedding (e.g. building your own
239
+ desktop wrapper):
240
+
241
+ ```ts
242
+ import { homedir } from 'node:os'
243
+ import { join } from 'node:path'
244
+ import { WorkerTunnel, WorkerRuntimeManager } from '@shogo-ai/worker'
245
+
246
+ // `WorkerRuntimeManager` refuses to spawn a runtime unless it knows
247
+ // where the workspace lives on disk. For embedders that just want
248
+ // the cli-worker default behaviour, set `autoPull` and the manager
249
+ // will clone each project's workspace from cloud on first request.
250
+ // Embedders that manage workspaces themselves should set `projectDir`
251
+ // inside `defaultSpawnConfig` (or via `enrichSpawnConfig`) instead.
252
+ const runtimeManager = new WorkerRuntimeManager({
253
+ defaultSpawnConfig: {
254
+ cloudUrl: 'https://studio.shogo.ai',
255
+ apiKey: process.env.SHOGO_API_KEY!,
256
+ },
257
+ autoPull: {
258
+ enabled: true,
259
+ projectsDir: join(homedir(), '.shogo', 'projects'),
260
+ },
261
+ })
262
+
263
+ const tunnel = new WorkerTunnel({
264
+ apiKey: process.env.SHOGO_API_KEY!,
265
+ cloudUrl: 'https://studio.shogo.ai',
266
+ resolver: runtimeManager, // implements RuntimeResolver
267
+ kind: 'cli-worker',
268
+ onAuthRevoked: (reason) => { /* re-login UX */ },
269
+ })
270
+ tunnel.start()
271
+ ```
272
+
273
+ ## External triggers
274
+
275
+ The worker lets external services (Jira, Linear, Zapier, n8n, your own
276
+ HTTP clients) send messages to a Shogo agent **running on this machine**,
277
+ without exposing any inbound port. Combine `shogo worker start` with a
278
+ project pin in Studio (or via the SDK) and the cloud-side
279
+ `/api/projects/:id/agent-proxy/*` becomes a stable public URL routed
280
+ through the worker's outbound tunnel:
281
+
282
+ ```
283
+ External caller ──HTTPS──▶ Shogo Cloud ──tunnel──▶ shogo worker ──▶ agent-runtime
284
+ (this machine)
285
+ ```
286
+
287
+ ### Pin a project to this machine
288
+
289
+ From Studio: open the project → **Channels → Run on** → pick this machine.
290
+ From a script (uses `@shogo-ai/sdk`):
291
+
292
+ ```ts
293
+ import { createClient } from '@shogo-ai/sdk'
294
+
295
+ const client = createClient({
296
+ apiUrl: 'https://api.shogo.ai',
297
+ shogoApiKey: process.env.SHOGO_API_KEY!,
298
+ })
299
+
300
+ const machines = await client.machines.list({ workspaceId })
301
+ const me = machines.find((m) => m.kind === 'cli_worker' && m.name === 'my-devbox')!
302
+
303
+ await client.machines.pinProject(projectId, {
304
+ instanceId: me.id,
305
+ policy: 'pinned', // 503 instance_offline if this machine goes down
306
+ // (use 'prefer' to fall back to a cloud pod instead)
307
+ })
308
+ ```
309
+
310
+ ### Trigger the agent
311
+
312
+ ```bash
313
+ curl -X POST \
314
+ "https://api.shogo.ai/api/projects/$PROJECT_ID/agent-proxy/agent/channels/webhook/incoming" \
315
+ -H "Authorization: Bearer $SHOGO_API_KEY" \
316
+ -H "X-Webhook-Secret: $CHANNEL_SECRET" \
317
+ -H "Content-Type: application/json" \
318
+ -d '{"message": "Triage Jira ticket ABC-123"}'
319
+ ```
320
+
321
+ The cloud verifies the bearer key, looks up the project pin, and relays
322
+ the request through this worker's existing outbound WebSocket into the
323
+ agent-runtime that the worker spawned on demand. Tool calls (shell, file
324
+ I/O, MCP servers) execute on **this machine**.
325
+
326
+ See [Webhook channel reference](https://docs.shogo.ai/docs/features/external-triggers/webhook-channel)
327
+ for the request/response shape, secret handling, and async callback mode.
328
+
329
+ ## Cloning a staging project (`shogo project pull`)
330
+
331
+ When you pin a staging project to this machine, the worker needs the
332
+ project's workspace files on disk to spawn the agent against. By default
333
+ the worker **auto-clones** the project on first request:
334
+
335
+ ```bash
336
+ shogo worker start # auto-pull is ON, git transport by default
337
+ shogo worker start --no-auto-pull # opt out (e.g. for git-backed projects)
338
+ shogo worker start --no-git # force the Files API path even when git is on PATH
339
+ shogo worker start --projects-dir /mnt/big-disk/shogo # override default ~/.shogo/projects
340
+ ```
341
+
342
+ You can also clone manually ahead of time:
343
+
344
+ ```bash
345
+ # Clones to ~/.shogo/projects/<projectId>/ by default
346
+ shogo project pull <projectId>
347
+
348
+ # Pull-then-watch: keeps a local editor and cloud in sync
349
+ shogo project pull <projectId> --watch
350
+
351
+ # Push local edits back
352
+ shogo project push <projectId>
353
+ shogo project push <projectId> --delete-remote # mirror local deletions
354
+
355
+ # Roll the local workspace back to a specific git checkpoint
356
+ shogo project checkout <projectId> # fast-forward to remote HEAD
357
+ shogo project checkout <projectId> --at "before refactor" # resolve by checkpoint name
358
+ shogo project checkout <projectId> --at <sha> --unshallow # full history
359
+ ```
360
+
361
+ **Two transports.** Auto-pull uses git's smart-HTTP protocol by default
362
+ (`git clone --depth=1` against `https://api.shogo.ai/api/projects/<id>/git`)
363
+ so the worker gets a full checkpoint history and delta-sized pushes for free.
364
+ If `git` isn't available, the worker falls back to the Files API. Manual
365
+ `shogo project pull/push` always uses the Files API so `--include` filters
366
+ and `.shogo/` SQLite state work the same way. See
367
+ [Cloning projects to a paired machine](https://docs.shogo.ai/docs/features/my-machines/project-pull)
368
+ and [Checkpoints on the VPS](https://docs.shogo.ai/docs/features/my-machines/checkpoints-on-the-vps)
369
+ for the end-to-end walkthrough.
370
+
371
+ ## Troubleshooting
372
+
373
+ ```bash
374
+ shogo worker start --debug # run preflight checks
375
+ shogo worker logs --follow # tail live logs
376
+ SHOGO_DEBUG=1 shogo worker status # verbose errors
377
+
378
+ # Runtime missing?
379
+ shogo runtime where # see what's resolved
380
+ shogo runtime install # (re)download the latest stable binary
381
+ ```
382
+
383
+ ### Repair a wedged local Shogo build
384
+
385
+ The Shogo Desktop app keeps its data in a local SQLite database and applies
386
+ schema changes with `prisma migrate deploy` on every launch. If a migration
387
+ is interrupted (a crash, a forced quit, or a buggy update), it can leave a
388
+ `_prisma_migrations` row in a half-applied state. Prisma's P3009 check then
389
+ refuses to run **any** further migrations, and the app gets stuck on startup.
390
+
391
+ The desktop app surfaces a recovery dialog when it hits this on boot, and you
392
+ can trigger the same fix from its **Help → Repair Local Database...** menu. If
393
+ the app won't open at all (or you're walking someone through a fix over a call),
394
+ run it from a terminal instead:
395
+
396
+ ```bash
397
+ shogo doctor # detect, confirm, back up, then clear the wedge
398
+ shogo doctor --check # diagnose only — never touches the database (exit 1 if wedged)
399
+ shogo doctor --yes # repair without the interactive confirmation
400
+ ```
401
+
402
+ What it does:
403
+
404
+ 1. **Detects** stuck migrations in the desktop app's local `shogo.db`.
405
+ 2. **Backs up** the database to a `shogo.db.bak-<timestamp>` sibling file
406
+ (skip with `--no-backup`, discouraged).
407
+ 3. **Clears** the failed migration record (equivalent to
408
+ `prisma migrate resolve --rolled-back`).
409
+
410
+ It does **not** re-run migrations itself — relaunch the Shogo app afterward and
411
+ it will re-apply them cleanly on the next boot. Repair only sticks if you're on
412
+ an app version where the underlying migration is fixed; otherwise you'll hit the
413
+ same state again, but your data is safe in the backup.
414
+
415
+ ```bash
416
+ # Point at a non-default database or a specific bun binary
417
+ shogo doctor --db "/path/to/shogo.db"
418
+ shogo doctor --bun "/Applications/Shogo.app/Contents/Resources/bun/bun"
419
+ ```
420
+
421
+ `shogo doctor` finds the desktop database automatically
422
+ (`~/Library/Application Support/Shogo/data/shogo.db` on macOS,
423
+ `%APPDATA%\Shogo\data\shogo.db` on Windows, `~/.config/Shogo/data/shogo.db` on
424
+ Linux) and uses the `bun` shipped inside the app (or one on your `PATH`). This
425
+ command is local-only; it never contacts Shogo Cloud.
426
+
427
+ ## Links
428
+
429
+ - [Cloud Agent: My Machines guide](../../docs/cloud-agent-my-machines.md) — full
430
+ walk-through, security model, deploy patterns
431
+ - [Networking & firewall guide](../../docs/my-machines-networking.md)
432
+ - Source: [github.com/shogo-labs/shogo-ai](https://github.com/shogo-labs/shogo-ai)
package/bin/shogo.mjs ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ // SPDX-License-Identifier: MIT
3
+ // Copyright (C) 2026 Shogo Technologies, Inc.
4
+ //
5
+ // `shogo` CLI entry shim. Picks an execution mode in this order:
6
+ //
7
+ // 1. Compiled per-platform binary at $PREFIX/dist/shogo (in the
8
+ // tarball release — Bun bundled, no runtime deps).
9
+ // 2. Bundled JS at ../dist/cli.mjs (npm install
10
+ // with no Bun on PATH — Node ESM-loadable).
11
+ // 3. Source TS at ../src/cli.ts (monorepo
12
+ // / `bun link`ed dev, requires Bun or tsx).
13
+ import { fileURLToPath } from 'node:url';
14
+ import { existsSync } from 'node:fs';
15
+ import { dirname, join } from 'node:path';
16
+ import { spawn } from 'node:child_process';
17
+
18
+ const __dirname = dirname(fileURLToPath(import.meta.url));
19
+ const args = process.argv.slice(2);
20
+
21
+ const compiledBin = join(__dirname, '..', 'dist', process.platform === 'win32' ? 'shogo.exe' : 'shogo');
22
+ const distEntry = join(__dirname, '..', 'dist', 'cli.mjs');
23
+ const srcEntry = join(__dirname, '..', 'src', 'cli.ts');
24
+
25
+ if (existsSync(compiledBin)) {
26
+ const child = spawn(compiledBin, args, { stdio: 'inherit' });
27
+ child.on('exit', (code) => process.exit(code ?? 0));
28
+ } else if (existsSync(distEntry)) {
29
+ await import(distEntry);
30
+ } else if (existsSync(srcEntry)) {
31
+ const runner = process.versions.bun ? 'bun' : 'tsx';
32
+ const child = spawn(runner, [srcEntry, ...args], { stdio: 'inherit' });
33
+ child.on('exit', (code) => process.exit(code ?? 0));
34
+ } else {
35
+ console.error('shogo: no executable entry found (looked for dist/shogo, dist/cli.mjs, src/cli.ts)');
36
+ console.error(' Reinstall with `npm i -g @shogo-ai/worker` or rebuild via `bun run build`.');
37
+ process.exit(1);
38
+ }