Guides

Script with uxd

Use uxd from shell scripts and CI — the stdout/stderr contract, --json output shapes, and exit codes you can branch on.

uxd is designed to be driven by other programs. Three rules make that safe.

The output contract

Every progress line (→ …), warning (warning: …) and debug line (· …) goes to stderr. Only the result goes to stdout. So $(uxd …) captures the data and nothing else.

checkout prints the workspace path on stdout, which makes this the canonical one-liner:

cd "$(uxd my-project 42 checkout)"

Run it and stderr still shows you what happened:

→ worktree ready (reused)

while stdout — the part that was captured — is just the path.

JSON output

checkout, list, info and projects accept --json.

checkout --json

uxd my-project feat/login checkout --json
{"project":"demo-app","slug":"feat-login","ref":"feat/login","kind":"branch","branch":"feat/login","path":"~/dev/uxd/demo-app/trees/feat-login","ports":[3053],"created":true}

created is false when the workspace already existed — useful for deciding whether to run a first-time seeding step.

list --json

uxd my-project list --json
[{"slug":"feat-login","ref":"feat/login","kind":"branch","branch":"feat/login","path":"~/dev/uxd/demo-app/trees/feat-login","adopted":false,"ports":[3053],"createdAt":"2026-07-25T06:00:28.086Z","lastUsedAt":"2026-07-25T06:00:28.148Z","dirty":false,"missing":false}]

info --json returns one object of the same shape.

projects --json

uxd projects --json
[{"name":"demo-app","repo":"~/dev/uxd/demo-app/origin","workspaces":1,"pathExists":true}]

Exit codes

Branch on the exit code rather than parsing error text.

CodeNameMeaning
0Success
1E_INTERNALUnexpected internal failure
2E_USAGEBad arguments or flags
3E_CONFIGMissing or invalid configuration
4E_RESOLVEThe ref could not be resolved
5E_GITA git or gh operation failed
6E_SETUPA setup step or hook failed

Errors print one line to stderr, plus an optional hint:

error(E_RESOLVE): cannot resolve ref 'does-not-exist'
hint: try a branch, PR number, sha, or a path to adopt

Worked examples

Iterate every workspace:

uxd my-project list --json \
  | jq -r '.[].slug' \
  | while read -r slug; do
      uxd my-project "$slug" exec -- git log -1 --oneline
    done

Fail a CI job when the ref does not exist, but treat "already checked out" as fine:

if ! path=$(uxd my-project "$REF" checkout); then
  status=$?
  [ "$status" -eq 4 ] && echo "unknown ref: $REF" >&2
  exit "$status"
fi
cd "$path"

Only seed when the workspace was newly created:

created=$(uxd my-project "$REF" checkout --json | jq -r '.created')
[ "$created" = "true" ] && ./scripts/seed.sh
--json implies no interactive prompts, but clean still asks for confirmation. Add --yes in any non-interactive context.