Setting up a PostHog devbox
A devbox is a Coder workspace running the full PostHog stack on an EC2 instance, managed through hogli devbox:* (the only supported interface — drive those commands, don't reimplement them). It ships ready to use: the repo cloned at ~/posthog, the stack pre-warmed, and Claude Code installed. This skill gets a dev connected and working; how they personalize beyond that is their choice, not something to push.
Prerequisite: tailnet access (the thing people miss)
The devbox control plane lives inside a private VPC reachable only over Tailscale. The ACL that grants the route is tailnet-policy.hujson in posthog-cloud-infra: your email must be in group:engineering. Without that grant, the Coder control plane (10.70.0.1:443) is simply unroutable and every hogli devbox:* command dies at the reachability check — not an auth or install problem, and no amount of re-running devbox:setup fixes it.
If hogli devbox:doctor reports the control plane unreachable, the fix is a PR adding the user to group:engineering in tailnet-policy.hujson (then ask Team DevEx if still blocked). Diagnose this before touching anything else.
Workflow
1. Check state — hogli devbox:doctor
hogli devbox:doctor # read-only: tailnet access, reachability, auth, ssh config, saved setup
A safe probe — it never prompts or mutates host config (unlike devbox:setup). If it flags the control plane unreachable, resolve the tailnet grant before anything else. For more detail: hogli devbox:list (your boxes), hogli devbox:status (state, template freshness), hogli devbox:secret:list (secret names only).
2. One-time local setup — hogli devbox:setup
Interactive: checks Tailscale + Coder reachability, installs and authenticates the coder CLI, and writes the SSH host entries that devbox:ssh/devbox:exec rely on. It then offers git identity, git signing, a dotfiles repo, and your Claude token — all optional; --skip-* anything you don't want. Re-run one step with its flag, e.g. hogli devbox:setup --configure-git-signing.
3. Start and connect — hogli devbox:start
hogli devbox:start # create or resume your box
hogli devbox:ssh # shell in
hogli devbox:open --vscode # or --cursor / --web
hogli devbox:stop # when done — preserves disk, stops billing
4. Auth, if you want it (optional)
To have gh or Claude Code authenticated on the box, store the token once as a Coder user secret. It's injected as an env var into every box you start, so you set it once rather than per box:
hogli devbox:secret:set GH_TOKEN --env GH_TOKEN
hogli devbox:secret:set CLAUDE_CODE_OAUTH_TOKEN --env CLAUDE_CODE_OAUTH_TOKEN
# also supported: ANTHROPIC_API_KEY, OPENAI_API_KEY, OP_SERVICE_ACCOUNT_TOKEN, AWS_CREDENTIALS (--file)
Authing gh / Claude on a devbox is fine — that's what these are for. Set the value from --file or the hidden prompt; never paste a token into a command line or into this conversation. Restart a running box to pick up a newly set secret.
5. Make it yours — your call
The box is usable as shipped; personalize it however suits you, or not at all. Two supported paths, neither required, don't push one over the other:
- Tweak the box directly —
devbox:sshin and install tools, add aliases, clone repos. Changes under/homesurvive stop/start and template updates, but adevbox:destroy(or a brand-new box) starts fresh. - A dotfiles repo — if you'd rather keep portable, version-controlled config that re-applies to every box:
hogli devbox:setup --configure-dotfilespoints the box at yourdotfiles_uri, and Coder clones it (running an executable~/dotfiles/install.shif present) on each start.
6. Run commands on the box — hogli devbox:exec
devbox:exec runs one command over SSH and propagates its exit code — handy for scripts, agents, and quick checks without opening a shell:
hogli devbox:exec -- bash -lc 'gh auth status'
hogli devbox:exec -- bash -lc 'cd ~/posthog && git status'
hogli devbox:exec -n api -- bash -lc 'uname -a' # -n targets a labeled box
Wrap commands in bash -lc '...': a non-login shell doesn't reliably source ~/.bashrc/~/.zshrc, so a bare gh auth status can report "command not found" for anything on a login-shell PATH (e.g. ~/.local/bin) — a false negative. The login shell also keeps the exit code trustworthy, so && chaining and if checks work. Use -- to separate hogli's flags from the command's own.
devbox:exec is not side-effect-free: like every devbox:* command it runs the reachability check first, which on Linux may sudo tailscale set --accept-routes and prompt for a password. Run hogli devbox:setup once interactively so routes and SSH config are in place before an agent drives devbox:exec unattended.
Persistence & multiple boxes
devbox:stop→devbox:startand template/AMI updates preserve/home(the instance is stopped, not terminated). Adevbox:destroywipes it — intentional, so don't keep anything irreplaceable only inside a box.- You can run more than one box. Box-local changes don't carry between them; user secrets do (user-scoped), and a dotfiles repo does if you use one. That's the practical reason to reach for those if you find yourself re-doing setup — but it's a choice, not a requirement.
Gotchas
- Never echo secret values into the transcript, logs, a PR, or a command line.
devbox:secret:setreads from a hidden prompt or--file;secret:listshows names only. Keep it that way. - Secrets need a restart. A new or changed secret only reaches boxes started afterward —
hogli devbox:restartto pick it up on a running box. devbox:exec/devbox:sshneeddevbox:setupto have run (it writes thecoder.*SSH host config). Without it they fail at connection;devbox:doctorshows whether SSH access is configured.code-server(browser IDE) has no SSH agent forwarding, so commit signing via a forwarded key won't work there — use VS Code Desktop / Cursor / JetBrains (SSH-based) when you need to sign.