Worktrees and forks
Create clean upstream PR worktrees while keeping fork-only patches isolated.
Worktrees + forks (hstack)
This repo is designed to run the Happier stack locally, while still making it easy to:
- keep using your fork day-to-day
- create clean upstream PR branches quickly (without carrying fork-only patches)
hstack is monorepo-first: UI/CLI/server all live in the same Happier git repo.
Key idea: keep stable checkouts stable
- Keep a stable checkout at
<workspace>/main(treat as read-only). - Do all development work in
<workspace>/devor worktrees under<workspace>/{pr,local,tmp}/.... - Point stacks at a repo checkout via
HAPPIER_STACK_REPO_DIR.- Managed by
hstack wt use ...andhstack stack wt ....
- Managed by
Workspace layout
Default paths (see hstack where for your actual values):
- Stable checkout:
<workspace>/main - Dev checkout:
<workspace>/dev(created byhstack setup --profile=dev) - Worktrees:
- PRs:
<workspace>/pr/... - locals:
<workspace>/local/<owner>/... - tmp:
<workspace>/tmp/<owner>/...
- PRs:
Inside the monorepo:
apps/ui(UI)apps/cli(CLI + daemon)apps/server(server; light/full flavors)
Spec grammar (what you can pass to --repo / wt use)
These tokens/specs are accepted anywhere a “repo/worktree” is expected:
main/default→<workspace>/maindev→<workspace>/devactive→ current active repo (your shell env / env.local)pr/<...>→<workspace>/pr/<...>local/<...>→<workspace>/local/<owner>/<...>(owner is your local username)tmp/<...>→<workspace>/tmp/<owner>/<...>- absolute path to a Happier monorepo checkout/worktree
Examples:
hstack wt use dev
hstack wt use pr/123-fix-thing
hstack stack wt exp1 -- use local/my-feature
hstack stack typecheck exp1 --repo=/abs/path/to/checkoutFork workflow (upstream vs origin)
Conventions:
upstream: the canonical Happier repo (happier-dev/happier)origin: your fork (where you push branches)
The “upstream-first” flow is:
- Create a worktree based on upstream (clean history)
- Push your feature branch to origin
- Open a PR into upstream/dev
Choosing which checkout hstack runs
hstack selects the active repo checkout using:
HAPPIER_STACK_REPO_DIR(absolute path to the monorepo root)
Recommended ways to set it:
# Switch the active checkout for non-stack commands:
hstack wt use dev
# Switch the repo for a specific stack env:
hstack stack wt exp1 -- use devOne-shot overrides (does not edit any env files):
hstack stack typecheck exp1 --repo=pr/123-fix-thing
hstack stack build exp1 --repo=/absolute/path/to/checkoutCreating worktrees (wt new)
Create a new worktree (defaults to local category, based on upstream):
hstack wt new local/my-feature --useThrowaway worktree:
hstack wt new tmp/scratch --usePush the active worktree branch to your fork:
hstack wt push active --remote=originNotes:
--from=upstream|origincontrols which remote is used as the base.- The default base branch is
dev(configurable viaHAPPIER_STACK_DEV_BRANCH).
Testing a GitHub PR locally (wt pr)
Create a worktree at the PR head ref:
hstack wt pr https://github.com/happier-dev/happier/pull/123 --use
# or just the PR number (remote defaults to upstream)
hstack wt pr 123 --useUpdate when the PR changes:
hstack wt pr 123 --update --stashNotes:
--updatefails closed if the PR was force-pushed and the update is not a fast-forward; re-run with--force.--stashkeeps your uncommitted changes safe during updates.
Testing a PR inside a stack (recommended)
Prefer hstack stack pr for maintainable PR stacks:
hstack stack pr pr123 --repo=123 --dev --reuseWorkflow helpers
wt status
hstack wt status active
hstack wt status devwt list
hstack wt listThis includes main/, dev/, and any categorized worktrees under pr/, local/, tmp/.
wt sync / wt sync-all
Sync remote refs into local mirror branches (useful before creating new worktrees):
hstack wt sync --remote=upstream
hstack wt sync-all --remote=upstreamwt update
Update a worktree from its base (fails closed on conflicts unless you opt into --force):
hstack wt update pr/123-fix-thing
hstack wt update pr/123-fix-thing --stash
hstack wt update pr/123-fix-thing --forceStash behavior:
--stash: auto-stash then pop back if the update was clean--stash-keep: auto-stash but keep it (you apply it manually later)
wt update-all
hstack wt update-allDry-run:
hstack wt update-all --dry-runwt git
Run git in a resolved worktree:
hstack wt git pr/123-fix-thing -- status
hstack wt git dev -- checkout -b feature/foowt shell
Open a “real” interactive shell in a worktree:
hstack wt shell devEditors (wt code / wt cursor)
hstack wt cursor dev
hstack wt code pr/123-fix-thingwt duplicate
Duplicate a worktree (useful for “same base, different experiment”):
hstack wt duplicate active tmp/try-alt --usewt archive
Archive and remove a worktree directory (and optionally delete the branch):
hstack wt archive pr/123-fix-thing --dry-run
hstack wt archive pr/123-fix-thingUse --detach-stacks to unpin stacks that were pointing at that worktree.
Interactive and JSON modes
Most commands support:
--interactive/-i(TTY-only wizards where supported)--json(machine-readable output)
Examples:
hstack wt use --interactive
hstack wt pr 123 --json
hstack wt list --jsonSwitching server flavor (light vs full)
Choose which backend flavor a stack runs with:
hstack srv status
hstack srv use happier-server-light
hstack srv use happier-server
hstack srv use --interactiveNotes:
- This selects a runtime flavor (light/full). It does not select a different git repo.
- Both flavors come from the same monorepo server code (
apps/server).
Fork setup (contributors)
For contributor workflows, hstack expects:
upstream→ the canonical repo you PR intoorigin→ your fork (where you push branches)
If you run hstack setup --profile=dev and origin still points to upstream (and you can’t push there), setup will guide you to configure a fork URL for origin.
Non-interactive option:
export HAPPIER_STACK_FORK_URL="https://github.com/<you>/happier.git"
hstack setup --profile=devOnce configured, a common PR flow is:
hstack wt new local/my-feature --from=upstream --use
hstack wt push active --remote=originIf you prefer working in the long-lived dev/ checkout, use hstack contrib extract to create feature branches cleanly. See /docs/hstack/development.