procdeck 1.1.1 → 2.0.0

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/CHANGELOG.md ADDED
@@ -0,0 +1,277 @@
1
+ # procdeck
2
+
3
+ ## 2.0.0
4
+
5
+ ### Major Changes
6
+
7
+ - procdeck is one native binary now — rewritten in Go, the web UI embedded.
8
+ `npx procdeck` and `pnpm add -D procdeck` keep working: the npm package is a
9
+ small launcher, and the binary for your machine arrives as an optional
10
+ dependency (`@procdeck/<os>-<arch>`), with no install scripts. Node is no
11
+ longer needed to run procdeck. Outside npm there is a Homebrew tap, an
12
+ `install.sh`, and a tarball, `.deb` or `.rpm` per platform on every GitHub
13
+ release; `go install github.com/kondaurovDev/procdeck@latest` builds it from
14
+ source.
15
+
16
+ Breaking, against what 1.0 promised:
17
+
18
+ - **Configs are JSON** — `procdeck.config.json`, or `procdeck.config.jsonc`
19
+ with comments and trailing commas. A `procdeck.config.ts` / `.js` is
20
+ reported with a pointer to move it; `defineConfig` is gone with it.
21
+ - **Unknown config keys are errors**, instead of being silently ignored — a
22
+ typo like `"need"` no longer quietly does nothing.
23
+ - **Regexes are RE2** (`alerts`, `preflight.expect`, `--grep`, `--path`,
24
+ `--pattern`): no lookaround or backreferences, and linear time on any
25
+ output.
26
+ - **MCP tool problems** (no deck, unknown proc) come back as tool errors
27
+ (`isError`) rather than `{error}` values; read-only tools are annotated as
28
+ such.
29
+ - The global `--log-level` and `--completions` flags are gone; `procdeck
30
+ completion <shell>` prints completions.
31
+
32
+ ### Minor Changes
33
+
34
+ - `envFile` (one path or a list) layers dotenv files under every proc's `env`
35
+ and every preflight. The files are read at each spawn, so a refreshed `.env`
36
+ reaches a proc on its next restart — no deck restart, no
37
+ `node --env-file` wrapper.
38
+ - `procdeck logs <proc> -f` follows a proc's output (it used to follow only
39
+ `--self`).
40
+ - A detached deck's own log rotates past 4 MB instead of growing forever.
41
+
42
+ ### Patch Changes
43
+
44
+ - The HTTP observer forwards standard proxy headers: `x-forwarded-host` carries
45
+ the original Host (an outer proxy's value wins), so frameworks that CSRF-check
46
+ Origin against it — Next.js Server Actions — accept mutating requests;
47
+ `x-forwarded-proto` and `x-forwarded-for` are set too. A client abort cancels
48
+ the upstream request, and an upstream dying mid-body cuts the client
49
+ connection instead of hanging it or appending an error note.
50
+ - A relative `cwd` resolves against the config's directory, also for
51
+ `up --fg` from a subdirectory.
52
+ - A `\r\n` split across two reads of a process's output no longer loses the
53
+ line.
54
+ - Start/stop/restart of an unknown proc answers 404 with a message, not 500.
55
+ - A proc's `cmd` is looked up in the proc's own `PATH`, and `PROCDECK_DETACHED`
56
+ no longer leaks into proc environments.
57
+ - A preflight that times out is killed with its whole process group.
58
+ - Port detection runs one `ps` and one `lsof` per poll for the whole deck,
59
+ instead of a pair per proc.
60
+
61
+ ## 1.1.1
62
+
63
+ ### Patch Changes
64
+
65
+ - c1a0400: HTTP observer forwards standard proxy headers and propagates connection failures faithfully:
66
+
67
+ - `x-forwarded-host` now carries the original Host (an outer proxy's value wins), so frameworks that CSRF-check Origin against the forwarded host — Next.js Server Actions — no longer reject mutating requests. `x-forwarded-proto` and `x-forwarded-for` are set too.
68
+ - A client abort (closed tab, cancelled fetch) now destroys the upstream request instead of letting it stream to completion unseen.
69
+ - An upstream dying mid-body truncates the client response by cutting the connection, instead of hanging the client or corrupting the payload with an appended error note.
70
+
71
+ ## 1.1.0
72
+
73
+ ### Minor Changes
74
+
75
+ - dace5bb: A proc can pin its assigned `${port}` to a fixed public number: `port: 8787`
76
+ on the spec. The public side stays exactly that number — dotenv files, mobile
77
+ simulators and teammates' scripts keep their hardcoded `localhost:8787` —
78
+ while an observed proc still binds a hidden internal port behind the HTTP
79
+ observer, so the traffic gets captured with no wiring changes anywhere.
80
+ Conflicting pins (duplicate, on the UI's port, or on a proc that never uses
81
+ `${port}`) are config errors; a pin whose port is already taken parks just
82
+ that proc in `blocked` — naming the port and the likely holder — while the
83
+ rest of the deck runs, and Start retries the bind. A pinned proc with no
84
+ `url` also gets its UI link derived from the pin.
85
+
86
+ ## 1.0.0
87
+
88
+ ### Major Changes
89
+
90
+ - 2364ad0: procdeck 1.0.0. Nothing breaks in this release — the version says the surface
91
+ is settled and will not move under you without a major bump.
92
+
93
+ What 1.0 promises to keep stable:
94
+
95
+ - **The config**, both formats: every field of the schema (and therefore
96
+ `schema.json`), the `${port}` / `${port:id}` templating, `needs` /
97
+ `readyWhen` readiness, `preflight`, `alerts`, `observe`, and the
98
+ `defineConfig` export.
99
+ - **The CLI**: the verbs (`up`, `down`, `restart`, `status`, `ls`, `open`,
100
+ `init`, `logs`, `mark`, `wait-for`, `errors`, `http`, `agents`, `mcp`),
101
+ their flags, and the shape of every `--json` payload. `wait-for` keeps exit
102
+ 2 for a timeout.
103
+ - **The MCP tools**: names and parameters of `deck_status`, `get_logs`,
104
+ `get_http`, `get_errors`, `set_mark`, `wait_for`, `timeline`, and the
105
+ `--mutations` trio.
106
+ - **The addresses**: `<id>.localhost:<ui-port>` for every proc, the UI on
107
+ 4820 by default, loopback-only unless `host` says otherwise.
108
+
109
+ Internals stay internal: the deck's HTTP API, the registry files under
110
+ `~/.procdeck/`, the SSE event shapes and everything under `src/` are free to
111
+ change.
112
+
113
+ The readme is now the pitch and the docs live in `docs/` — config reference,
114
+ the agent harness, the traffic observer and the architecture notes.
115
+
116
+ ### Minor Changes
117
+
118
+ - 6ef989d: `procdeck restart --all` restarts every deck on this machine — stop, then detach again
119
+ from each deck's own registry entry (foreground decks are skipped). The version a deck
120
+ actually runs now shows in `status`, `ls` and the UI's deck switcher, and `status`/`up`
121
+ say so out loud when it differs from the CLI — the answer to "did my update reach this
122
+ deck?".
123
+
124
+ ## 0.5.0
125
+
126
+ ### Minor Changes
127
+
128
+ - 10b557f: procdeck is now a harness for coding agents, not just a dashboard for humans.
129
+ New CLI verbs, all bounded and `--json`-able: `status --json` grows an
130
+ `attention` list (crashed / blocked / alerting procs with reasons — the
131
+ cheapest first question); `logs [proc]` returns pane output as plain
132
+ timestamped lines (ANSI stripped, `\r` progress bars keep only their final
133
+ state), filterable with `--grep`, `--since`, `--lines` — no proc means every
134
+ proc interleaved with `[id]` prefixes, and the old daemon-log behaviour moved
135
+ to `logs --self [-f]`; `mark [name]` drops a named marker in every proc's
136
+ stream and `--since-mark` shows only what happened after it — the verify
137
+ loop (mark → edit → restart → check) in four commands; `wait-for <proc>
138
+ [--pattern RE]` blocks until a listening port or a matching line, failing
139
+ fast with the log tail if the proc crashes instead (exit 2 on timeout);
140
+ `errors [proc]` parses stack traces out of recent output and deduplicates
141
+ them by signature ("same TypeError, 41×, last 3s ago"); `restart <proc>`
142
+ restarts a single process. `procdeck mcp` serves the same verbs over MCP
143
+ (stdio) — `claude mcp add procdeck -- procdeck mcp` once, globally, and the
144
+ instance registry finds the right deck per project; read-only by default,
145
+ `--mutations` adds restart/stop/start, plus `since_last` cursors and a
146
+ `timeline` tool. `procdeck agents` (and `procdeck init`) plant the discovery:
147
+ a `## procdeck` section in CLAUDE.md / AGENTS.md and a Claude Code skill
148
+ teaching the loop.
149
+ - 10b557f: procdeck sees the traffic now, not just the logs. Procs that use `${port}`
150
+ get an HTTP observer interposed on their assigned port: the proc binds a
151
+ hidden internal port, procdeck listens on the public one and forwards — so
152
+ requests between processes (`${port:api}`) and into them are captured
153
+ transparently, statuses and bodies included, with zero app changes
154
+ (`"observe": false` opts a proc out; the `*.localhost` proxy captures for
155
+ opted-out procs). WebSocket connections are captured per-message with
156
+ direction and text — compression is stripped at the handshake so frames stay
157
+ readable. Bodies are text-only and truncated (16 KB); `authorization`,
158
+ `cookie` and friends are redacted before anything is stored. Three surfaces
159
+ over the same per-proc rings: `procdeck http [proc] [--status 5xx|422|error]
160
+ [--path RE] [--since-mark] [--ws] [--body] [--digest] [--json]` — `--digest`
161
+ groups 4xx/5xx by route with path params collapsed (`/users/:id`); a
162
+ `get_http` MCP tool with `since_last` cursors (and `timeline` now carries
163
+ the window's exchanges); and a traffic view in the UI — the ⇄ position of
164
+ the layout switch — with kind/proc/errors filters, click-to-expand bodies,
165
+ pause and clear. Marks span both streams, so mark → act →
166
+ `http --since-mark` shows exactly which requests a change caused and what
167
+ they returned.
168
+
169
+ ## 0.4.0
170
+
171
+ ### Minor Changes
172
+
173
+ - 8e4b627: procdeck runs in the background now. `procdeck up` (and bare `procdeck`) starts the
174
+ deck detached, opens the UI and returns — no terminal tab kept hostage; `up --fg` is
175
+ the old foreground mode. New commands, all working from anywhere inside the project:
176
+ `down` (terminates every process tree), `restart`, `status`, `ls` (every running deck
177
+ on the machine), `open` and `logs [-f]`. Running decks register in
178
+ `~/.procdeck/instances/` (stale entries pruned by pid; `PROCDECK_HOME` relocates it);
179
+ a detached deck's own output goes to `~/.procdeck/logs/`. `up` refuses a port already
180
+ held by another deck — naming it — or simply busy, before anything spawns; a bad
181
+ config is reported in the terminal, not in a log file. In the UI: ⏻ shuts the deck
182
+ down (with a confirm), the page says so instead of "reconnecting" and revives itself
183
+ when `procdeck up` runs again; the deck name in the bar lists the other running decks
184
+ as links. The CLI moved to `effect/unstable/cli` — `--help` per command, shell
185
+ completions via `--completions`.
186
+ - f2abc61: Three things for the first real release. **Loopback only:** the server binds
187
+ `127.0.0.1` by default — the UI types into real terminals, so it is not something to
188
+ put on the LAN by accident; `"host": "0.0.0.0"` in the config opens it up for
189
+ devcontainers and VMs. **Per-proc backlog:** each proc keeps its last 256 KB of output
190
+ and a new tab gets every pane's history plus a `synced` marker before live events — a
191
+ chatty ticker can no longer evict a quiet server's startup lines, a deck that has run
192
+ for days still opens with every pane populated, the UI knows exactly which chunks are
193
+ news, and a reconnect replays into freshly reset panes instead of appending history to
194
+ itself. **`procdeck init`:** writes a first `procdeck.config.json` from what is already there —
195
+ a Procfile, workspace packages with `dev` scripts (via the package manager your lockfile
196
+ points at), plain `backend/` + `frontend/` subdirectories (each its own package.json or
197
+ a Django / Go / Rust / Rails / compose project, with `cwd` set), or the root itself.
198
+
199
+ ### Patch Changes
200
+
201
+ - 9f944e5: The deck tells you when it needs you. Procs that crashed, are blocked on a preflight,
202
+ carry an alert or have unread error lines count into the tab title (`(2) garage ·
203
+ procdeck`) and put a red dot on the favicon — visible from the tab strip and the Dock.
204
+ A bell in the global bar turns on system notifications: a crash, a block or a new alert
205
+ while the tab is hidden or the window unfocused shows one (click brings the deck back);
206
+ replayed history on reconnect never notifies. The bell state persists with the UI state;
207
+ the browser permission is asked for on the first click.
208
+ - 1db7f78: Grid pinning. Pin a proc (📌 in its pane header or sidebar row, ⌥P on the active one) and
209
+ the grid shows only pinned procs; the rest collapse into a tray strip under the tiles —
210
+ status dot, id, badges — where a click peeks at one and the pin puts it back. Nothing
211
+ pinned = everyone tiled, as before. ⌥Z zooms the active tile in and out of single. The
212
+ grid now sizes its columns from the tile count (near-square, at most 4) so the deck fits
213
+ the screen when it can and scrolls only when tiles would drop under 180 px. Pins persist
214
+ with the rest of the UI state.
215
+ - e90a08c: Polish before publishing, part one.
216
+
217
+ - URLs in pane output are clickable (`Local: http://localhost:5173/` from every dev
218
+ server opens in a new tab).
219
+ - Exit status reads like a human wrote it: `exit 1 · 2m ago`, `killed (SIGTERM) · 5s ago`
220
+ — signal names instead of numbers, and no more `signal 0` on a plain non-zero exit.
221
+ Running procs that were respawned show a restart count (`↻3`), so crash loops are
222
+ visible from the status line. The sidebar shows the same exit summary where uptime sits
223
+ while running.
224
+ - Grid tile headers keep the `*.localhost` address whole instead of clipping it to `:61`:
225
+ compact tiles show only the primary address (raw ports in its tooltip) and the status
226
+ text is what gives way first.
227
+ - The assigned port no longer also counts as "internal" when it lands in the ephemeral
228
+ range.
229
+
230
+ - a85d537: Light theme. A System · Light · Dark switch in the global bar; System follows the OS
231
+ (`prefers-color-scheme`) and tracks it live. The terminals switch palette too — light gets
232
+ its own ANSI set (GitHub Light), since xterm's defaults are unreadable on white. The choice
233
+ is stored with the rest of the UI state and painted before the first frame, so there is
234
+ no flash on reload.
235
+ - 512e814: The UI remembers itself across reloads, and says when it has lost the server.
236
+
237
+ Layout (single/grid) and the selected pane are kept in localStorage — per origin, so per
238
+ deck — and restored on the next load; a stored pane that is no longer in the config falls
239
+ back to the first one. While the event stream is down (a `procdeck restart`, a killed
240
+ server) a "reconnecting" banner sits over the panes instead of the UI silently showing
241
+ stale state; when the stream is back the proc snapshot is refetched so statuses that
242
+ changed in the meantime catch up. A stream the browser gave up on (server answered with
243
+ something other than an event stream) is retried every 2 s.
244
+
245
+ ## 0.3.0
246
+
247
+ ### Minor Changes
248
+
249
+ - a1ced2e: Cut the install from 116 MB to 1.8 MB, and remove every reason for it to fail.
250
+
251
+ `node-pty` is replaced by `@lydell/node-pty` — the same upstream sources and the same API,
252
+ but the binaries ship as per-platform optional dependencies instead of one tarball carrying
253
+ every platform's prebuilds. Upstream runs an install script and has no Linux prebuild at
254
+ all, so Linux users needed a C++ toolchain and pnpm ≥ 10 / Bun users needed
255
+ `pnpm approve-builds` (or `trustedDependencies`) on every platform or spawning failed at
256
+ runtime. The replacement runs no install script and compiles nothing, anywhere — which also
257
+ retires the startup hack that repaired the darwin `spawn-helper` execute bit.
258
+
259
+ `effect` is no longer installed either: it is bundled into the CLI, where tree-shaking takes
260
+ it from 48 MB on disk to under 1 MB of shipped code. The package's public entry point
261
+ (`defineConfig` and the config types) is now a standalone module with no effect types in its
262
+ declarations, so a `procdeck.config.ts` typechecks against a package that has none of
263
+ procdeck's own dependencies installed.
264
+
265
+ ## 0.2.0
266
+
267
+ ### Minor Changes
268
+
269
+ - 212de8d: Accept `procdeck.config.json` next to the TypeScript config, validated by the same schema.
270
+ A JSON deck needs nothing from the project's toolchain — no TypeScript, and procdeck itself
271
+ does not have to be a dependency, so `npx procdeck` works in any repo. Point `$schema` at
272
+ `https://unpkg.com/procdeck/schema.json` (generated from the Effect schema at build time and
273
+ shipped with the package) for completion and validation in the editor.
274
+
275
+ Started without an argument, the CLI now looks for `procdeck.config.json`, `.ts`, `.js` and
276
+ `.mjs` in that order, and reports a missing or unreadable config against the file instead of
277
+ crashing. `port` is validated as an integer in 1–65535.
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env node
2
+ "use strict"
3
+
4
+ // procdeck's npm entry. The binary for this machine ships as an optional
5
+ // dependency — @procdeck/<os>-<arch> — so the package manager installs only
6
+ // the one that fits, with no install scripts. This launcher finds it and runs
7
+ // it with the same arguments, terminal and exit code.
8
+
9
+ const { spawn } = require("node:child_process")
10
+
11
+ const supported = ["darwin-arm64", "darwin-x64", "linux-arm64", "linux-x64"]
12
+ const target = `${process.platform}-${process.arch}`
13
+
14
+ const fail = (message) => {
15
+ console.error(`procdeck: ${message}`)
16
+ process.exit(1)
17
+ }
18
+
19
+ const binary = () => {
20
+ // A binary built from source, for trying a change through this launcher.
21
+ if (process.env.PROCDECK_BINARY) return process.env.PROCDECK_BINARY
22
+ if (!supported.includes(target)) {
23
+ fail(`no binary for ${target} — supported: ${supported.join(", ")}`)
24
+ }
25
+ try {
26
+ return require.resolve(`@procdeck/${target}/bin/procdeck`)
27
+ } catch {
28
+ fail(
29
+ `@procdeck/${target} is missing — it carries the procdeck binary for this machine. ` +
30
+ "Reinstall without --no-optional / --omit=optional."
31
+ )
32
+ }
33
+ }
34
+
35
+ const child = spawn(binary(), process.argv.slice(2), { stdio: "inherit" })
36
+
37
+ // Pass signals on rather than dying of them: the binary decides how to stop
38
+ // (a deck tears its processes down first). A Ctrl-C reaches the binary from
39
+ // the terminal as well; it reads a repeat within a moment as the same press.
40
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
41
+ process.on(signal, () => child.kill(signal))
42
+ }
43
+
44
+ child.on("error", (cause) => fail(cause.message))
45
+ child.on("exit", (code, signal) => {
46
+ if (signal === null) process.exit(code ?? 1)
47
+ // Die of the same signal, so the caller sees what the binary saw.
48
+ process.removeAllListeners(signal)
49
+ process.kill(process.pid, signal)
50
+ })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "procdeck",
3
- "version": "1.1.1",
4
- "description": "Interactive dev-process multiplexer with a web UI: terminal panes in a browser tab, declarative dependencies, assigned ports and a *.localhost reverse proxy.",
3
+ "version": "2.0.0",
4
+ "description": "Dev-process multiplexer with a web UI: terminal panes in a browser tab, declarative dependencies, assigned ports, a *.localhost proxy and captured HTTP traffic. One native binary.",
5
5
  "keywords": [
6
6
  "cli",
7
7
  "dev-server",
@@ -22,56 +22,23 @@
22
22
  "repository": {
23
23
  "type": "git",
24
24
  "url": "https://github.com/kondaurovDev/procdeck",
25
- "directory": "packages/procdeck"
25
+ "directory": "npm/procdeck"
26
26
  },
27
27
  "bin": {
28
- "procdeck": "./dist/cli.js"
28
+ "procdeck": "bin/procdeck.js"
29
29
  },
30
30
  "files": [
31
- "dist",
31
+ "bin",
32
32
  "schema.json",
33
- "ui/dist"
33
+ "CHANGELOG.md"
34
34
  ],
35
- "type": "module",
36
- "exports": {
37
- ".": {
38
- "types": "./dist/public.d.ts",
39
- "import": "./dist/public.js"
40
- }
41
- },
42
- "publishConfig": {
43
- "access": "public"
44
- },
45
- "dependencies": {
46
- "@lydell/node-pty": "1.2.0-beta.15"
47
- },
48
- "devDependencies": {
49
- "@effect/platform-browser": "4.0.0-beta.106",
50
- "@effect/platform-node-shared": "4.0.0-beta.106",
51
- "@types/node": "^22.10.1",
52
- "@xterm/addon-fit": "^0.11.0",
53
- "@xterm/addon-search": "^0.16.0",
54
- "@xterm/addon-web-links": "^0.12.0",
55
- "@xterm/xterm": "^6.0.0",
56
- "effect": "4.0.0-beta.106",
57
- "foldkit": "^0.141.2",
58
- "tsup": "^8.5.1",
59
- "typescript": "^7.0.2",
60
- "vite": "^6.2.0",
61
- "vitest": "^3.2.4"
62
- },
63
35
  "engines": {
64
- "node": ">=22"
36
+ "node": ">=18"
65
37
  },
66
- "scripts": {
67
- "ui:dev": "vite ui",
68
- "build": "pnpm run build:meta && pnpm run build:schema && pnpm run build:ui && pnpm run build:js && pnpm run build:types",
69
- "build:meta": "cp ../../readme.md ../../license .",
70
- "build:schema": "node scripts/gen-schema.ts",
71
- "build:ui": "vite build ui",
72
- "build:js": "tsup",
73
- "build:types": "tsc -p tsconfig.build.json",
74
- "check:types": "tsc --noEmit && tsc -p ui --noEmit",
75
- "test": "vitest run"
38
+ "optionalDependencies": {
39
+ "@procdeck/linux-arm64": "2.0.0",
40
+ "@procdeck/linux-x64": "2.0.0",
41
+ "@procdeck/darwin-x64": "2.0.0",
42
+ "@procdeck/darwin-arm64": "2.0.0"
76
43
  }
77
- }
44
+ }
package/readme.md CHANGED
@@ -7,7 +7,7 @@ Run your whole dev stack with one command — and actually see what it's doing.
7
7
 
8
8
  ![The example stack in procdeck: six processes tiled, every pane a live terminal, every service on its own *.localhost address, the flaky one flagged](https://raw.githubusercontent.com/kondaurovDev/procdeck/main/docs/screenshot.webp)
9
9
 
10
- procdeck is four tools in one ~2 MB package — the process runner, the port
10
+ procdeck is four tools in one binary — the process runner, the port
11
11
  allocator, the log viewer and the network tab of your dev environment:
12
12
 
13
13
  - **Runs everything.** Every proc is a real terminal in a browser tab — and
@@ -28,20 +28,29 @@ npx procdeck # starts the deck in the background and opens the UI
28
28
  ```
29
29
 
30
30
  The UI opens at <http://localhost:4820> and your terminal is free again.
31
- `procdeck down` stops everything. Requires **Node ≥ 22**, macOS or Linux.
31
+ `procdeck down` stops everything. macOS or Linux.
32
32
 
33
- Prefer it in the project (and you do, if you want the config in TypeScript):
33
+ ## Install
34
+
35
+ procdeck is a single native binary with the web UI inside — nothing else to
36
+ install, no runtime to match. Pick the channel that fits:
34
37
 
35
38
  ```sh
36
- pnpm add -D procdeck # npm i -D procdeck · bun add -d procdeck
39
+ brew install kondaurovDev/tap/procdeck # macOS, with shell completions
40
+ curl -fsSL https://raw.githubusercontent.com/kondaurovDev/procdeck/main/install.sh | sh
41
+ pnpm add -D procdeck # npm i -D procdeck · bun add -d procdeck — pins the version for the whole team
42
+ go install github.com/kondaurovDev/procdeck@latest
37
43
  ```
38
44
 
39
- > **Install footprint.** ~2 MB, one dependency. The server ships as a bundle,
40
- > so nothing but the PTY bindings is installed — and those are
41
- > [`@lydell/node-pty`](https://github.com/lydell/node-pty): the same sources as
42
- > [node-pty](https://github.com/microsoft/node-pty), as per-platform packages.
43
- > Nothing compiles and no install script runs, so there is no
44
- > `pnpm approve-builds` detour and no compiler needed on Linux.
45
+ or a tarball, `.deb` or `.rpm` for your platform from the
46
+ [releases](https://github.com/kondaurovDev/procdeck/releases). On Windows,
47
+ install inside WSL.
48
+
49
+ > **What npm installs.** A small launcher, plus exactly one
50
+ > `@procdeck/<os>-<arch>` package with the binary for your machine — picked by
51
+ > the package manager through `optionalDependencies`. No install script runs,
52
+ > so there is no `pnpm approve-builds` detour and nothing compiles. Node runs
53
+ > the launcher; the deck itself does not need it.
45
54
 
46
55
  ## What you get
47
56
 
@@ -157,31 +166,37 @@ for a devcontainer or a VM. No telemetry, no service worker.
157
166
  }
158
167
  ```
159
168
 
160
- JSON needs nothing from your toolchain — no TypeScript, and procdeck does not
161
- have to be a dependency. TypeScript configs buy comments and computed values:
169
+ Comments and trailing commas are welcome — name the file
170
+ `procdeck.config.jsonc` if your editor wants a hint. Unknown keys are errors,
171
+ so a typo never silently does nothing. `"envFile": ".env"` hands every proc the
172
+ variables of a dotenv file. Full field reference:
173
+ [docs/config.md](https://github.com/kondaurovDev/procdeck/blob/main/docs/config.md).
174
+
175
+ ## Upgrading from 1.x
162
176
 
163
- ```ts
164
- import { defineConfig } from "procdeck"
177
+ 2.0 is the same tool rewritten in Go — the CLI verbs, their flags and `--json`
178
+ shapes, the MCP tools and the addresses stay. What changes:
165
179
 
166
- export default defineConfig({
167
- procs: [{ id: "api", shell: "pnpm dev", env: { PORT: "${port}" } }]
168
- })
169
- ```
180
+ - **Configs are JSON.** A `procdeck.config.ts` becomes `procdeck.config.jsonc`:
181
+ quote the keys, drop the `import` and `defineConfig(…)`, keep the comments.
182
+ - **Regexes are RE2** (Go's): no lookaround or backreferences.
183
+ - **Unknown config keys are errors.**
184
+ - **No `node --env-file` wrapper** needed — use `envFile` in the config.
170
185
 
171
- Both formats validate against the same schema. Full field reference:
172
- [docs/config.md](https://github.com/kondaurovDev/procdeck/blob/main/docs/config.md).
186
+ A 1.x deck and the 2.0 CLI understand each other (same registry, same API), so
187
+ `procdeck restart` moves a running deck over.
173
188
 
174
189
  ## Try the example
175
190
 
176
- In a clone of this repo:
191
+ In a clone of this repo, with Go ≥ 1.26 and pnpm:
177
192
 
178
193
  ```sh
179
194
  pnpm install
180
- pnpm dev # builds the UI, starts the example stack in the foreground
195
+ pnpm dev # builds the UI, embeds it, runs the example stack on the Go procdeck
181
196
  ```
182
197
 
183
- Then open <http://localhost:4820> for the panes, and
184
- <http://web.localhost:4820> / <http://api.localhost:4820> — the example's
198
+ Then open <http://localhost:4840> for the panes, and
199
+ <http://web.localhost:4840> / <http://api.localhost:4840> — the example's
185
200
  servers found each other, and their own ports, entirely through `${port}`
186
201
  templates. See [`example/`](https://github.com/kondaurovDev/procdeck/tree/main/example).
187
202
 
@@ -197,7 +212,7 @@ templates. See [`example/`](https://github.com/kondaurovDev/procdeck/tree/main/e
197
212
 
198
213
  ## Status
199
214
 
200
- **macOS and Linux.** Port discovery asks the OS through `pgrep` + `lsof`, and
215
+ **macOS and Linux.** Port discovery asks the OS through `ps` + `lsof`, and
201
216
  a whole-tree restart signals the process group (`kill(-pid)`) — both POSIX.
202
217
  Windows works through WSL, not natively.
203
218