Commit Graph
13 Commits
Author SHA1 Message Date
valknarandClaude Sonnet 5 e779c5a93b Use the header's Terminal icon as the app favicon
Replaces the default create-next-app favicon.ico with an icon.svg
matching lucide-react's Terminal glyph (same one used in the header)
exactly, on a dark rounded-square backdrop so it stays legible at
16x16 in the browser tab regardless of the OS/browser chrome theme.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 21:01:13 +02:00
valknarandClaude Sonnet 5 acc6715a88 Allow timeoutSeconds: 0 to mean no timeout
Previously every script was forced to have a positive timeout capped
at 24h, with no way to run something genuinely unbounded. execa only
enforces its timeout option when it's greater than 0, so this just
relaxes the schema's lower bound from positive to >= 0 and lets that
flow through unchanged - no engine logic needed beyond a clarifying
comment. The 1800s default and 86400s cap for finite timeouts are
unchanged; 0 is an explicit opt-in, not the default.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 20:57:24 +02:00
valknarandClaude Sonnet 5 97bb6cc092 Add per-page titles
Root layout now defines a title template (%s · TriggerShell) so every
page just sets its own short title instead of repeating the brand
name. Static titles for the dashboard, login, and run history pages;
dynamic generateMetadata for the script and run detail pages, since
those need the script/run name which isn't known until the route
params resolve.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 20:52:11 +02:00
valknarandClaude Sonnet 5 7daaa95ab9 Hide the Next.js dev-mode route indicator badge
Sets devIndicators: false in next.config.ts. Compile/runtime error
overlays are unaffected - only the floating route-info badge is hidden.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 20:45:46 +02:00
valknarandClaude Sonnet 5 6d7788e48b Keep the TriggerShell wordmark visible on mobile
Only the icon-only nav links, username, and logout label needed to
collapse to fit a phone-width header - the brand text alone doesn't
push it over, so keep it always shown for identity.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 20:40:37 +02:00
valknarandClaude Sonnet 5 88f561230e Fix header horizontal overflow on mobile
The nav bar's brand text, both nav-link labels, the username, and the
logout label were all always rendered, easily exceeding a phone-width
viewport since nothing could shrink or wrap. Collapse to icon-only
below the sm breakpoint (labels stay in the DOM via sr-only so they're
still announced to screen readers, just not painted) and truncate a
long username instead of letting it force overflow.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 20:36:55 +02:00
valknarandClaude Sonnet 5 7269886f9e Render run output with xterm.js instead of plain text
Replaces the plain-text output <div> with a real xterm.js terminal
(@xterm/xterm + @xterm/addon-fit), so ANSI color/control codes from
scripts render as actual colors instead of raw escape characters.
stderr chunks are wrapped in ANSI red so failures stand out even from
tools that don't colorize their own output. Also sets FORCE_COLOR=1/
CLICOLOR_FORCE=1 as env defaults (real/script env still wins) since
scripts run without a real TTY and most tools auto-disable color
without one of these overrides.

Fixed a React Strict Mode bug found while testing: the initial log was
written to the terminal via a "write once" ref flag in the parent,
but Strict Mode's dev-only mount->cleanup->remount cycle creates a
fresh Terminal on the real mount, so that flag silently skipped
writing to the surviving instance - the terminal looked completely
blank until live output arrived. Fixed by writing initialData inside
the same effect that creates the Terminal, so it's correct by
construction regardless of how many times the effect runs.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 20:29:03 +02:00
valknarandClaude Sonnet 5 20989987f6 Suppress hydration-warning noise from browser-extension DOM tweaks on body
cz-shortcut-listen is ColorZilla's own marker attribute, injected into
<body> client-side before React hydrates - not an app bug. This only
silences mismatches on body's own attributes, not its children, so a
real hydration bug elsewhere would still surface normally.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 19:49:08 +02:00
valknarandClaude Sonnet 5 9dc45f751a Delegate non-/ws/runs upgrade requests to Next instead of dropping them
Our upgrade handler on the shared httpServer was destroying every socket
that wasn't for /ws/runs, which silently killed Next's own dev-mode HMR
websocket (/_next/hmr) too - breaking hot reload with no useful error,
just a failed WebSocket connection in the browser console. Delegate to
app.getUpgradeHandler() instead, which must be called after prepare().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 19:46:41 +02:00
valknarandClaude Sonnet 5 d3e3360d6e Remove deprecated url.parse() usage from the custom server
Node flags legacy url.parse() (DEP0169) as having security implications
and recommends the WHATWG URL API instead. The main request handler's
parsedUrl argument to Next's handle() is optional and unused by us, so
that call is dropped entirely (matching Next's own minimal custom-server
example); the WS upgrade path-check now uses `new URL()` instead.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 19:41:37 +02:00
valknarandClaude Sonnet 5 466458a664 Point repo URLs at dev.pivoine.art
Replace the placeholder GitHub URL in the scaffolded config template
with the project's real repo, and add matching Repository/repository
metadata to pyproject.toml and app/package.json.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 19:34:54 +02:00
valknarandClaude Sonnet 5 80c11d3bd3 Externalize auth secrets to .env and rename default config to triggershell.yml
sessionSecret was previously baked directly into the scaffolded config file;
`triggershell init` now generates a .env with TRIGGERSHELL_SESSION_SECRET
instead and references it via ${VAR} interpolation, keeping the actual
secret out of the (often committed) config file. `triggershell dev/start/
validate` load that .env automatically without overriding real env vars.

Also renames the default config filename from triggershell.config.yaml to
triggershell.yml throughout the CLI, app, docs, and examples.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 19:15:03 +02:00
valknarandClaude Sonnet 5 ced99a8e75 Initial implementation of TriggerShell
A Python CLI (typer) that bootstraps Node/pnpm and launches a Next.js 16 web
app for running configured shell scripts: YAML config validated by a shared
Zod schema, dynamic per-script forms mapped to shadcn controls, argv-safe
execa execution with live WebSocket streaming, SQLite/Drizzle run history,
and optional argon2 session + API token auth.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 18:37:30 +02:00