---
name: microdev
description: Use when the user wants to run coding tasks in MicroDev, sign up for or log in to MicroDev, start Codex, Claude Code or Pi on a prompt in a MicroDev task, start, list, pause, resume or delete a MicroDev task environment, run commands in one, or set up a MicroDev team or billing. Covers installing the `microdev` CLI, the device-code step the human must do, starting agents with `--agent` and `--prompt`, the `--json` automation contract and what survives pause/resume.
---

# MicroDev

MicroDev gives each coding task its own isolated Linux microVM with the repository
checked out in `~/workspace`, and can start Codex, Claude Code or Pi in it on a prompt.
A task pauses after 15 idle minutes and resumes where it left off, with the
workspace and the agents' sign-in, sessions and settings intact.

You can do the whole onboarding for the human. Their part is entering one GitHub
device code in their browser. No card is needed. A few things may add one more step
for them, each explained below: a Git consent answer if a private repository needs
their GitHub credentials, Codex's own login the first time you start a Codex task, and one sign-in per
task for Claude Code or Pi.

## 1. Install the CLI

```sh
curl -fsSL https://microdev.dev/install.sh -o install-microdev.sh
sh install-microdev.sh
export PATH="$HOME/.local/bin:$PATH"
```

The installer verifies a SHA-256 checksum fetched over HTTPS, installs `microdev`
into `~/.local/bin`, needs no sudo and does not edit shell startup files. It runs on
macOS and Linux (x86_64 and arm64); on Windows use WSL2. OpenSSH must be installed.

`~/.local/bin` is often not on `PATH`, and an `export` in one of your shell commands
does not carry over to the next. Call the CLI as `~/.local/bin/microdev`, or start
each command with `export PATH="$HOME/.local/bin:$PATH";`. Check with
`~/.local/bin/microdev --version`.

## 2. Log in: the one human step

Run login in the background so you can read its first line while it waits:

```sh
microdev login --no-browser --json
```

It prints one line on stderr, `Open VERIFICATION_URL and enter USER_CODE`, then polls
until the human finishes. Relay that URL and code verbatim:

> Open VERIFICATION_URL in your browser, enter the code **USER_CODE** and approve
> MicroDev for your GitHub account. No card is needed.

Keep the command running. When the human approves, it prints the account as JSON on
stdout and stores the session in `~/.config/microdev` (owner-only). The personal
organization is selected automatically. If the code expires the command fails with
`Login expired`; run it again and give the human the new code.

The trial needs no card: 5 agent-hours (300 minutes) of running time over
14 days, 2 tasks running at once, no limit per run, and up to 10 new
tasks an hour. Resuming a paused task doesn't count against that (resumes have their
own limit of 30 an hour). Paused time is free, so pause tasks that are waiting on the human. Check what is left:

```sh
microdev trial --json
```

## 3. Start a task

The public sample repository:

```sh
microdev demo --json
```

The human's own repository. A public one needs nothing more. A private one clones
with this computer's Git credentials (`gh auth login` or a Git credential helper),
which the CLI hands to the task on its first start; see Git consent below.

```sh
microdev start OWNER/REPO --json
microdev start OWNER/REPO --ref BRANCH_OR_TAG --json
```

`--json` never opens a shell. The CLI prints `Request ID: …` and `Environment: …` on
stderr before it waits for setup, then prints the ready environment as JSON on
stdout. Record the environment ID.

### Start an agent on a prompt

```sh
microdev start OWNER/REPO --agent codex --prompt "Fix the flaky retry test and push a branch" --json
microdev start OWNER/REPO --agent claude --prompt-file task.md --json
```

`--agent codex|claude|pi|custom` starts that agent in a tmux session in the task's
`~/workspace` on the prompt (`--prompt TEXT`, or `--prompt-file PATH`, at most 32 KiB).
With `--json` the command returns as soon as the agent is running, and the JSON has
an extra field: `"agent": {"name": "codex", "terminal": "UUID"}`. To fan work out, run
one start per task, each with its own prompt and request ID.

- **Codex** runs on the human's Codex account, connected once and kept encrypted by
  MicroDev, so Codex tasks work without them. The first `--agent codex` start (or
  `microdev codex connect --no-browser` up front) runs Codex's own login on this
  computer, which needs Codex installed here; relay what it prints to the human.
  Once Git is connected, the task can push branches with the human's credential.
  Nothing pushes on its own: the task's agent pushes when its prompt asks it to.
- **Claude Code** runs on the human's Claude plan once they connect it for every
  task: they run `claude setup-token` and pipe what it prints to
  `microdev agent connect claude -` (an Anthropic API key works too). Never ask
  for the token yourself. **Pi** reuses a login the human makes once in a task
  (`microdev agent reuse PROVIDER ID`). `microdev agent status` shows what is
  connected. Without a connection, ask the human to run `microdev attach ID` in
  their own terminal (the same `MICRODEV_CONFIG_DIR` as you), follow the agent's
  login, then detach with `Ctrl-b d`; that login is kept across pause and resume.
- **Custom** (`--agent custom`) runs the human's own harness: the executable their
  dotfiles `init.sh` registers at `~/.config/microdev/custom-agent`, called as
  `custom-agent start PROMPT`, `open` or `resume` in `~/workspace`.

Claude Code runs with permission prompts off, like Codex. Pi never asks for tool
approval. The task's VM is the boundary.

`microdev attach ID` reopens the agent this computer started in the task: it resumes
a paused task and continues that agent's most recent conversation, with no picker
(the human must use the same `MICRODEV_CONFIG_DIR` as you). If Claude has no
conversation yet, it opens fresh. For any other task, `--agent codex|claude|pi|custom` opens
that agent fresh. It opens a terminal, so it is for the human, not for you.

For safe retries, choose the request ID yourself and reuse it. Repeating the command
with the same UUID after a timeout or crash creates no second task:

```sh
REQUEST_ID=$(uuidgen)
microdev start OWNER/REPO --agent codex --prompt "…" --json --request-id "$REQUEST_ID"
```

Rerunning the same start command (same `--request-id`) is always safe. It resumes a
paused task, finishes setup, and starts the agent once. If the agent already got the
prompt, it reopens the agent instead, so the prompt is never sent twice. If setup was
interrupted, inspect the existing task with `microdev status ID --json` rather than
creating another. When setup failed, `guest.setup_failure` says where:
`{"stage": "repository"|"dotfiles"|"dotfiles_init"|"task_configuration", "outcome": "failed"|"timed_out"}`.
Fix the cause (for example your dotfiles), then `microdev resume ID --json` retries
setup, even on a running task and even when the repository clones without Git
credentials. If a private project still needs Git consent, resume stops first and
names `microdev git connect ID`.

### Git consent

When this computer has GitHub credentials (`gh auth login` or a Git credential
helper), the first start of a repository asks, on a terminal, whether to sync those
credentials into the task. The demo is never asked about. Without a terminal:

- **A public repository** starts anyway and clones anonymously; stderr says
  `Continuing without Git credentials: OWNER/REPO is public and clones anonymously, but agents cannot push. To let them push: microdev git connect ID`.
  The agent starts as usual and `resume` still retries a failed setup. The task's
  agent cannot push until the human connects Git.
- **A private repository** (or one whose visibility GitHub would not confirm) stops
  with `Connect Git for OWNER/REPO interactively: microdev git connect ID`. The task
  already exists; do not create another.
- **A dotfiles repository** is a project of its own: private dotfiles stop the start
  with `Connect Git for OWNER/DOTFILES interactively: microdev git connect ID`, even
  when the repository is public.

To connect Git, ask the human to run `microdev git connect ID` in their own terminal
and answer `y` to each question. It asks about every project of the task that isn't
connected to their local GitHub account: the repository and its dotfiles repository.
This is a second human step; never answer the consent prompt for them. On a paused
task, `git connect` saves consent without resuming it; on a running task it hands the
credentials over right away. After a stopped start, run the same start command again with the same
`--request-id` (the one printed as `Request ID: …` if you did not choose it). It finds
the same task, waits until it is ready and starts the agent, if you asked for one,
without sending the prompt twice. A task started without `--agent` can use
`microdev resume ID --json` instead.

## 4. Work in the task

`microdev ssh ID` opens an interactive shell and needs a TTY. It resumes a paused
task first. There is no `microdev ssh ID -- COMMAND` form. To run commands
non-interactively, read the connection from status and call OpenSSH yourself:

```sh
microdev status ID --json        # .ssh.host, .ssh.port, .ssh.user
ssh -o BatchMode=yes \
    -o StrictHostKeyChecking=yes \
    -o HostKeyAlias=microdev-ID \
    -o UserKnownHostsFile=$HOME/.config/microdev/known_hosts/ID \
    -i $HOME/.config/microdev/id_ed25519 \
    -p PORT USER@HOST 'cd ~/workspace && cargo test'
```

The CLI writes the verified host keys to `~/.config/microdev/known_hosts/ID` whenever
`start`, `resume`, `ssh` or `attach` reaches the running task, with or without
`--agent` and with or without Git credentials. A start that stopped for Git consent
has not reached the task yet: after `microdev git connect ID`, rerun the start (or
`microdev resume ID --json`) first. The task authorizes
`~/.config/microdev/id_ed25519` unless the start named another key with `--key`. If
`MICRODEV_CONFIG_DIR` is set, use that directory instead of `~/.config/microdev`.

The image has Ubuntu 24.04, Git, Python, Node, compilers, tmux, ripgrep and the
Codex, Claude Code and Pi CLIs. Agents inside the task run on the human's own model
account; model usage is not part of MicroDev.

## 5. Lifecycle

```sh
microdev list --json             # every task and its phase
microdev status ID --json        # one task: phase, guest status, setup_failure, errors, SSH
microdev pause ID --json         # waits until the workspace is saved
microdev resume ID --json        # resume without opening a shell
microdev trial --json            # remaining trial allowance
microdev delete ID               # permanent; deletes the saved work too
```

Leaving an SSH session does not pause compute. Pause explicitly when a task is done
for now. Ask the human before `delete`.

## What survives pause

- **Kept:** all of `~/workspace`, byte for byte: every branch, stash and commit, and staged, uncommitted, untracked and ignored files.
- **Kept:** Codex, Claude Code and Pi sign-in, session history and settings files.
- **Rebuilt:** a fresh copy of the pinned system image, plus the human's dotfiles, cloned fresh with `init.sh` run on every resume.
- **Lost:** installed packages, other home-directory files, shell history, environment variables, agent logs, general caches and other agent files outside the kept list.
- **Lost:** running processes, tmux sessions, open connections, unsaved editor buffers.
- **Auto-stop:** a task pauses after 15 idle minutes, even with an agent open and a terminal or the Mac app attached: every minute under 2% of one vCPU and 32 bytes/s of data (packet headers and SSH sessions into the task excluded), with no typing in the terminal and no transcript change. Builds, tests, downloads, streaming model calls and typing are busy. A tool that sleeps with no CPU and no network for the whole window is paused too (the workspace is kept).

## Teams and billing

```sh
microdev org create "Team name"          # prints the organization as JSON
microdev org use ORGANIZATION_UUID       # select it for later commands
microdev billing plans                   # plans and prices
microdev billing subscribe PLAN SEATS    # PLAN: microdev-pro-v2 (1–500 seats), microdev-team-v1 (2–250 seats), microdev-business-v1 (5–125 seats), microdev-payg-v1 (1 seat)
microdev billing setup                   # returns a payment link for the human
microdev billing status
```

Payment happens only in the browser, through the link `billing setup` returns. Hand
that link to the human; never enter payment details yourself. `microdev help
advanced` and `microdev billing --help` list the remaining team commands.

## Do not

- Do not keep durable state outside `~/workspace`; everything else is rebuilt on resume.
- Do not assume a process, tmux session or server survives a pause.
- Do not create a second task to retry a failed start; reuse `--request-id` or inspect with `status`.
- Do not answer Git consent or payment prompts on the human's behalf.
- Do not put model API keys in the repository. Model credentials are the human's own.
