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.
git push from inside ships through your normal deploy pipeline.create_dev_environment (MCP), the AI Dev Environment wizard, or hoststack dev create — not 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), andopencode(SST OpenCode) — all onPATH. - MCP servers wired into all three agents:
hoststack(manage your projects, services, deploys, databases, domains),poststack(email),filesystem,git, andchrome. - A real browser: Google Chrome, driven headlessly by your agent. It can open the dev server it just started, screenshot it, read the console and network log, click through a flow, and profile it — so it can check its own work instead of guessing.
- Toolchain: git, GitHub CLI (
gh), thehoststackCLI, Node 24, Bun, Python 3, uv, ripgrep, fzf, jq, tmux, postgresql-client, redis-tools, and the usual editors. - Persistent
/workspacevolume — your repos, agent logins andnode_modulessurvive 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:
// 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) andHOSTSTACK_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:
# Claude Code — opens a device-code login flow
claude /login
# Then just run an agent
claude # interactive
codex # OpenAI Codex
opencode # SST OpenCodeLet your agent use the browser
Every box ships Google Chrome and wires it into all three agents as the chrome MCP server. Ask for it in plain language — "start the dev server, open it, and show me a screenshot", or "the login page 500s, check the network tab" — and the agent navigates, clicks, screenshots, reads the console and network log, and records performance traces.
It's headless: there's no screen in the box, so the agent reads the page rather than showing it to you. Chrome only starts on the first browser tool call, so sessions that never browse don't pay for it — but a page costs roughly 300–400 MB of the box's memory while it's open, so size up if you're also running an agent and a dev server on a 2 GB box.
Each agent session gets a fresh, throwaway Chrome profile. If you'd rather have one browser that stays logged into the app you're testing, run dev-browser up — one shared Chrome with a profile on /workspace and a DevTools endpoint on 127.0.0.1:9222 that survives restarts. Your repo's own Playwright and Puppeteer tests find the same Chrome with no extra download.
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
/workspacevolume 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_hetznerforscripts/deploy.sh, or any name for git-over-SSH). - Connect agents & MCP — paste
ANTHROPIC_API_KEY(Claude),OPENAI_API_KEY(Codex), andHOSTSTACK_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 theGSC_OAUTH_*env vars set) sobun run gsc:reportworks 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:
# 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.shYour ~/.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.