Skip to content

feat: headless execute, session baseDir, env injection, and run command#32

Merged
jesse23 merged 11 commits into
mainfrom
feat/execute-error-handling
Jun 21, 2026
Merged

feat: headless execute, session baseDir, env injection, and run command#32
jesse23 merged 11 commits into
mainfrom
feat/execute-error-handling

Conversation

@jesse23

@jesse23 jesse23 commented Jun 21, 2026

Copy link
Copy Markdown
Owner

Summary

Four new features building on the existing POST /s/:id/execute endpoint, each with a full ADR:

  • Execute resilience (ADR 027): server never crashes on a bad agent tool call — child.on('error') handler, done flag, and uncaughtException/unhandledRejection guards; structured { exit, error, code } exit line so agents can distinguish spawn failure from command failure without parsing stderr
  • Session base directory (ADR 028): POST /api/sessions accepts baseDir (absolute path); PTY shell and headless execute commands both start in that directory; CLI webtty go [id] --dir <path> resolves and forwards it
  • Env injection (ADR 030): env field in ~/.config/webtty/config.json (same contract as ~/.claude/settings.json) — merged over process.env and injected into both PTY shells and execute commands; TERM/COLORTERM always win for PTY spawns
  • webtty run command (ADR 029): webtty run <id> starts the server + session + PTY via transient WebSocket — no browser; webtty run <id> <cmd> [args...] drives POST /s/:id/execute directly from the terminal, streaming stdout/stderr and forwarding exit code

Also includes:

  • Spec + ADR renames: server.pipe.mdheadless-execute.md, 026.server.pipe.md026.server.headless-execute.md
  • bun run dev script for running from source without a build step

Test plan

  • bun test — 229 pass, 0 fail
  • webtty run myproject — starts server + session + PTY, prints URL, no browser opens
  • webtty run myproject echo hello — streams "hello" to stdout, exits 0
  • webtty run myproject __no_such_cmd__ — prints ENOENT error, exits 1
  • webtty go myproject --dir /tmp — PTY shell starts in /tmp
  • POST /api/sessions with invalid baseDir — returns 400
  • env: { "GITLAB_HOST": "..." } in config — var present in PTY shell and execute commands

🤖 Generated with Claude Code

jesse23 and others added 7 commits June 20, 2026 08:45
`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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 baseDir to sessions and ensure PTY + execute spawns run with cwd: session.baseDir.
  • Add config.env and inject it into PTY spawns and POST /s/:id/execute.
  • Add execute resilience (child.on('error'), done flag, server-level rejection guards) and new CLI webtty 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.

Comment thread src/server/routes.ts
Comment thread src/cli/commands.ts
Comment thread docs/specs/webtty.md Outdated
Comment thread docs/specs/config.md Outdated
Comment thread docs/specs/cli.md Outdated
jesse23 and others added 3 commits June 21, 2026 10:13
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>
@jesse23 jesse23 merged commit b388c77 into main Jun 21, 2026
3 checks passed
@jesse23 jesse23 deleted the feat/execute-error-handling branch June 21, 2026 14:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants