Flatten the repo: move everything out of app/ to the root

Now that the CLI and the Next.js app are one package, nesting it inside
app/ served no purpose - the repo root itself becomes the published
npm package. Merges app/.gitignore and app/README.md into the root
versions, drops the now-duplicate app/LICENSE, and updates path
references (README, docs/ARCHITECTURE.md, docs/CONFIG_REFERENCE.md,
package.json's repository.directory) that assumed the app/ nesting.

Also fixes a real bug this surfaced: the in-app docs viewer resolved
docs/ relative to process.cwd(), which only worked by accident when the
CLI happened to be invoked from app/'s parent directory. A first attempt
at fixing it with import.meta.dirname broke instead, for the same
cross-module-graph reason config-path resolution already documented -
Next compiles Route Handlers through a separate module graph that
doesn't preserve source-relative import.meta paths. Fixed by exposing
the app root via TRIGGERSHELL_APP_ROOT (set once in server.ts, where
import.meta *does* resolve correctly), the same pattern already used
for TRIGGERSHELL_CONFIG_PATH.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-16 11:14:01 +02:00
co-authored by Claude Sonnet 5
parent 30350d80f4
commit 3f379ca2ac
123 changed files with 65 additions and 104 deletions
+34
View File
@@ -1,3 +1,36 @@
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# typescript
*.tsbuildinfo
next-env.d.ts
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# vercel
.vercel
# Runtime data (created by `triggershell start` in whatever directory the config lives in)
.triggershell/
@@ -11,5 +44,6 @@
# Editors / OS
.DS_Store
*.pem
.idea/
.vscode/
View File
View File
+12 -10
View File
@@ -34,7 +34,7 @@ Edit `triggershell.yml` to add your own scripts (see [Configuration](#configurat
re-run `triggershell start`.
> The `triggershell` package isn't published to npm yet. Until it is, build and link a local copy
> instead: `pnpm --dir app install && pnpm --dir app build && pnpm --dir app link --global`.
> instead: `pnpm install && pnpm build && pnpm link --global`.
## Requirements
@@ -150,21 +150,23 @@ Full reference with request/response shapes and curl examples: [`docs/API.md`](d
## Development
This is the workflow for working on TriggerShell itself, not for installing/running it — it
bypasses the CLI entirely and talks to `app/`'s own scripts directly, with hot reload:
bypasses the CLI entirely and talks to the app's own scripts directly, with hot reload. The app is
still not meant to be run standalone with `next dev`/`next start`, since it needs the custom server
(`server.ts`) for the WebSocket endpoint — `pnpm dev`/`pnpm start` below cover that:
```bash
pnpm --dir app install
pnpm --dir app dev # tsx watch server.ts - reads TRIGGERSHELL_CONFIG_PATH from the environment
pnpm --dir app lint
pnpm --dir app typecheck
pnpm --dir app test # CLI unit tests (src/cli/**/*.test.ts)
pnpm --dir app db:studio # browse the SQLite DB
pnpm install
pnpm dev # tsx watch server.ts - reads TRIGGERSHELL_CONFIG_PATH from the environment
pnpm lint
pnpm typecheck
pnpm test # CLI unit tests (src/cli/**/*.test.ts)
pnpm db:studio # browse the SQLite DB
```
Repo layout:
Repo layout — the repo root itself is the published npm package (Next.js app + the `triggershell`
CLI in `bin/`/`src/cli/`), alongside:
```
app/ The published npm package: Next.js app + the `triggershell` CLI (bin/, src/cli/) in one
examples/ A runnable example config + scripts
docs/ Config/architecture/API reference docs
```
-41
View File
@@ -1,41 +0,0 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
-21
View File
@@ -1,21 +0,0 @@
MIT License
Copyright (c) 2026 TriggerShell contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
-21
View File
@@ -1,21 +0,0 @@
# TriggerShell web app
This directory is both the Next.js app and the home of the `triggershell` CLI (`bin/triggershell.js`
`src/cli`) that launches it — together they're published as one npm package. The app is still not
meant to be run standalone with `next dev`/`next start`, since it needs a custom server (`server.ts`)
for the WebSocket endpoint; use the CLI (`triggershell start`) or the `pnpm` scripts below instead.
See the [repo root README](../README.md) for how to run TriggerShell end-to-end, and
[`../docs/ARCHITECTURE.md`](../docs/ARCHITECTURE.md) for how this app is put together.
```bash
pnpm install
pnpm dev # tsx watch server.ts - reads TRIGGERSHELL_CONFIG_PATH from the environment
pnpm lint
pnpm typecheck
pnpm test # CLI unit tests (src/cli/**/*.test.ts)
pnpm db:studio # browse the SQLite database
```
Note: this is the contributor workflow for developing TriggerShell itself. End users install and
run the published `triggershell` CLI instead (see the root README).
+4 -4
View File
@@ -1,8 +1,8 @@
# Architecture
```
triggershell (Node CLI, src/cli) app/ (Next.js, all server logic)
─────────────────────────────── ──────────────────────────────
triggershell (Node CLI, src/cli) server.ts + src/ (Next.js, all server logic)
─────────────────────────────── ─────────────────────────────────────────
triggershell start server.ts (custom Node server)
1. resolve + validate the config (loadConfig) ├─ Next.js request handler (pages, API routes)
2. check the port is free ├─ ws.WebSocketServer on /ws/runs
@@ -24,7 +24,7 @@
## Why a custom Node server
Next.js Route Handlers can't host a persistent WebSocket server, so `app/server.ts` wraps Next's
Next.js Route Handlers can't host a persistent WebSocket server, so `server.ts` wraps Next's
request handler in a plain `http.createServer` and attaches a `ws.WebSocketServer` via the
`upgrade` event, scoped to `/ws/runs` with its own auth check (Route Handlers get auth via
`next/headers`'s `cookies()`, which isn't available on a raw `http.IncomingMessage`).
@@ -100,4 +100,4 @@ Every server file that reads the config/DB at request time (`getConfig()`, `getD
`requireAuth()`) sets `export const dynamic = "force-dynamic"`. Without it, `next build` tries to
statically prerender pages like `/` at build time, which fails because there's no config file to
read yet (the config only exists at `triggershell start` runtime, in the user's own project
directory, not `app/`'s).
directory, not the package's).
+1 -1
View File
@@ -10,7 +10,7 @@ present) into its environment - without overriding any variable already set in t
secrets referenced via `${VAR}` don't have to be committed alongside the config. `triggershell
init` scaffolds both files together.
The canonical schema is the Zod schema at `app/src/lib/config/schema.ts` — this document mirrors
The canonical schema is the Zod schema at `src/lib/config/schema.ts` — this document mirrors
it. `triggershell validate` loads and validates the config directly against the schema below (no
separate pre-flight step).
+2 -2
View File
@@ -5,8 +5,7 @@
"type": "module",
"repository": {
"type": "git",
"url": "https://dev.pivoine.art/valknar/triggershell.git",
"directory": "app"
"url": "https://dev.pivoine.art/valknar/triggershell.git"
},
"bin": {
"triggershell": "bin/triggershell.js"
@@ -19,6 +18,7 @@
"src",
"templates",
"drizzle",
"docs",
".next",
"server.ts",
"next.config.ts",
View File
+4
View File
@@ -24,6 +24,10 @@ reconcileOrphanedRuns();
// `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));
// Exposed via `process.env` (not just the local `dir` const) so Route Handlers/Server Components -
// compiled through Next's own module graph, separate from this file's - can find it too. See
// `docs.ts`'s use of this and the `globalThis` comment in `runner/events.ts` for the same reasoning.
process.env.TRIGGERSHELL_APP_ROOT = dir;
const app = next({ dev, dir, hostname, port });
const handle = app.getRequestHandler();

Before

Width:  |  Height:  |  Size: 386 B

After

Width:  |  Height:  |  Size: 386 B

Some files were not shown because too many files have changed in this diff Show More