tipod docs

tipod documentation

Isolated Linux VMs with SSH, a disk saved every minute, and a pause that never loses the disk. Install the CLI and get to a root shell in about five minutes.

Quickstart

Install, sign up with an invite, create a pod, work in it, then pause it without losing state.

1. Install the CLI

$ curl -fsSL https://tipod-control-plane.ramasamy-vignesh.workers.dev/install | sh
# open a new terminal, or: export PATH="$HOME/.tipod/bin:$PATH"

The installer verifies the binary against the published sha256 manifest, installs to ~/.tipod/bin, and writes a default config only if none exists — it never overwrites an existing API key. Re-run it any time with pod upgrade.

2. Create an account

Signup is invite-gated during the friends beta. Ask the operator for the shared token, then:

$ pod signup --email you@example.com --invite <token>
$ pod whoami

Signup prints an API key once and grants trial machine-time. If you already have a key, run pod signin tp_… instead. pod setup runs the guided browser flow.

3. Create a pod

$ pod create --type small --name first-pod --ttl 900
✓ Created pod tp_abc123 · type small · state creating

$ pod ls
$ pod get active

active is an alias for the last pod you created in this shell session, so you rarely need to type a full ID. --ttl sets the auto-stop timer in seconds (default 3600, max 2592000); pass --no-auto-stop to disable it.

4. Work, pause, wake

$ pod shell active
$ pod pause active
# poll until state is archived
$ pod get active
$ pod wake active
$ pod rm active

Pause writes a verified snapshot before the pod is archived. The disk is saved about once a minute while the pod is running.

Friends beta

Control plane: https://tipod-control-plane.ramasamy-vignesh.workers.dev. Custom domains are not live yet, so the CLI and API both target the Worker URL directly.

Machines

Two predictable x86_64 shapes for the first release.

TypeResourcesRateGood for
small2 vCPU · 4 GB0.5× machine-timeAgent tasks, scripts, everyday shells
default4 vCPU · 8 GB1× machine-timeBuilds and longer sessions

--type also applies when restoring or forking: pod wake --type small <id> resizes on restore, and pod clone --type default <id> sizes the fork. large is post-MVP.

Base image

Pods start from a baked Ubuntu x86_64 template with OpenSSH, qemu-guest-agent, Docker, Git, Node, Python, and common CLI tools.

Not included yet

GPUs, ARM images, Windows and macOS guests, memory (RAM) snapshots, and desktop streaming are outside the initial release. Dedicated public IPs are in procurement.

Pod states

Lifecycle operations are asynchronous. Poll with pod get <id> and read transitions with pod log <id>.

StateMeaning
creating / provisioningVM clone in progress
ready / idle / runningRunning and reachable over SSH
stopping / archivingPause requested; final snapshot in progress
archivedPaused with a completed snapshot — resumable with wake
stoppedStopped before the archiving step
errorLast operation failed; see pod log

Abort-stop

If the final snapshot or the shutdown fails, the pause aborts: the pod reverts to its running state, billing continues, and a pod.stop_failed event is recorded. A pod reaches archived only when a verified snapshot exists, so a pause can never silently discard your disk.

CLI reference

One binary for humans and automation. Every command accepts --json, which is enabled automatically when output is piped.

Pod lifecycle

CommandDoesNotable flags
pod createCreate a pod--type --name --ttl --no-auto-stop --env --no-env
pod lsList pods--filter r|s|p|t|e --all
pod get <id>Show pod details
pod pause <id>Snapshot, archive, pause billing
pod wake <id>Resume from latest snapshot--type --no-env
pod clone <id>Fork from latest snapshot--type --env --no-env
pod ttl <id>Change the auto-stop timer--hours --ttl --no-auto-stop
pod rm <id>Delete a pod
pod log <id>Read lifecycle events--follow --limit
pod cancel <id>Interrupt the running command

Access

CommandDoesNotable flags
pod shell <id> [cmd]Open a shell or run a command
pod cpCopy files to or from a pod--recursive
pod tunnel <id>Forward a port to localhost--remote --local --bind
pod expose <id> <port>Publish a port on HTTPS--title --public --private
pod exposes <id>List exposed ports
pod unexpose <id> <port>Remove an exposed port

Snapshots, templates, account

CommandDoes
pod snap ls [id]List snapshots, all or for one pod
pod snap latest <id>Show the snapshot that wake and clone use
pod tpl lsList your templates
pod tpl create <id> --nameCreate a template from a paused pod
pod tpl clone <tpl> --nameCreate a pod from a template
pod tpl rm <tpl>Delete a template
pod quotaShow balance, active pods, and rate limits
pod key create|ls|rotate|revokeManage API keys
pod whoamiShow account, plan, and config path
pod openOpen the dashboard in a browser
pod upgradeRe-run the installer to upgrade
pod autocomplete bash|zsh|fishPrint shell completions

Config & flags

Configuration lives at ~/.config/tipod/config.json with restrictive permissions.

{
  "apiUrl": "https://tipod-control-plane.ramasamy-vignesh.workers.dev/v1",
  "apiKey": "tp_…"
}
Global flagEffect
--api-url <url>Override the endpoint (env: TIPOD_API_URL)
--jsonMachine-readable output; automatic when piped
--no-updateSkip the startup version check

Run pod path to print the resolved path and contents. The managed SSH key lives at ~/.ssh/tipod_ed25519.

SSH, files, tunnels

Pods are ordinary Linux machines; the CLI manages connection details for you.

$ pod shell tp_abc123
$ pod shell tp_abc123 "cd app && npm test"
$ pod shell tp_abc123 -- bash -s < ./setup.sh

$ pod cp ./build.zip tp_abc123:/home/user/
$ pod cp --recursive ./project tp_abc123:/home/user/

$ pod tunnel tp_abc123 --remote 5432 --local 5433

SSH becomes available once the pod is running and has an IP. Keys are injected with POST /pods/{id}/sshkey and stored locally at ~/.ssh/tipod_ed25519.

Expose a port

Publish a service on HTTPS without touching a firewall rule yourself.

$ pod expose tp_abc123 3000 --title "App preview"
✓ https://host-tp_a1b2c3.tipod.dev?_token=…

$ pod expose tp_abc123 3000 --public
$ pod exposes tp_abc123
$ pod unexpose tp_abc123 3000

Routes are private by default and carry an _token query parameter. The proxy strips the token before forwarding and only accepts upstream targets registered by the host orchestrator. Custom domains are not configured yet.

Templates

Bake an environment once, then fork it per user, task, or CI run.

$ pod pause tp_source
$ pod tpl create tp_source --name "Node baseline"
$ pod tpl clone tpl_abc123 --name customer-1 --no-env
$ pod tpl ls

A template needs a paused pod with a completed snapshot. To update one, wake the source, make changes, and pause it again — later forks use the newest snapshot. --no-env drops account secrets from the fork, and it is one-way.

Snapshots

Disk-level snapshots power wake, clone, and templates.

KindWhenRetention
periodicAbout every minute while running60 minutely · 24 hourly · 7 daily
stopOn pause, before archivingKept as the resume point

What a snapshot holds

  • Included — user files, installed packages, configuration, enabled systemd services, and Docker named volumes.
  • Not included — running process memory, hostname, network identity, and SSH host keys.

Because RAM is not captured, processes you started by hand need restarting after wake. Services enabled through systemd come back on their own.

$ pod snap ls tp_abc123
$ pod snap latest tp_abc123

Billing & quota

Subscription machine-time with carry-forward. Paused pods are free.

ItemValue
Starter$20/month → 2,000,000 default-equivalent seconds per paid invoice
small0.5× machine-time rate
default1× machine-time rate (~$0.036/hour)
Paused or archived$0.00 — the disk is still kept
BalanceCarries forward; it does not reset monthly

The friends beta may grant trial seconds at signup. Check your balance with pod quota, or read GET /limits, GET /billing/usage, and GET /billing/transactions.

Troubleshooting

SymptomCause and fix
orchestrator_unavailableThe control plane is up but no host agent is registered. Install the Go orchestrator on a KVM-capable host to enable VM operations.
pod.stop_failedAbort-stop triggered: the snapshot could not be verified, so the pod stayed running. Retry pod pause; if it repeats, check host disk space.
SSH connection refusedThe pod has no IP yet. Wait for ready in pod get, then retry.
quota_exceededMachine-time balance or the active-pod cap is exhausted. Check pod quota; pause idle pods.
Process gone after wakeExpected — snapshots are disk-only. Run the process under systemd so it restarts automatically.
pod: command not foundOpen a new terminal, or add ~/.tipod/bin to PATH.

FAQ

What exactly is a pod?

An isolated KVM/QEMU virtual machine running Ubuntu — a real computer for an agent or a person. Files and packages survive a clean pause and wake.

Is this a container?

No. Pods are full VMs with their own disk and systemd, managed by a host orchestrator. You get machine semantics rather than a process tree.

Why is the CLI verb pause but the HTTP route /stop?

The CLI uses short, human verbs; the underlying HTTP routes keep RESTful names. pause maps to POST /pods/{id}/stop, wake to POST /pods/{id}/resume, and clone to POST /pods/{id}/fork.

Am I billed while a pod is paused?

No. Machine-time accrues per second only while a pod runs. Paused and archived pods cost nothing and keep their disk.

Can two agents share secrets?

Account-level secrets are injected into new pods unless you pass --no-env. Isolation still holds between running VMs — one pod cannot read another's live filesystem.

Where do pods run?

APAC-first, with Singapore staging today. Dedicated public IPs are on the roadmap; for now SSH uses the host IP plus a mapped port.

Do you support GPUs?

Not in the initial scope.