@happier-dev/stack
v0.2.16
Published
Run [**Happier**](https://cloud.happier.dev) locally and access it remotely and securely (using Tailscale).
Downloads
2,021
Readme
hstack (Happier Stack)
Run Happier locally and access it remotely and securely (using Tailscale).
What is Happier?
Happier is an UI/CLI stack (server + web UI + CLI + daemon) who let you monitor and interact with Claude Code, Codex and Gemini sessions from your mobile, from a web UI and/or from a desktop app.
What is hstack?
hstack is a guided installer + local orchestration CLI for Happier.
If you only want to use Happier and self-host it on your computer, start with the Self-host section below. If you want to develop Happier (worktrees, multiple stacks, upstream PR workflows), see the Development section further down.
Self-host Happier (install + run)
Quickstart
curl -fsSL https://happier.dev/install | bash
happier relay host installLegacy hstack wrapper (optional):
hstack self-host installFollow the guided instructions to install Happier and launch it.
Daily use
Configure provider API keys for the daemon
If you want the daemon to have access to provider API keys (for example OpenAI), you can set them so they are automatically loaded when the daemon starts:
hstack env set OPENAI_API_KEY=sk-...Then restart so the daemon picks up the new environment:
hstack start --restartStart Happier
Starts the local server, CLI daemon, and serves the pre-built UI.
hstack startAuthentication
On a fresh machine, the daemon needs to authenticate once before it can register a “machine”.
hstack auth loginBy default (in a TTY), hstack auth login is local-first: it guides you through authenticating against your local stack UI
instead of the hosted Happier web app. Advanced targeting:
hstack auth login --webapp=auto|stack|expo|public|hosted
hstack auth login --webapp-url=http://localhost:8081
hstack auth login --start-if-neededIf you want a quick diagnosis:
hstack auth statusEnable Tailscale Serve (recommended for mobile/remote)
hstack tailscale enable
hstack tailscale urlMobile access
Make sure Tailscale is installed and running on your phone, then either:
- Open the URL from
hstack tailscale urlon your phone and “Add to Home Screen”, or - [Download the Happier mobile app] (https://cloud.happier.dev) and configure it to use your local server.
Details (secure context, phone instructions, automation knobs): [docs/remote-access.md](docs/remote-access.md).
Development (worktrees, stacks, contributor workflows)
If you want to develop Happier (worktrees, multiple stacks, upstream PR workflows), you can install hstack for development with:
Setup (guided)
npx --yes -p @happier-dev/stack hstack setup-from-source --profile=devDuring setup, you’ll be guided through:
- where to store your workspace (the folder that will contain
main/,dev/,pr/,local/,tmp/) - bootstrapping/cloning the Happier monorepo
- recommended: setting up a dedicated
dev-authseed stack (authenticate once, then new stacks can reuse it) - recommended: creating a dedicated dev stack (keep
mainstable) - optional: installing the iOS dev-client app (for phone testing)
Manual shortcuts (if you want to do it yourself):
# Create the dev-auth seed stack (recommended) and do the guided login now:
hstack auth seed
# Create a dev stack and pin it to the dev checkout:
hstack stack new dev
hstack stack wt dev -- use devYou can also set it non-interactively:
npx --yes -p @happier-dev/stack hstack setup-from-source --profile=dev --workspace-dir=~/Documents/Development/happierWhy this exists
- Automated setup (from source):
hstack setup-from-source+hstack startgets the whole stack up and running. - No hosted dependency: run the full stack on your own computer.
- Lower latency: localhost/LAN is typically much faster than remote hosted servers.
- Custom forks: easily use forks while still contributing upstream to
happier-dev/happier. - Worktrees: clean upstream PR branches without mixing fork-only patches.
- Stacks: run multiple isolated instances in parallel (ports + dirs + repo pinning).
- Remote access:
hstack tailscale ...helps you get an HTTPS URL for mobile/remote devices.
How hstack wires “local” URLs
There are two “URLs” to understand:
- Internal URL: used by local processes on this machine (server/daemon/CLI)
- typically
http://127.0.0.1:<port>
- typically
- Public URL: used by other devices (phone/laptop) and embedded links/QR codes
- recommended:
https://<machine>.<tailnet>.ts.netvia Tailscale Serve
- recommended:
Diagram:
other device (phone/laptop)
|
| HTTPS (secure context)
v
https://<machine>.<tailnet>.ts.net
|
| (tailscale serve)
v
local machine (this repo)
+--------------------------------+
| happier-server-light OR |
| happier-server (via UI gateway) |
| - listens on :PORT |
| - serves UI at / |
+--------------------------------+
^
| internal loopback
|
http://127.0.0.1:<port>
(daemon / CLI)More details + automation: [docs/remote-access.md](docs/remote-access.md).
How it’s organized
- Scripts:
scripts/*.mjs(bootstrap/dev/start/build/stacks/worktrees/service/tailscale/mobile) - Stable checkout:
<workspace>/main(the monorepo clone; treated as read-only) - Dev checkout:
<workspace>/dev(created byhstack setup-from-source --profile=dev) - Worktrees:
- PRs:
<workspace>/pr/... - locals:
<workspace>/local/<owner>/... - tmp:
<workspace>/tmp/<owner>/...
- PRs:
- CWD-scoped commands: if you run
hstack test/typecheck/lintfrom insideapps/ui/apps/cli/apps/serverand omit a target, hstack infers the “service” automatically;hstack build/dev/startalso prefer the checkout you’re currently inside.
Quickstarts (feature-focused)
Remote access (Tailscale Serve)
hstack tailscale enable
hstack tailscale urlDetails: [docs/remote-access.md](docs/remote-access.md).
Worktrees + forks (clean upstream PRs)
Create a clean local worktree:
hstack wt new my-feature --use
hstack wt push active --remote=originTest an upstream PR locally:
hstack wt pr https://github.com/happier-dev/happier/pull/123 --use
hstack wt pr 123 --update --stashDeveloper quickstart: create a PR stack (isolated ports/dirs; idempotent updates)
This creates (or reuses) a named stack, checks out the monorepo PR worktree, optionally seeds auth, and starts the stack.
Re-run with --reuse to update the existing worktrees when the PR changes.
hstack stack pr pr123 \
--repo=https://github.com/happier-dev/happier/pull/123 \
--seed-auth --copy-auth-from=dev-auth --link-auth \
--devOptional: enable Expo dev-client for mobile reviewers (reuses the same Expo dev server; no second Metro process):
hstack stack pr pr123 --repo=123 --dev --mobileOptional: run it in a self-contained sandbox folder (delete it to uninstall completely):
SANDBOX="$(mktemp -d /tmp/hstack-sandbox.XXXXXX)"
hstack --sandbox-dir "$SANDBOX" stack pr pr123 --repo=123 --dev
rm -rf "$SANDBOX"Update when the PR changes:
- Re-run with
--reuseto fast-forward worktrees when possible. - If the PR was force-pushed, add
--force.
hstack stack pr pr123 --repo=123 --reuse
hstack stack pr pr123 --repo=123 --reuse --forceMaintainer quickstart: one-shot “install + run PR stack” (idempotent)
This is the maintainer-friendly entrypoint. It is safe to re-run and will keep the PR stack wiring intact.
npx --yes -p @happier-dev/stack hstack tools setup-pr \
--repo=https://github.com/happier-dev/happier/pull/123 \
--devOptional: enable Expo dev-client for mobile reviewers (works with both default --dev and --start):
npx --yes -p @happier-dev/stack hstack tools setup-pr --repo=123 --dev --mobileOptional: run it in a sandbox folder (auto-cleaned).
Note: review-pr uses a persistent sandbox workspace cache by default to speed up repeat runs (default: ~/.happier-stack/cache/sandbox/workspace). Add --no-workspace-cache for a fully self-contained sandbox, or --workspace-cache-dir=... to customize the location.
SANDBOX="$(mktemp -d /tmp/hstack-review-pr.XXXXXX)"
npx --yes -p @happier-dev/stack hstack tools review-pr --repo=123 --dev --sandbox-dir "$SANDBOX"
rm -rf "$SANDBOX"Short form (PR numbers):
npx --yes -p @happier-dev/stack hstack tools setup-pr --repo=123 --devOverride stack name (optional):
npx --yes -p @happier-dev/stack hstack tools setup-pr --name=pr123 --repo=123 --devUpdate when the PR changes:
- Re-run the same command to fast-forward the PR worktrees.
- If the PR was force-pushed, add
--force.
npx --yes -p @happier-dev/stack hstack tools setup-pr --repo=123 --dev
npx --yes -p @happier-dev/stack hstack tools setup-pr --repo=123 --dev --forceDetails: [docs/worktrees-and-forks.md](docs/worktrees-and-forks.md).
Server presets (light vs full)
- Use
happier-server-lightfor local, no-Docker topology defaults: SQLite, local files, and UI serving from the server. - Use
happier-serverfor production-like topology defaults: managed Postgres + Redis + S3-compatible storage and the UI gateway.- hstack can manage the required infra automatically per stack (via Docker Compose) and runs a UI gateway so you still get a single
https://...ts.netURL that serves the UI + proxies API/websockets/files.
- hstack can manage the required infra automatically per stack (via Docker Compose) and runs a UI gateway so you still get a single
- The database is an independent choice. Set
HAPPIER_DB_PROVIDER=postgres|mysql|pglite|sqlite; the preset supplies only the default (sqlitefor light,postgresfor full).
Switch globally:
hstack srv status
hstack srv use --interactiveSwitch per-stack:
hstack stack srv exp1 -- use --interactiveDetails: [docs/server-flavors.md](docs/server-flavors.md).
Stacks (multiple isolated instances)
hstack stack new exp1 --interactive
hstack stack dev exp1Point a stack at a PR worktree:
hstack wt pr 123 --use
hstack stack wt exp1 -- use pr/123-fix-thing
hstack stack dev exp1Details: [docs/stacks.md](docs/stacks.md).
Dev stacks: browser origin isolation (IMPORTANT)
Non-main stacks use a stack-specific localhost hostname (no /etc/hosts changes required):
http://happier-<stack>.localhost:<uiPort>(default; setHAPPIER_STACK_LOCALHOST_SUBDOMAIN_PREFIX=happyfor legacy)
This avoids browser auth/session collisions between stacks (separate origin per stack).
Menu bar (SwiftBar)
hstack menubar install
hstack menubar openDetails: [docs/menubar.md](docs/menubar.md).
Mobile iOS dev (optional)
# Install the shared hstack dev-client app on your iPhone:
hstack mobile-dev-client --install
# Install an isolated per-stack app (Release config, unique bundle id + scheme):
hstack stack mobile:install <stack> --name="Happier (<stack>)"Details: [docs/mobile-ios.md](docs/mobile-ios.md).
Reviewing PRs in an isolated sandbox
- Unique hostname per run (default):
hstack tools review-prgenerates a unique stack name by default, which results in a uniquehappier-<stack>.localhosthostname. This prevents browser storage collisions when the sandbox is deleted between runs. - Reuse an existing sandbox: if a previous run preserved a sandbox (e.g.
--keep-sandboxor a failure in verbose mode), re-runninghstack tools review-proffers an interactive choice to reuse it (keeping the same hostname + on-disk auth), or create a fresh sandbox.
Tauri desktop app (optional)
hstack build --tauriDetails: [docs/tauri.md](docs/tauri.md).
Commands (high-signal)
- Setup:
hstack setup-from-source(guided; selfhost or dev)- (deprecated alias)
hstack setup - (advanced)
hstack init(plumbing: shims/runtime/pointer env) - (advanced)
hstack bootstrap --interactive(workspace bootstrap wizard)
- Run:
hstack start(production-like; serves built UI via server-light)hstack dev(dev; Expo dev server for UI, optional dev-client via--mobile)
- Server flavor:
hstack srv statushstack srv use --interactive
- Worktrees:
hstack wt use --interactivehstack wt pr <pr-url|number> --use [--update] [--stash] [--force]hstack wt sync-allhstack wt update-all --dry-run/hstack wt update-all --stash
- Stacks:
hstack stack new --interactivehstack stack dev <name>/hstack stack start <name>hstack stack edit <name> --interactivehstack stack wt <name> -- use --interactivehstack stack happier <name> -- <happier-cli args...>
- Tools (maintainer / automation):
hstack tools setup-pr --repo=<pr-url|number> [--dev|--start]hstack tools review-pr --repo=<pr-url|number> [--dev|--start]hstack tools review(local diff review)hstack tools import(split repos → monorepo porting helpers)
- Menu bar (SwiftBar):
hstack menubar install
Docs (deep dives)
- Remote access (Tailscale + phone):
[docs/remote-access.md](docs/remote-access.md) - Server flavors (server-light vs server):
[docs/server-flavors.md](docs/server-flavors.md) - Worktrees + forks workflow:
[docs/worktrees-and-forks.md](docs/worktrees-and-forks.md) - Stacks (multiple instances):
[docs/stacks.md](docs/stacks.md) - Paths + env precedence (home/workspace/runtime/stacks):
[docs/paths-and-env.md](docs/paths-and-env.md) - Menu bar (SwiftBar):
[docs/menubar.md](docs/menubar.md) - Mobile iOS dev:
[docs/mobile-ios.md](docs/mobile-ios.md) - Tauri desktop app:
[docs/tauri.md](docs/tauri.md)
Configuration
Where config lives by default:
~/.happier-stack/.env: stable “pointer” file (home/workspace/runtime)~/.happier-stack/env.local: optional global overrides~/.happier/stacks/main/env: main stack config (port, server flavor, repo/worktree override)
Notes:
Canonical env prefix is
HAPPIER_STACK_*(no legacy aliases).Canonical stack storage is
~/.happier/stacks.To edit per-stack environment variables (including provider keys like
OPENAI_API_KEY), use:hstack stack env <stack> set KEY=VALUE hstack stack env <stack> unset KEY hstack stack env <stack> get KEY hstack stack env <stack> listRepo env templates:
- Use
.env.exampleas the canonical template (copy it to.envif you’re running this repo directly). - If an LLM tool refuses to read/edit
.env.exampledue to safety restrictions, do not create anenv.exampleworkaround—instead, ask the user to apply the change manually.
- Use
Breaking changes (vs “Happy Stacks”)
- No compatibility/migration for previous installs: uninstall old setups and run
hstack setup-from-sourceagain. - Env prefix is now
HAPPIER_STACK_*(no legacy aliases likeHAPPY_STACKS_*/HAPPY_LOCAL_*). - Workspace/worktrees are monorepo-first (default workspace:
~/.happier-stack/workspace, withmain/,dev/,pr/,local/,tmp/). - Yarn-only (no pnpm support).
Sandbox / test installs (fully isolated)
If you want to test the full setup flow (including PR stacks) without impacting your “real” install, run everything with --sandbox-dir.
To fully uninstall the test run, stop the sandbox stacks and delete the sandbox folder.
SANDBOX="$(mktemp -d /tmp/hstack-sandbox.XXXXXX)"
# Run a PR stack (fully isolated install)
npx --yes -p @happier-dev/stack hstack --sandbox-dir "$SANDBOX" tools setup-pr --repo=123 --dev
# Tear down + uninstall
npx --yes -p @happier-dev/stack hstack --sandbox-dir "$SANDBOX" stop --yes --no-service
rm -rf "$SANDBOX"Notes:
- Sandbox mode disables global OS side effects (PATH edits, SwiftBar plugin install, LaunchAgents/systemd services, Tailscale Serve enable/disable) by default.
- To explicitly allow those for testing, set
HAPPIER_STACK_SANDBOX_ALLOW_GLOBAL=1(still recommended to clean up after).
For contributor/LLM workflow expectations: [AGENTS.md](AGENTS.md).
Developing hstack itself
git clone https://github.com/happier-dev/happier.git
cd happier-dev
node ./apps/stack/bin/hstack.mjs setup --profile=devNotes:
- For local dev, prefer running stack commands via the
hstackentrypoint (it applies stack-scoped env and safety gates). - To make the installed
~/.happier-stack/bin/hstackshim (LaunchAgents / SwiftBar) run your local checkout without publishing to npm, set:
echo 'HAPPIER_STACK_CLI_ROOT_DIR=/path/to/your/happier-dev-checkout' >> ~/.happier-stack/.envOr (recommended) persist it via init:
hstack init --cli-root-dir=/path/to/your/happier-dev-checkout