Stacks (isolated instances)
Run multiple isolated Happier stacks on one machine (ports + dirs + repo pinning).
Stacks (multiple local Happier instances)
hstack supports running multiple stacks in parallel on the same machine.
A “stack” is just:
- a dedicated server port
- isolated directories for UI build output, CLI home, and logs
- a repo checkout pin (point at a specific worktree/checkout)
- (when using
happier-server) isolated infra (Postgres/Redis/Minio) managed per-stack
Stacks are configured via a plain env file stored under:
~/.happier/stacks/<name>/envCreate a stack
Non-interactive:
hstack stack new exp1 --port=3010 --server=happier-server-lightAuto-pick a port:
hstack stack new exp2Power users: choose a DB provider without extra prompts:
# Light flavor (default): SQLite (no Docker)
hstack stack new exp-light --server=happier-server-light --db-provider=sqlite
# Light flavor (optional): embedded Postgres via PGlite (PG_Light)
hstack stack new exp-pglite --server=happier-server-light --db-provider=pglite
# Full server (default): Postgres (Docker-managed per stack)
hstack stack new exp-full --server=happier-server --db-provider=postgres
# Full server (optional): MySQL (requires an explicit DATABASE_URL; hstack does not provision MySQL)
hstack stack new exp-mysql --server=happier-server --db-provider=mysql --database-url=mysql://user:[email protected]:3306/happierCreate a PR test stack (copy/paste friendly)
If you want maintainers to be able to try your PR quickly, you can give them a single command that:
- creates an isolated stack
- checks out PR(s) into worktrees
- pins those worktrees to the stack
- optionally seeds auth
- optionally starts the stack in dev mode
Example (most common):
hstack stack pr pr123 \
--repo=https://github.com/happier-dev/happier/pull/123 \
--seed-auth --copy-auth-from=dev-auth --link-auth \
--devNotes:
--remote(defaultupstream) controls which Git remote is used to fetchrefs/pull/<n>/head.--seed-authuseshstack stack auth <stack> copy-from <source>under the hood, which also best-effort seeds DB Account rows (avoids FK errors like PrismaP2003).--link-authsymlinks auth files instead of copying them (keeps credentials in sync, but reduces isolation).- For full-server stacks (
happier-server), seeding may require Docker infra to be running. - DB provider flags are forwarded to the underlying
hstack stack newcall:--db-provider=...--database-url=...(full server only)
Auth seeding (recommended: dev-auth)
Create the dev-auth seed stack once, authenticate once, then reuse it when creating new stacks:
hstack auth seedInteractive wizard (TTY only):
hstack stack new --interactiveThe wizard lets you:
- pick the server type (
happier-server-lightorhappier-server) - pick or create a repo worktree for the Happier monorepo
- choose which Git remote to base newly-created worktrees on (defaults to
upstream)
When creating --server=happier-server stacks, hstack will also reserve additional ports and persist
the stack-scoped infra config in the stack env file (so restarts are stable):
HAPPIER_STACK_PG_PORTHAPPIER_STACK_REDIS_PORTHAPPIER_STACK_MINIO_PORTHAPPIER_STACK_MINIO_CONSOLE_PORTDATABASE_URL,REDIS_URL,S3_*
Run a stack
Dev mode (interactive, recommended):
hstack tui stack dev exp1Dev mode (non-interactive / no TUI):
hstack stack dev exp1Dev mode (background):
hstack stack dev exp1 --backgroundProduction-like mode (interactive):
hstack tui stack start exp1Production-like mode (non-interactive / no TUI):
hstack stack start exp1Production-like mode (background):
hstack stack start exp1 --backgroundBuild UI for a stack (server-light serving):
hstack stack build exp1Doctor:
hstack stack doctor exp1Edit a stack (interactive)
To change server flavor, port, or repo worktree for an existing stack:
hstack stack edit exp1 --interactiveSwitch server flavor for a stack
You can change happier-server-light vs happier-server for an existing stack without re-running the full edit wizard:
hstack stack srv exp1 -- status
hstack stack srv exp1 -- use happier-server-light
hstack stack srv exp1 -- use happier-server
hstack stack srv exp1 -- use --interactiveSwitch repo worktree for a stack (stack wt)
If you want the exact same UX as hstack wt, but scoped to a stack env file:
hstack stack wt exp1 -- status
hstack stack wt exp1 -- use pr/my-ui-pr
hstack stack wt exp1 -- use defaultThis updates the stack env file (~/.happier/stacks/<name>/env), not repo env.local (legacy path still supported).
Run the Happier CLI against a specific stack (stack happier)
If you want to run a happier CLI command against a specific stack (instead of whatever your current shell env points at), use:
hstack stack happier exp1 -- status
hstack stack happier exp1 -- daemon statusStack shorthand also works:
hstack exp1 happier statusStack wrappers you can use
These commands run with the stack env file applied:
hstack stack dev <name>hstack stack start <name>hstack stack build <name>hstack stack doctor <name>hstack stack mobile <name>hstack stack eas <name> [subcommand...]hstack stack happier <name> [-- ...]hstack stack srv <name> -- status|use ...hstack stack wt <name> -- <wt args...>hstack stack tailscale:status|enable|disable|url <name>hstack stack service:* <name>
Tip: hstack stack eas <name> env:sync --environment production syncs the stack’s EXPO_* config values into the Expo project’s EAS Environment Variables.
Global/non-stack commands:
hstack setup(recommended; installs shims/runtime and bootstraps the monorepo)- (advanced)
hstack init(plumbing: shims/runtime/pointer env) - (advanced)
hstack bootstrap(clone/install monorepo + deps)
Services (autostart)
Each stack can have its own autostart service (so multiple stacks can start at login).
hstack stack service exp1 install
hstack stack service exp1 status
hstack stack service exp1 restart
hstack stack service exp1 logsImplementation notes:
- Service name/label is stack-scoped:
main→com.happier.stackexp1→com.happier.stack.exp1
- macOS: implemented via launchd LaunchAgents
- Linux: implemented via systemd user services (if available)
- The service persists
HAPPIER_STACK_ENV_FILE, so you can edit the stack env file without reinstalling.
Repo/worktree selection per stack
When creating a stack you can point the stack at a repo worktree:
hstack stack new exp3 \\
--repo=local/my-feature \\
--server=happier-serverWorktree specs are interpreted relative to the workspace:
main -> <workspace>/main
dev -> <workspace>/dev
pr/<...> -> <workspace>/pr/<...>
local/<...> -> <workspace>/local/<owner>/<...>
tmp/<...> -> <workspace>/tmp/<owner>/<...>So --repo=pr/foo maps to:
<workspace>/pr/fooYou can also pass an absolute path.
Stack env + repo env precedence
On startup, hstack loads env in this order:
~/.happier-stack/.env(defaults)~/.happier-stack/env.local(optional global overrides; prefer stack env for persistent config)HAPPIER_STACK_ENV_FILE(stack env; highest precedence)
hstack stack ... sets HAPPIER_STACK_ENV_FILE=~/.happier/stacks/<name>/env and clears any already-exported HAPPIER_STACK_* variables so the stack env stays authoritative.
For a full explanation of the different folders/paths (home vs workspace vs runtime vs stack storage) and the exact env precedence rules, see: /docs/hstack/paths-and-env.
Cloned-repo fallback (before you run hstack init):
<repo>/.env(defaults)<repo>/env.local(optional overrides)HAPPIER_STACK_ENV_FILE(stack env)
Manage per-stack environment variables (including API keys)
To add/update environment variables in a stack env file from the CLI:
hstack stack env <stack> set KEY=VALUE [KEY2=VALUE2...]To remove keys:
hstack stack env <stack> unset KEY [KEY2...]To inspect:
hstack stack env <stack> get KEY
hstack stack env <stack> list
hstack stack env <stack> pathNotes:
- This is the recommended place for provider API keys the daemon needs (example:
OPENAI_API_KEY). - Changes apply on the next start of the stack/daemon. Restart to pick them up:
main:hstack start --restart- named stack:
hstack stack start <stack> -- --restart(orhstack stack dev <stack> -- --restart)
Self-host shortcut (defaults to main when not running under a stack wrapper):
hstack env set OPENAI_API_KEY=sk-...Daemon auth + “no machine” on first run
On a fresh machine (or any new stack), the daemon may need to authenticate before it can register a “machine”.
If the UI shows “no machine” (or the daemon shows auth_required), it usually means the stack-specific CLI home
doesn’t have credentials yet:
~/.happier/stacks/<stack>/cli/access.key
To check / authenticate a stack, run:
hstack stack auth <stack> status
hstack stack auth <stack> loginNotes:
- You can run multiple daemons for the same stack on different accounts using
--identity=<name>.default(no flag):~/.happier/stacks/<stack>/cli/...--identity=account-b:~/.happier/stacks/<stack>/cli-identities/account-b/...
- To authenticate an identity without auto-opening a browser, use
--no-open(it prints the URL so you can open it in the browser profile/incognito window you want):
hstack stack auth <stack> login --identity=account-a --no-open
hstack stack auth <stack> login --identity=account-b --no-open- To start/stop an identity’s daemon explicitly:
hstack stack daemon <stack> start --identity=account-a
hstack stack daemon <stack> stop --identity=account-a- For the main stack, use
<stack>=mainand the default<port>=3005(unless you changed it). - If you use Tailscale Serve,
HAPPIER_WEBAPP_URLshould be your HTTPS URL (what you get fromhstack tailscale url). - Logs live under:
- default identity:
~/.happier/stacks/<stack>/cli/logs/ - named identities:
~/.happier/stacks/<stack>/cli-identities/<identity>/logs/
- default identity:
JSON mode
For programmatic usage:
hstack stack list --json
hstack stack new exp3 --json
hstack stack edit exp3 --interactive --json