@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.
- package/LICENSE +21 -0
- package/README.md +432 -0
- package/bin/shogo.mjs +38 -0
- package/dist/cli.mjs +64 -0
- package/package.json +62 -0
- package/src/cli.ts +199 -0
- package/src/commands/agent.ts +123 -0
- package/src/commands/config.ts +29 -0
- package/src/commands/doctor.ts +128 -0
- package/src/commands/login.ts +126 -0
- package/src/commands/logs.ts +24 -0
- package/src/commands/project-checkout.ts +179 -0
- package/src/commands/project-pull.ts +133 -0
- package/src/commands/project-push.ts +89 -0
- package/src/commands/runtime.ts +104 -0
- package/src/commands/start.ts +290 -0
- package/src/commands/status.ts +22 -0
- package/src/commands/stop.ts +13 -0
- package/src/lib/__tests__/agent-launch.test.ts +92 -0
- package/src/lib/__tests__/cloud-login-coverage.test.ts +210 -0
- package/src/lib/__tests__/cloud-login.test.ts +218 -0
- package/src/lib/__tests__/cloud-sync-watcher.test.ts +214 -0
- package/src/lib/__tests__/config.test.ts +141 -0
- package/src/lib/__tests__/db-doctor.test.ts +204 -0
- package/src/lib/__tests__/git-cloner.test.ts +382 -0
- package/src/lib/__tests__/runtime-manager-auto-pull.test.ts +275 -0
- package/src/lib/__tests__/runtime-manager-cloud-sync-gate.test.ts +119 -0
- package/src/lib/__tests__/runtime-manager-coverage-gaps.test.ts +768 -0
- package/src/lib/__tests__/runtime-manager-describe-rejection.test.ts +42 -0
- package/src/lib/__tests__/runtime-manager-git-pull.test.ts +207 -0
- package/src/lib/__tests__/runtime-manager-idle-eviction.test.ts +196 -0
- package/src/lib/__tests__/runtime-manager-restart-cap.test.ts +310 -0
- package/src/lib/__tests__/runtime-manager-tree-sitter-env.test.ts +189 -0
- package/src/lib/__tests__/runtime-manager-wait-for-health.test.ts +269 -0
- package/src/lib/__tests__/runtime-resolver.test.ts +112 -0
- package/src/lib/__tests__/tunnel-coverage.test.ts +1094 -0
- package/src/lib/__tests__/tunnel-structured-502.test.ts +101 -0
- package/src/lib/__tests__/worker-commands-greenfield.test.ts +463 -0
- package/src/lib/__tests__/worker-libs-greenfield.test.ts +355 -0
- package/src/lib/__tests__/worker-transport-greenfield.test.ts +176 -0
- package/src/lib/api-discovery.ts +36 -0
- package/src/lib/cloud-login.ts +320 -0
- package/src/lib/cloud-sync-watcher.ts +322 -0
- package/src/lib/config.ts +68 -0
- package/src/lib/db-doctor.ts +355 -0
- package/src/lib/device-id.ts +27 -0
- package/src/lib/git-cloner.ts +354 -0
- package/src/lib/paths.ts +53 -0
- package/src/lib/preflight.ts +158 -0
- package/src/lib/process-manager.ts +123 -0
- package/src/lib/resource-limits.ts +340 -0
- package/src/lib/runtime-install.ts +371 -0
- package/src/lib/runtime-manager.ts +1873 -0
- package/src/lib/runtime-resolver.ts +136 -0
- package/src/lib/transport.ts +202 -0
- package/src/lib/tunnel.ts +710 -0
- 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
|
+
}
|