Quick Start
By the end of this page you will have a configured project, a materialized workspace, a command running inside it, and a clean machine again. It takes about ten minutes.
You need uxd installed and a git
repository you can clone.
Scaffold your first project
uxd setup creates the config directory (~/.uxd by default), sets a base
root for repos and worktrees, and writes your first project file. On a
terminal it prompts for each field; every prompt is also a flag, so the same
command runs unattended.
uxd setup
uxd setup --name my-project --repo git@github.com:my-org/my-project.git --yes
Not sure what it will write? --dry-run prints the plan and changes nothing:
uxd setup --name my-project --repo git@github.com:my-org/my-project.git --dry-run --yes
mkdir -p ~/.uxd
write ~/.uxd/defaults.toml
root = "~/dev/uxd"
write ~/.uxd/my-project.toml
repo = "git@github.com:my-org/my-project.git"
Teach the project how to run
setup writes the minimum. Open the project file and add the two things uxd
needs to make a workspace runnable — how to install dependencies, and what your
commands are:
uxd config edit my-project
repo = "git@github.com:my-org/my-project.git"
editor = "code"
[setup]
run = "pnpm install --frozen-lockfile"
cache_key = ["pnpm-lock.yaml"]
[env]
PORT = "{port}"
[commands.dev]
run = "pnpm dev"
{port} is a template variable.
Each workspace gets its own port, so two dev servers never collide.
repo_path and worktrees_path are left out on purpose — they default to
{root}/{project}/repo and {root}/{project}/trees. See
Configuration.Check your environment
doctor inspects your tools, your config directory, and every project you have
configured. Run it before you trust a setup:
uxd doctor
OK git version: git 2.50.1
OK gh (github cli): authenticated
OK config dir: ~/.uxd
OK state dir: ~/.local/state/uxd
OK project my-project: config: schema-valid
OK project my-project: repo: bare repo at ~/dev/uxd/my-project/repo
OK project my-project: fetch refspec: remote.origin.fetch configured
doctor exits non-zero if any check fails, so it works in CI. To validate only
the config files, use uxd config validate.
Materialize a workspace
Now the pipeline. Pick any ref — a branch name, a PR number, a full commit SHA:
uxd my-project feat/login checkout
→ cloning git@github.com:my-org/my-project.git (bare, partial)
→ fetching origin/feat/login
→ worktree ready: ~/dev/uxd/my-project/trees/feat-login
~/dev/uxd/my-project/trees/feat-login
The first run clones once. Every later ref reuses that bare repo, so the second workspace is fast.
checkout prints the worktree path on stdout and nothing else, which makes it
the scriptable primitive:
cd "$(uxd my-project feat/login checkout)"
Do something in it
run materializes the workspace, executes [setup], then runs a configured
command inside the worktree:
uxd my-project feat/login run dev
→ worktree ready (reused)
→ running setup
...
listening on 3053
Other ways to act on the same workspace:
uxd my-project feat/login code # open it in your editor
uxd my-project feat/login shell # interactive shell, uxd env exported
uxd my-project feat/login exec -- git log --oneline -2
uxd my-project feat/login diff --stat
See what you have
uxd my-project list
SLUG KIND BRANCH STATUS PORT AGE LAST USED
feat-login branch feat/login clean 3053 0m 0m
On a terminal, a bare uxd my-project turns that list into a picker and prints
the chosen path — so cd "$(uxd my-project)" walks you into a workspace.
Clean up
uxd my-project clean --all --yes
→ plan:
feat-login (clean, 16 KB)
feat-login
→ freed 16 KB
clean prints its plan and asks for confirmation first; --yes skips the
prompt. In day-to-day use you will reach for the filters instead —
--merged, --closed, --older-than 7d. See
cleaning up workspaces.
Where to go next
- Review a pull request — the workflow
uxdwas built for. - How it works — what "materialize" actually does.
- Refs — every ref form and how it is resolved.