feat: headless execute, session baseDir, env injection, and run command#32
Merged
Conversation
`webtty run <id>` starts the server, creates the session if needed, and triggers PTY spawn via a transient WebSocket connection — no browser. `webtty run <id> <cmd> [args...]` is the renamed headless exec mode. Removes 'run' from GO_ALIASES so it no longer aliases `go`. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds multiple “headless + session-scoped execution” capabilities to webtty by extending session creation to carry a working directory, injecting config-defined environment variables into spawned processes, hardening the execute endpoint against spawn failures, and introducing a webtty run CLI for browserless operation.
Changes:
- Add
baseDirto sessions and ensure PTY + execute spawns run withcwd: session.baseDir. - Add
config.envand inject it into PTY spawns andPOST /s/:id/execute. - Add execute resilience (
child.on('error'),doneflag, server-level rejection guards) and new CLIwebtty run.
Reviewed changes
Copilot reviewed 22 out of 22 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/server/websocket.ts | Pass session.baseDir and config.env into PTY spawn. |
| src/server/session.ts | Store baseDir on sessions and include it in session JSON. |
| src/server/routes.ts | Accept/validate baseDir on session creation; inject env + cwd for execute; add spawn error handling. |
| src/server/routes.test.ts | Add coverage for execute spawn failure (ENOENT) emitting structured exit line. |
| src/server/index.ts | Add process-level error guards and catch unhandled route promise rejections. |
| src/pty/node.ts | Thread cwd and injected env into node-pty spawn. |
| src/pty/index.ts | Extend spawnForSession to accept cwd and injected env. |
| src/pty/index.test.ts | Update spawnForSession tests for new parameters. |
| src/pty/bun.ts | Thread cwd and injected env into Bun spawn. |
| src/config.ts | Add env to config schema, defaults, and parsing/validation. |
| src/cli/index.ts | Add run command; add global --dir parsing; adjust go aliases. |
| src/cli/commands.ts | Implement cmdRun (warm-up PTY via WS, or headless execute streaming). |
| package.json | Point webtty script to source entry for dev; add webtty:prod for dist CLI. |
| docs/specs/webtty.md | Document baseDir on session creation. |
| docs/specs/headless-execute.md | Update ADR link + mark execute and resilience items. |
| docs/specs/config.md | Document env injection feature. |
| docs/specs/cli.md | Document webtty run feature. |
| docs/adrs/030.config.env-inject.md | ADR for config-based environment injection. |
| docs/adrs/029.cli.exec.md | ADR for new webtty run command behavior. |
| docs/adrs/028.session.base-dir.md | ADR for session baseDir plumbing and validation. |
| docs/adrs/027.server.execute-resilience.md | ADR for execute hardening + structured spawn-failure exit line. |
| docs/adrs/026.server.headless-execute.md | Update spec link after spec rename. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Switch warm-up WebSocket from ws package to Bun's native global WebSocket (browser-style API) so it can be mocked in unit tests. Add 13 new unit tests covering all exec-mode and warm-up-mode paths in cmdRun (lines 221-316 were previously uncovered). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Validate baseDir is a directory (not just that it exists) — fixes silent runtime failure when a file path is passed to POST /api/sessions - Treat unexpected stream EOF as failure (exit 1) instead of silent success — fixes scripts misreading a mid-stream crash as success - Mark session baseDir, env injection, and webtty run as done in specs Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Four new features building on the existing
POST /s/:id/executeendpoint, each with a full ADR:child.on('error')handler,doneflag, anduncaughtException/unhandledRejectionguards; structured{ exit, error, code }exit line so agents can distinguish spawn failure from command failure without parsing stderrPOST /api/sessionsacceptsbaseDir(absolute path); PTY shell and headless execute commands both start in that directory; CLIwebtty go [id] --dir <path>resolves and forwards itenvfield in~/.config/webtty/config.json(same contract as~/.claude/settings.json) — merged overprocess.envand injected into both PTY shells and execute commands;TERM/COLORTERMalways win for PTY spawnswebtty runcommand (ADR 029):webtty run <id>starts the server + session + PTY via transient WebSocket — no browser;webtty run <id> <cmd> [args...]drivesPOST /s/:id/executedirectly from the terminal, streaming stdout/stderr and forwarding exit codeAlso includes:
server.pipe.md→headless-execute.md,026.server.pipe.md→026.server.headless-execute.mdbun run devscript for running from source without a build stepTest plan
bun test— 229 pass, 0 failwebtty run myproject— starts server + session + PTY, prints URL, no browser openswebtty run myproject echo hello— streams "hello" to stdout, exits 0webtty run myproject __no_such_cmd__— prints ENOENT error, exits 1webtty go myproject --dir /tmp— PTY shell starts in/tmpPOST /api/sessionswith invalidbaseDir— returns 400env: { "GITLAB_HOST": "..." }in config — var present in PTY shell and execute commands🤖 Generated with Claude Code