Skip to content

v2.12.0: Live startup logs and worktree-aware proxy routing

Choose a tag to compare

@mise-en-dev mise-en-dev released this 27 May 19:39
· 54 commits to main since this release
Immutable release. Only release title and notes can be modified.
04f4f74

Pitchfork v2.12.0 makes starting daemons feel alive — logs stream into the terminal as each daemon boots and a spinner shows what the supervisor is waiting on — and teaches the proxy to understand git worktrees and jj workspaces so parallel branches each get their own subdomain.

Added

  • Live startup logs in the CLI (#444) — @gaojunran. pitchfork start, restart, and run now render a per-daemon progress job with a spinner that names the active ready check (e.g. "waiting for HTTP ...", "waiting for TCP port 5432...", "waiting for output matching '...'") and stream the daemon's log lines into the terminal as it boots, finishing with a green check and the resolved port. Set general.startup_log_timestamps = true (or PITCHFORK_STARTUP_LOG_TIMESTAMPS=1) to prefix each line with a timestamp instead of the default dim bullet — handy for spotting slow startup phases.

  • Worktree- and workspace-aware proxy routing (#448) — @gaojunran. When a slug points at a project directory, pitchfork now auto-discovers git worktrees (via git worktree list) and jj workspaces (via jj workspace list) under it. Each worktree gets its own URL prefix derived from the branch / workspace name:

    myapp                  → myapp.localhost           (main checkout)
    myapp-feature-a        → feature-a.myapp.localhost (worktree on branch feature-a)
    myapp-fix/auth         → fix-auth.myapp.localhost  (branch name sanitized for URLs)
    

    Each worktree gets its own namespace (the directory name), so multiple copies can run the same daemon name without conflict, and auto-start picks up the daemon definition from the worktree's own pitchfork.toml. Controlled by proxy.worktree (default true) or PITCHFORK_PROXY_WORKTREE; set to false to disable. Branch / workspace names that sanitize to the same prefix log a warning and only the first one is routed.

Fixed

  • Web UI no longer hangs after viewing logs (#447) — @sargunv-headway. Navigating away from /logs while a daemon was streaming would block the browser indefinitely because the SSE EventSource was never closed. Pitchfork now tracks active log streams and closes them on pagehide, so navigation completes immediately and streams resume cleanly when you come back.

Changed

  • Debounced state-file writes (#446) — @gaojunran. The supervisor previously wrote state.toml to disk on every mutation (active port detected, daemon inserted/removed, shell directory tracked, etc.), which could mean dozens of writes per second during a busy start storm. A new dirty-flag + 1s background flush task batches these into a single write, and serialized content is compared against the last-written copy so unchanged state is a no-op. IPC handlers force-flush before returning so CLI commands still see fresh state, cron last_cron_triggered is still written synchronously to guarantee correctness across crashes, and shutdown drains any pending changes before exiting.

Documentation

  • Daemon groups reference (#451) — @gaojunran. Documents the [groups.*] config introduced in v2.11.0, including how daemons = [...] resolves short names and qualified IDs and how groups merge across config files. Fixes #450.

Full Changelog: v2.11.0...v2.12.0

💚 Sponsor pitchfork

pitchfork is built by @jdx at en.dev — an independent studio shipping developer tools like mise, aube, hk, pitchfork, and more. Development is sustained by sponsorships.

If pitchfork has a place in your dev workflow, please consider sponsoring at en.dev. Individual and company sponsorships are what keep the project healthy and moving forward.