LATdx keeps a daemon warm and a per-workspace cache on disk so your second test run skips the multi-second cold-load the first one paid.
This page explains what the daemon and the ~/.latdx/ caches do, how they’re scoped per workspace, and how to inspect or clean them.
Why the Daemon Exists
Org-mode test runs need a loaded org context: schema, package metadata, and a warm Salesforce connection. Cold-loading takes several seconds. The daemon keeps it in memory and serves repeated latdx test run calls over a local socket, so the second and Nth runs in the same workspace skip the cold path entirely.
| Scenario | Daemon used? | Notes |
|---|---|---|
test run org-mode (--class-names, --tests, or no input) | Yes | CLI auto-spawns the daemon if not running and reuses it for streaming progress events. |
test run file/dir-mode (--file or --dir) | No | Runs in-process through LatdxCore. No socket, no spawn. |
| Daemon connection fails after spawn | Fallback | CLI logs a warning and falls back to direct in-process execution so the test run still completes. |
The daemon does not auto-shut-down on idle. It runs until you stop it explicitly, kill the process, or reboot. Each git worktree gets its own daemon and cache namespace, so daemons are scoped to the workspace they were spawned from.
Per-Workspace Isolation
Switching branches via git switch reuses the same workspace; running multiple branches in parallel via git worktree add gives each one a fully isolated daemon, socket, and cache.
The workspace identity is <sanitized-basename>-<8-char-sha256>, derived from the absolute path of the worktree root (or process.cwd() outside a git repo). Symlinks are resolved before hashing, so /tmp/foo and /private/tmp/foo collapse to the same identity.
LATDX_WORKSPACE_ID and LATDX_WORKSPACE_ROOT are set automatically when the daemon spawns; they exist so the child process rebuilds the same identity without re-walking the filesystem. Do not set them manually.
Cache Layout
- config.json
- update-check.json
- daemon.pid
- daemon.sock
- daemon.endpoint
- daemon.log
| Path | Purpose |
|---|---|
config.json | User-global config (release channel). |
update-check.json | Upgrade-check cache, refreshed at most hourly. |
runner-access/<orgId>.json | Per-org permset grant cache (see Auth & Org Targeting). |
workspaces/<id>/daemon.pid | Running daemon PID. |
workspaces/<id>/daemon.sock | Unix socket (POSIX). |
workspaces/<id>/daemon.endpoint | Sidecar pointing to the actual endpoint when sock path is too long. |
workspaces/<id>/daemon.log | Daemon stdout/stderr. |
workspaces/<id>/cache/ | Per-workspace data cache (Apex source snapshots, deployed-source hash, etc). |
workspaces/<id>/tmp/ | Per-workspace temp dir. |
On Windows the IPC endpoint is a named pipe (\\.\pipe\latdx-daemon-<user-hash>-<workspace-hash>) instead of a Unix socket. On macOS, very long socket paths fall back to $TMPDIR/latdx-<hash>.sock because of the 104-byte sun_path limit; the actual path is recorded in daemon.endpoint.
Earlier builds wrote the cache and daemon files directly under ~/.latdx/ (~/.latdx/cache/, ~/.latdx/daemon.{sock,pid,log}). Clean up any that remain with latdx cache clear --legacy.
Inspecting the Daemon
latdx daemon status # current workspace
latdx daemon status --all-workspaces # every workspace on the machine
latdx daemon status --in-flight # snapshot active phases (stuck or slow?)The status output includes the PID and the IPC endpoint. If the daemon is not running, the status command says so without spawning anything.
The --in-flight flag connects to the running daemon and prints the currently-open PhaseLogger frames with elapsed times, useful for answering “is the daemon stuck or slow?” without a restart. Only frames opened inside the daemon process itself are visible; if the work runs in a child process the daemon spawned, that process’s stack is not reported.
tail -f ~/.latdx/workspaces/<id>/daemon.log
tail -f ~/.latdx/workspaces/<id>/logs/latdx-daemon-*.ndjsonThe plain-text daemon.log captures startup, RPC traffic at the configured log level, and crash output. The NDJSON sibling under logs/ carries the same records in structured form (one JSON object per line) so tools like jq can filter them. Opt out of the NDJSON sink with LATDX_DAEMON_LOG_FILE=off. When diagnosing a stuck daemon, run with -vv and watch either file; daemon-side log levels are inherited from the spawning CLI invocation.
Restarting or Stopping the Daemon
latdx daemon stop # SIGTERM the current workspace daemon
latdx daemon stop --all-workspaces # all workspaces
latdx daemon restart # stop; next test run respawnslatdx cache clear --daemon does the same as latdx daemon stop for the current workspace, and is convenient when you also want to clear other state in one command.
The daemon will respawn the next time you run latdx test run in org mode. There is no manual latdx daemon start; spawning is implicit.
Cleaning Caches
latdx cache clear mutates on-disk state for the current workspace (or every workspace with --all-workspaces). Running tests after a clear pays the cold-load cost again. Do not use during an in-flight test run.
latdx cache status # space + entries for the current workspace
latdx cache status --all-workspaces # every workspace
latdx cache clear # workspace data cache only
latdx cache clear --daemon # kill the workspace daemon (no cache delete)
latdx cache clear --temp # only ~/.latdx/workspaces/<id>/tmp + os.tmpdir() artifacts
latdx cache clear --all # cache + daemon + temp for current workspace
latdx cache clear --all-workspaces # cache for every workspace
latdx cache clear --legacy # remove earlier-build ~/.latdx/cache + daemon.* files
latdx cache clear -q # suppress per-step output (useful in scripts)User-global state (config.json, update-check.json) is never touched by latdx cache clear, regardless of flags. Remove it manually if you want a full reset:
rm -rf ~/.latdx # nukes everything: config, caches, daemons, runner-accessTemp Files & Logs
Per-run temp directories live under os.tmpdir() (/tmp on Linux/macOS, $TEMP on Windows). They’re named latdx_temp_* or latdx-org-source, and are deleted automatically when the run finishes.
To keep them around for debugging:
| Variable | Effect |
|---|---|
LATDX_KEEP_TEMP_FILES=true | Skip cleanup of per-run temp directories. |
LATDX_KEEP_SF_LOGS=true | Skip deletion of Apex debug logs after the run completes. |
Use them when filing a support ticket or inspecting a hard-to-reproduce failure, then unset to avoid filling disk.
LATDX_DEBUG Namespace Patterns
LATDX_DEBUG selectively enables internal trace channels on stderr. For the full value syntax (boolean form, subtree wildcards, exclusions), see LATDX_DEBUG namespace patterns in the CLI reference.
Useful channels to start with:
cli:upgrade, version check / install flow.daemon:ipc, RPC traffic between CLI and daemon.core:cache, per-workspace cache reads/writes.core:org, org context loading and schema queries.
Troubleshooting
| Symptom | First step |
|---|---|
| Test runs hang on “connecting to daemon…” | latdx daemon status; if running, latdx daemon restart. Inspect daemon.log if it persists. |
EADDRINUSE / stale socket after a crash | latdx cache clear --daemon (removes the stale socket and PID). |
Disk filling up under ~/.latdx/workspaces/ | latdx cache status --all-workspaces to see culprits, then latdx cache clear --all-workspaces. |
| Behavior differs across two worktrees on the same branch | Each worktree has its own daemon; restart the misbehaving one (cd <worktree> && latdx daemon restart). |
Stray ~/.latdx/cache or daemon.* files from an earlier build | latdx cache clear --legacy. |
For symptom-keyed troubleshooting beyond the daemon, see Troubleshooting.