phux file locations reference
Where phux keeps its files: the socket under $XDG_RUNTIME_DIR (or /tmp), config under $XDG_CONFIG_HOME, and logs, TLS material, and pairing tokens under...
Full source summary
Where phux keeps its files: the socket under $XDG_RUNTIME_DIR (or /tmp), config under $XDG_CONFIG_HOME, and logs, TLS material, and pairing tokens under $XDG_STATE_HOME. Runtime and state paths carry the active profile, so a development build never shares them with an installed one. Each rule is pinned to the resolving function by a unit test, so the page moves when the code does.
phux splits its files across the three XDG base directories: config (hand-written, follows you between machines), runtime (expected to disappear on reboot), and state (survives across runs but is not config). Paths below are symbolic; each rule names its fallback when the environment variable is unset.
Profiles
Every runtime and state path carries the active profile, so a development build cannot touch the installed build’s socket, sessions, or logs (ADR-0080). The profile is $PHUX_PROFILE when set; otherwise dev for a binary that is not an installed release (a debug build, or one under a Cargo target/ directory); otherwise default.
The default profile is unsuffixed — phux — so paths created by earlier releases stay valid. Any other profile suffixes the directory name: phux-dev, phux-<name>. Below, <profile-dir> means phux or phux-<profile> accordingly. phux doctor reports the resolved profile.
Socket
The Unix domain socket every consumer dials and the server binds:
$PHUX_SOCKETif set (an explicit--socketflag still overrides it);$XDG_RUNTIME_DIR/<profile-dir>/phux.sockifXDG_RUNTIME_DIRis set;/tmp/phux-<user>[-<profile>]/phux.sockotherwise.
The parent directory is created mode 0700. Its sibling spawn.lock serialises auto-spawn so concurrent invocations elect one server rather than racing to bind.
A socket file whose server has died is stale, not a server: liveness is established by connecting, never by the file existing. A stale entry is removed and a server started, so an uncleanly killed server cannot wedge later invocations.
Config
$XDG_CONFIG_HOME/phux/config.toml, falling back to ~/.config/phux/config.toml when XDG_CONFIG_HOME is unset. A missing config file is not an error (the embedded defaults apply); there is no global config-path flag — set XDG_CONFIG_HOME to isolate configuration for a test or an alternate environment. phux config path prints the resolved path.
State
The state directory is $XDG_STATE_HOME/<profile-dir>, falling back to ~/.local/state/<profile-dir> when XDG_STATE_HOME is unset or empty:
$XDG_STATE_HOME/<profile-dir>/
├── server.log # the ONE server log, both spawn paths
├── server.log.1..4 # older generations, rotated while live
├── server-starts.log # one line per server start (crash-loop check)
├── client-<pid>.log # per-pid interactive-client log
├── onboarding.json # versioned first-use journey progress
├── onboarding.lock # serializes first-use moment delivery
├── remote-cert.pem # auto-provisioned remote-consumer certificate
├── remote-key.pem # its private key (owner-only, 0600)
└── remote-tokens # structured credential store (owner-only, 0600)
server.logis the canonical server log regardless of how the server was started: the auto-spawn path redirects the daemon’s stderr here, and the service unit points its log capture at the same file.phux logsandphux service logsread it;PHUX_LOGtees the server’s structured log to an additional file without moving this one. Whenever it exceeds 8 MiB it is rolled aside toserver.log.1(older generations shifting to.2,.3,.4, oldest dropped), checked at server start and again periodically for as long as the server runs — so one very long-lived server is bounded the same as many short-lived ones. Rotation truncates the live file in place rather than replacing it, so atail -for the OS-redirected stdio a service-managed server writes through keeps working across it.server-starts.logrecords<epoch> <pid> <version>per server start.phux doctorcounts recent entries to report a crash-loop, and compares the newest version against the running binary’s to detect an upgrade the server has not picked up.client-<pid>.logis where an interactive client writes its trace — the TUI owns the alt screen, so the client never logs to stderr.PHUX_LOGredirects it. Log files are created mode0600.onboarding.jsonrecords only the versioned first-use journey stage.onboarding.lockserializes delivery within that profile. State is best-effort: missing state starts the guidance, while unreadable, unknown, or unwritable state stays quiet and never prevents attach.remote-cert.pem/remote-key.pemare the self-signed TLS pair auto-provisioned for remote consumers (ADR-0031);PHUX_WS_TLS_CERT/PHUX_WS_TLS_KEYsubstitute an operator-supplied pair. A complete pair is never regenerated, so the pinned fingerprint stays stable — which also means its subjectAltName set is fixed at generation (ADR-0091);phux doctorreports whether it names the address phux advertises.remote-tokensis the versioned verifier-only credential store the server reads andphux pair,phux pair rotate, andphux pair revokeupdate under the sibling.remote-tokens.lock. Writers first lock the owner-controlled, non-group/world-writable parent directory, then no-follow open and validate the owner-only regular lock file, preventing lock-path replacement from splitting concurrent writers. Store commits use a synced temporary file and atomic rename. The store must be a regular, non-symlink file owned by the effective user with no group/world permissions; an integrity failure denies authentication.PHUX_WS_TOKENSmoves it without weakening those checks. Legacy anonymous token lines require the idempotentphux pair --migrate-legacyconversion.
Design intent (not yet implemented)
A server.pid file and a journal/ directory of per-pane PTY output for crash recovery remain design intent; neither path exists today. Workspace archives are written only where phux workspace save is pointed.
phux exit codes reference
The canonical exit-code table: 0 success, 1 failure, 2 usage error or server refusal, 3 partial-fleet unanswerable, 124 wait timeout, 125 run timeout.
phux deprecations reference
Deprecated spellings the current binary still accepts, each pinned with its replacement and lifecycle releases; empty when nothing is currently deprecated.