Skip to content
HostStack Docs

AI Dev Environments

A dev environment on HostStack is a private service running our hoststack/dev-env image — a persistent cloud container with coding agents and MCP servers preinstalled. Open the Terminal tab (it works great from a phone) and run your agent on your repos, on European infrastructure.

It's just a service. No new resource type to learn — it provisions, deploys, scales, suspends, streams logs and bills exactly like any other private service. git push from inside ships through your normal deploy pipeline.
Not a project deploy environment. A dev box is created with create_dev_environment (MCP), the AI Dev Environment wizard, or hoststack dev createnot with create_environment(type:"development"), which makes a project deploy target (production/staging) and never gives you a terminal. See the MCP reference for the tool surface.

What's inside

  • Coding agents: claude (Anthropic Claude Code), codex (OpenAI Codex), and opencode (SST OpenCode) — all on PATH.
  • MCP servers wired into all three agents: hoststack (manage your projects, services, deploys, databases, domains), poststack (email), filesystem, and git.
  • Toolchain: git, GitHub CLI (gh), Node 22, Bun, Python 3, uv, ripgrep, fzf, jq, tmux, postgresql-client, redis-tools, and the usual editors.
  • Persistent /workspace volume — your repos, agent logins and node_modules survive restarts and redeploys.

Create one (one click)

In the dashboard, create a new service and pick the AI Dev Environment template. It pre-selects the image, makes the service private (no public ingress), attaches a 10 GB /workspace volume, and prompts you for the optional MCP API keys — then deploys.

The Development workspace

Every dev environment shows up in the dashboard's Development section — one place to switch between environments, open multiple terminal tabs per box (run an agent in one, git in another), and watch a live readout of what's running inside (the coding agent, your shells, and other processes). It works great from a phone.

Your dev URL (serve on $PORT)

Every box has a private, unguessable public URL that proxies to port 3000 inside the box. Start a dev server on 3000 bound to 0.0.0.0 and it's live at that URL — until then the URL shows a branded "no app listening" page. The box presets HOST=0.0.0.0, injects PORT=3000, and exports the URL as $HOSTSTACK_DEV_HOST.

The proxied port is hard-wired to 3000 — bind your dev server there. Setting a different PORT (in a dashboard env var or a committed .env) does not re-point the URL; it just moves your server off the port the proxy reaches, so the box looks empty. Always listen on 3000 (the injected $PORT) for the dev URL to work.

Dev servers (Vite, Next, Astro, …) reject requests whose Host header isn't allow-listed, so a plain run is refused at the dev URL even when bound to 0.0.0.0. Add the dev host to the framework's allowlist:

ts
// Vite — vite.config.ts
export default defineConfig({
  server: { host: true, allowedHosts: ['.hoststack.dev'] },
})

// Next.js — next.config.js
// Use the literal wildcard: HOSTSTACK_DEV_HOST is undefined unless you've
// exported it, and [undefined] allow-lists nothing.
module.exports = { allowedDevOrigins: ['*.hoststack.dev'] }

Injected environment

HostStack sets a handful of variables in the container at boot. These are real environment variables, so under Bun/Node they take precedence over the same keys in a committed .env file (a committed PORT or DATABASE_URL is silently ignored). What's injected:

  • PORT (3000) and HOSTSTACK_DEV_HOST — the listen port and public dev host.
  • HOSTSTACK_* — service/project/team IDs, internal URL, deploy ID, branch, HOSTSTACK_TMP_DIR.
  • Companion database URLs/creds when you attach them — DATABASE_URL, POSTGRES_*, REDIS_*, MEILI_*.
  • Agent/MCP keys you save in Setup ANTHROPIC_API_KEY, OPENAI_API_KEY, HOSTSTACK_API_KEY, POSTSTACK_API_KEY.

Run printenv in the box to see the live set. To point at your own local stack instead, run dev-services up and export the URL in your shell (a shell export overrides the committed .env).

Log your agent in

Agent logins are account-wide: the default you pick per agent in Settings → Coding Agents is seeded into every box automatically, so you sign in once — not per box. For all three agents, log in inside a box (claude /login, codex login, opencode auth login) and use Development → Setup → Capture from this box to save it to your account — a real subscription login, so the full model menu (incl. Fable) works. For Claude you can also paste your ~/.claude/.credentials.json in Settings → Coding Agents. Logins persist on the /workspace volume:

bash
# Claude Code — opens a device-code login flow
claude /login

# Then just run an agent
claude            # interactive
codex             # OpenAI Codex
opencode          # SST OpenCode

Set up from the dashboard (Setup)

Open Development → Setup on a running box to provision it without touching the terminal. Two kinds of things you can save, with different storage:

  • Box-only (never stored). The write-through Credentials panel — SSH keys, raw API keys pasted as env vars, and your git identity — is written straight into the box's /workspace volume and nowhere else. It persists across restarts on that box, but HostStack keeps no copy.
  • Account-wide (stored encrypted). Coding-agent logins (Claude / Codex / OpenCode) and the Google Search Console OAuth client are saved once under Settings → Coding Agents and seeded into every box. These are persisted server-side — encrypted at rest with AES-256-GCM — so you sign in once instead of per box.

What you can set here (each lands on the box's /workspace volume, so it persists across restarts and applies in new terminal sessions — the account-wide rows are also kept encrypted on your account, per above):

  • SSH keys — upload a private key (name it id_hetzner for scripts/deploy.sh, or any name for git-over-SSH).
  • Connect agents & MCP — paste ANTHROPIC_API_KEY (Claude), OPENAI_API_KEY (Codex), and HOSTSTACK_API_KEY / POSTSTACK_API_KEY (MCP servers). They reach the agents with no redeploy.
  • Git identity — the name & email stamped on your commits.
  • Search Console — save your Google OAuth client once under Settings → Coding Agents and it's seeded into every box (at /workspace/.config/gsc-oauth-client.json, with the GSC_OAUTH_* env vars set) so bun run gsc:report works with no per-box upload.

Prefer the terminal? Subscription users can still run claude /login, and any of the above can be set with git config / export by hand. The filesystem and git MCPs work with no key.

Develop any repo — incl. hoststack/poststack

A dev box isn't limited to apps hosted on HostStack. To work on any git repo — including ones that deploy over SSH rather than a HostStack git push — start a blank box, then:

bash
# 1. Development → Credentials → upload your SSH key as "id_hetzner"
#    (and your git identity + agent keys)

# 2. Clone over SSH (persists on /workspace):
git clone git@github.com:you/hoststack.git
cd hoststack

# 3. Work with your agent, then ship however that repo ships —
#    e.g. its own deploy script over SSH:
./scripts/deploy.sh

Your ~/.ssh and git config live on /workspace, so the key and identity survive every restart. You can also pre-clone at boot with hoststack dev create --repo <git-url>.

Code from your phone

The Terminal is built mobile-first. Install HostStack as a PWA (Add to Home Screen) or just open it in any mobile browser. Tap the terminal to bring up your keyboard; a soft-key bar gives you the keys phones lack — Esc, Tab, common Ctrl combos (Ctrl-C/D/Z/R/L), arrow keys, and shell symbols. The view tracks the on-screen keyboard so your prompt is never hidden. Kick off an agent, lock your phone, come back later — the session keeps running on our infra.

Shipping from inside

Your dev environment shares the same git + deploy plumbing as the rest of HostStack. Have your agent commit and git push, and the push hits your service's normal deploy webhook — no extra wiring. Clone any repo into /workspace and work on it there.

Billing

A dev environment is billed exactly like the private service it is — by the plan size you pick, plus the /workspace volume's per-GB-month storage. Power it down from the dashboard when you're not using it: the container is stopped so it no longer consumes compute. Anything running in it — terminal sessions, tmux, in-flight agents — is ended, but your /workspace (repos, agent logins, node_modules) is a persistent volume and is retained. Resume re-runs the box on its existing image in seconds.

Essential cookies only — for login sessions. No tracking. Details