v2.26.0: Automatic proxy hostnames and oneshot daemons
The reverse proxy now gives every project daemon a stable hostname without registering a slug, oneshot = true turns a daemon into a run-to-completion task that dependents wait for, and the supervisor no longer mistakes a recycled pid for a live supervisor after a reboot.
Added
-
Automatic proxy hostnames for projects and worktrees (#880) — @jdx. With the proxy enabled, any project daemon that has a
portis reachable at<daemon>.<project>.<tld>, and the same daemon in a linked git worktree at<daemon>.<worktree>.<project>.<tld>, so two projects with anapidaemon no longer collide and no slug is required. URLs stay stable when port bumping moves the daemon, and requests can still auto-start a stopped daemon.# ~/.config/pitchfork/config.toml [settings.proxy] enable = true https = false port = 8088 # myproject/pitchfork.toml [daemons.api] run = "node server.js" port = { expect = [3000], bump = 10 } proxy = "web" # optional: use the label "web" instead of "api"; `proxy = false` opts out
After
pitchfork supervisor start --forceandpitchfork start api, the daemon is served at:api.myproject.localhost:8088 # primary checkout api.fix-login.myproject.localhost:8088 # linked worktree checked out as fix-loginThe project label comes from the primary checkout's namespace or directory name; a worktree's label comes from its directory name or a checkout-local
worktree_label.pitchfork start,list,status, and the web UI display the URLs,list --json/status --jsongain aurlfield (proxy_urlis kept), daemons receivePITCHFORK_URL, and templates can use{{ url }},{{ host }}, and{{ daemons.api.url }}.pitchfork proxy statusgroups hostnames by project and worktree and lists label conflicts; conflicting labels are not routed.Compatibility notes: the proxy remains disabled by default. Existing
[slugs]andpitchfork proxy addkeep working and take precedence over automatic hostnames. Routed daemons now receiveHOST=127.0.0.1for automatic hostnames as well as slugs (except in LAN mode). Automatic hostnames are not written to/etc/hostsor published over mDNS, so use a browser that resolves.localhost, configure DNS for a custom TLD, or use a slug for LAN discovery; custom TLS certificates must cover the project and worktree names (*.localhostalone is not enough). Checkouts that share an explicitnamespacestill share daemon identity, so give them distinct namespaces to run same-named daemons at once. See the port management guide. -
Oneshot daemons: tasks that are ready when they exit 0 (#876) — @jdx. Set
oneshot = trueon a daemon to run migrations, seeds, or other setup to completion before dependents start, replacing themigrate && exec sleep infinityworkaround.[daemons.db] run = "postgres -D ./data" ready_cmd = { run = "pg_isready -h 127.0.0.1", timeout = "30s" } [daemons.migrate] run = "npm run migrate" oneshot = true depends = ["db"] [daemons.api] run = "node server.js" depends = ["migrate"]
pitchfork start apistartsdb, waits for it to be ready, runsmigrate, and startsapionly after it exits 0. A clean exit is recorded with the newcompletedstatus (shown inlist,list --status completed,status,wait, the TUI, and the web UI; JSON output only gains a newstatusvalue). A nonzero exit iserrored, follows the normalretrypolicy, and blocks dependents.ready_*andhealth_*fields are rejected on a oneshot daemon. Explicitstart/restartre-run a completed task (including viadepends), so the command must be safe to repeat; directory entry viaauto = ["start"]leaves completed tasks alone.pitchfork startwaits up tosupervisor.oneshot_timeout(default1h;0waits indefinitely), configurable per project. Regular daemons are unaffected and still reportstoppedon a clean exit. See the oneshot tasks guide. -
general.windows_shellsetting, defaulting tocmd /C(#852) — @JamBalaya56562. On Windows withoutshonPATH(the default Git for Windows install), every daemon failed to start withprogram not foundbecausegeneral.shelldefaulted tosh -ceverywhere. Windows now usesgeneral.windows_shell(PITCHFORK_WINDOWS_SHELL) for daemon spawns,ready_cmd/health_cmdprobes, lifecycle hooks, and the log archive hook. An explicitly setgeneral.shell(config file orPITCHFORK_SHELL) still wins as a cross-platform override, which you need if a sharedpitchfork.tomluses POSIX syntax inrunstrings.
Fixed
-
A stale supervisor pid is no longer trusted after a reboot or pid reuse (#878) — @jdx. If the supervisor died or the machine rebooted and the OS handed its pid to another process, every command failed with
Failed to connect to supervisor,supervisor startdemanded--force, andsupervisor stopsent SIGTERM to the unrelated process (reported in #877). The supervisor's recorded start time and boot time are now checked before the pid is believed: stale records are cleaned up and auto-start proceeds,supervisor start/runreplace them without--force,supervisor status --jsonreportsdown, and any real kill is bound to the recorded process generation (pidfd on Linux, process handle on Windows, start-token re-check elsewhere) so a bare pid is never signalled. -
Proxy slugs and worktree names match case-insensitively (#858) — @jweslley. Hostnames are case-insensitive and browsers lowercase the
Hostheader, but the proxy compared slugs and worktree prefixes exactly, so a worktree directory such asFeature-Asilently served the main checkout instead of the worktree (with a 200). Lookups now fold ASCII case. Slugs or worktree prefixes that differ only by case are ambiguous and are refused rather than guessed:pitchfork proxy statusshows them with statuscollisionand no URL, no/etc/hostsentry is written for them, and a request for a colliding worktree prefix returns an error instead of the wrong checkout.
Changed
- The README, docs site, web UI, favicons, and social previews now share a single devil-and-pitchfork logo (#860) — @jdx.
New Contributors
Full Changelog: v2.25.0...v2.26.0
💚 Sponsor pitchfork
pitchfork is built and maintained by @jdx, an open source developer at entire.io, the title sponsor of his open source work.
If pitchfork has a place in your development workflow, please consider becoming an individual or company sponsor. Your support funds ongoing development and helps keep pitchfork fast, free, and independent.