Replace the Python CLI with a Node CLI, add a systemd service command

The app is already 100% Node, so the Python launcher was pure overhead - it
existed mainly to bootstrap Node, which is circular. The CLI is now merged
into app/ (the single published npm package): `triggershell start` validates
the config and imports server.ts directly in-process, so server.ts's own
SIGTERM/SIGINT handling just works with no signal-relay/child-process layer
needed. `dev` is dropped from the public CLI (contributors use `pnpm --dir
app dev` directly); there's no `build` command either, since the package
ships a prebuilt `.next` via a `prepack` hook. Adds `triggershell service
install|uninstall|status` for running as a per-user or system systemd unit.

Also fixes two bugs found while wiring this up: server.ts resolved `.next`
relative to `process.cwd()`, which broke once the CLI could run from a
directory other than the app itself; and an explicitly-`files`-listed
package directory bypasses .npmignore for its subpaths, so `.next/cache`
was inflating the npm tarball to ~670MB (now stripped in `prepack`, ~7MB).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 11:03:25 +02:00
co-authored by Claude Sonnet 5
parent e2b6c6102c
commit 30350d80f4
40 changed files with 1154 additions and 1071 deletions
+6 -1
View File
@@ -1,5 +1,7 @@
import "./src/bootstrap/async-local-storage-polyfill";
import { createServer } from "node:http";
import path from "node:path";
import { fileURLToPath } from "node:url";
import next from "next";
import { WebSocketServer } from "ws";
import { getConfig } from "./src/lib/config/load";
@@ -19,7 +21,10 @@ migrateOnBoot();
syncAuthFromConfig();
reconcileOrphanedRuns();
const app = next({ dev, hostname, port });
// `dir` must be this file's own directory, not `process.cwd()` - when launched by the installed
// `triggershell` CLI, the working directory is wherever the user's config lives, not the package.
const dir = path.dirname(fileURLToPath(import.meta.url));
const app = next({ dev, dir, hostname, port });
const handle = app.getRequestHandler();
app.prepare().then(() => {