Configuration

Commands & Hooks

Define named commands for uxd run, give them their own cwd and env, and attach the four lifecycle hooks.

Named commands

Anything under [commands] becomes a run target.

~/.uxd/my-project.toml
[commands.dev]
run = "pnpm dev"
cwd = "packages/app"

[commands.dev.env]
NODE_OPTIONS = "--max-old-space-size=8192"

[commands.test]
run = "pnpm test"
uxd my-project 42 run dev
uxd my-project 42 run test -- --watch
KeyTypeMeaning
runstringrequired — the command, templated, executed through a shell
cwdstringOptional, relative to the worktree root
envtableOptional, merged over the project's [env] for this command only

Arguments after -- are appended to run, so run test -- --watch executes pnpm test --watch.

If you name a command after a built-in verb — list, sync, info — the built-in takes precedence and your command becomes unreachable. uxd doctor warns about the shadowing.

default_command

default_command = "dev"

makes uxd my-project 42 behave like uxd my-project 42 run dev. It accepts either a verb or a configured command name.

Hooks

Four lifecycle hooks, all optional, all templated, each executed as bash -c "<script>" with the worktree as the working directory and the full UXD_* environment.

~/.uxd/my-project.toml
[hooks]
post_checkout = "echo 'workspace ready: {path}'"
pre_run = "docker compose up -d"
post_sync = "pnpm install --frozen-lockfile"
pre_clean = "docker compose down"
HookFiresIf it exits non-zero
post_checkoutAfter a workspace is materializedFails the command — E_SETUP, exit 6
pre_runBefore run, exec or shell executesFails the command — E_SETUP, exit 6
post_syncAfter sync resets the worktreeWarns and continues
pre_cleanBefore a workspace is removedWarns and skips that removal
Keep hooks fast and idempotent. post_checkout runs on every fresh workspace and pre_run runs on every single run, exec and shell.

pre_clean is the place to release resources a workspace acquired — stop a container, drop a scratch database — since after clean the directory is gone. Because a failing pre_clean skips the removal, it also works as a veto:

warning: pre_clean hook failed for feat-login — skipping

Under --dry-run, hooks are printed as the bash -c line that would run, and nothing executes.

Ordering

For a uxd my-project 42 run dev on a fresh ref:

  1. Resolve the ref, create the worktree.
  2. post_checkout
  3. [setup] — seed files, then run if the cache_key hash changed.
  4. pre_run
  5. commands.dev.run

Preview steps 3–5 without executing them:

uxd my-project 42 run dev --dry-run