feat: kimi-box template — the Moonshot Kimi CLI agent seed

The fourth agent seed, thin per #81: Debian 13, the 'kimi' user, tmux
and rig — everything the box becomes lands via 'rig bootstrap kimi-box'
(heavy-duty/rig#109). Same resources as the sibling agent seeds. The
template loop in test/cli.sh discovers it dynamically; doc lists and the
README table gain the row.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
dan-claude-bot 2026-07-22 15:10:35 +00:00
parent a17903f07c
commit bf74744bda
6 changed files with 67 additions and 7 deletions

View file

@ -5,6 +5,10 @@ which records not just what changed but what each drill run proved.
## Unreleased ## Unreleased
### Added
- `kimi-box` template — the Moonshot Kimi CLI agent seed (#158; rig#109's tenant)
## 0.9.0 — 2026-07-21 ## 0.9.0 — 2026-07-21
### Added ### Added

View file

@ -3,7 +3,7 @@
**Headless, trust-less, throwaway dev VMs.** One command mints a fresh, **Headless, trust-less, throwaway dev VMs.** One command mints a fresh,
network-isolated Incus box from a **template**; the coding-agent templates network-isolated Incus box from a **template**; the coding-agent templates
hand you a CLI agent on Debian 13 — `claude-box` (Claude Code), `codex-box` hand you a CLI agent on Debian 13 — `claude-box` (Claude Code), `codex-box`
(OpenAI Codex), `grok-box` (xAI Grok) — **box mints, [rig](https://github.com/heavy-duty/rig) (OpenAI Codex), `grok-box` (xAI Grok), `kimi-box` (Moonshot Kimi) — **box mints, [rig](https://github.com/heavy-duty/rig)
converges**: the template is a thin seed, and the agent tooling lands via a converges**: the template is a thin seed, and the agent tooling lands via a
creds-free `rig bootstrap` role auto-run at mint creds-free `rig bootstrap` role auto-run at mint
([#81](https://github.com/heavy-duty/box/issues/81)). The box is the product ([#81](https://github.com/heavy-duty/box/issues/81)). The box is the product
@ -222,7 +222,7 @@ box shell work # enter as the template's user
``` ```
Pick whichever coding-agent template you like — `claude-box`, `codex-box`, Pick whichever coding-agent template you like — `claude-box`, `codex-box`,
`grok-box` — or `blank` for none. Inside the box, authenticate as needed. The `grok-box`, `kimi-box` — or `blank` for none. Inside the box, authenticate as needed. The
`claude-box` template looks like this; the others follow the same shape with `claude-box` template looks like this; the others follow the same shape with
their own login step: their own login step:
@ -245,6 +245,7 @@ another is just another directory. What ships today:
| `claude-box` | Claude Code, creds-free — where this project started | | `claude-box` | Claude Code, creds-free — where this project started |
| `codex-box` | OpenAI Codex CLI, creds-free | | `codex-box` | OpenAI Codex CLI, creds-free |
| `grok-box` | xAI Grok CLI, creds-free | | `grok-box` | xAI Grok CLI, creds-free |
| `kimi-box` | Moonshot Kimi CLI, creds-free |
| `staging-box` | Server-class: docker + sshd hardening via rig; VM-only, autostarts | | `staging-box` | Server-class: docker + sshd hardening via rig; VM-only, autostarts |
**Templates are thin seeds; rig does the becoming** **Templates are thin seeds; rig does the becoming**
@ -256,7 +257,7 @@ pin tokens below). The seed is deliberately small — the tenant user, tmux,
and [rig](https://github.com/heavy-duty/rig) preinstalled, nothing that and [rig](https://github.com/heavy-duty/rig) preinstalled, nothing that
joins a tailnet or admits credentials — and after cloud-init settles, box joins a tailnet or admits credentials — and after cloud-init settles, box
auto-runs the template's **creds-free** tenant role inside the guest auto-runs the template's **creds-free** tenant role inside the guest
(`rig bootstrap claude-box` / `codex-box` / `grok-box` / `staging-box`, (`rig bootstrap claude-box` / `codex-box` / `grok-box` / `kimi-box` / `staging-box`,
[rig#31](https://github.com/heavy-duty/rig/issues/31); the roles carry a [rig#31](https://github.com/heavy-duty/rig/issues/31); the roles carry a
family suffix — `-box` for box tenants, `-server` for fleet machines — and a family suffix — `-box` for box tenants, `-server` for fleet machines — and a
template is named for the role it converges, template is named for the role it converges,

View file

@ -265,7 +265,7 @@ one of its snapshots — login state, git creds and clones carry over,
isolation is preserved, and the clone knows its template's user without isolation is preserved, and the clone knows its template's user without
being told. being told.
A tenant template (claude-box, codex-box, grok-box, staging-box) is a THIN seed — the user, A tenant template (claude-box, codex-box, grok-box, kimi-box, staging-box) is a THIN seed — the user,
tmux, rig (#81) — and after cloud-init box auto-runs the creds-free tenant tmux, rig (#81) — and after cloud-init box auto-runs the creds-free tenant
role inside it ('rig bootstrap <role>', rig#31): that role installs the role inside it ('rig bootstrap <role>', rig#31): that role installs the
agent CLI / server posture and the agent-context file. rig is preinstalled agent CLI / server posture and the agent-context file. rig is preinstalled

View file

@ -1,8 +1,8 @@
# box design # box design
`box` is a CLI that mints and manages **trust-less, network-isolated VMs `box` is a CLI that mints and manages **trust-less, network-isolated VMs
with a coding agent installed** (`claude-box`, `codex-box`, `grok-box`, or with a coding agent installed** (`claude-box`, `codex-box`, `grok-box`,
`blank` for none). It is infrastructure, not a project provisioner. `kimi-box`, or `blank` for none). It is infrastructure, not a project provisioner.
See issue #3 for the full reframe and rationale. This doc captures the durable See issue #3 for the full reframe and rationale. This doc captures the durable
design decisions. design decisions.
@ -94,7 +94,7 @@ A template is a **thin, creds-free seed** — base image, the tenant user,
tmux, and [rig](https://github.com/heavy-duty/rig) preinstalled — and what tmux, and [rig](https://github.com/heavy-duty/rig) preinstalled — and what
the box *becomes* lives in rig's bootstrap roles (rig#31): box auto-runs the the box *becomes* lives in rig's bootstrap roles (rig#31): box auto-runs the
template's creds-free tenant role after cloud-init (`rig bootstrap claude-box` template's creds-free tenant role after cloud-init (`rig bootstrap claude-box`
/ `codex-box` / `grok-box` / `staging-box` — the roles carry a family suffix, / `codex-box` / `grok-box` / `kimi-box` / `staging-box` — the roles carry a family suffix,
`-box` for box tenants and `-server` for fleet machines, and the templates are `-box` for box tenants and `-server` for fleet machines, and the templates are
named for the roles they converge, rig#76), which installs the agent CLI or named for the roles they converge, rig#76), which installs the agent CLI or
server posture. The split is deliberate: cloud-init is a first-boot one-shot — server posture. The split is deliberate: cloud-init is a first-boot one-shot —

View file

@ -0,0 +1,22 @@
# The kimi-box template — a thin, creds-free seed (#81): Debian 13, the
# 'kimi' user, tmux and rig. What the box BECOMES — the Moonshot Kimi CLI,
# docker, the agent-context file with its #80 guard — is rig's job:
# box auto-runs 'rig bootstrap kimi-box' after mint (heavy-duty/rig#31,
# the role itself: heavy-duty/rig#109).
# The template is named for the role it converges, suffix and all
# (heavy-duty/rig#76): rig's roles carry a family suffix — '-server' for
# fleet machines, '-box' for box tenants — and a seed that named the bare
# 'kimi' would ask a post-rename rig for a role that no longer exists.
# KEY="value" only. Parsed against an allowlist, never sourced; there is no
# key for a network or a security flag, on purpose — the shared box-net
# profile is the placement contract and no template can weaken it.
# BOX_USER must match the user user-data.yaml creates (the duplication is
# deliberate and by hand) — and it is the tenant user the rig role converges
# (rig dies loudly if the seed did not create it).
BOX_DESCRIPTION="Moonshot Kimi CLI on Debian 13, creds-free — box mints, rig converges"
BOX_IMAGE="images:debian/13/cloud"
BOX_USER="kimi"
BOX_CPU="4"
BOX_MEMORY="8GiB"
BOX_DISK="60GiB"
BOX_BOOTSTRAP_ROLE="kimi-box"

View file

@ -0,0 +1,33 @@
#cloud-config
# A thin, creds-free seed (#81): the tenant user, tmux (#65), and rig —
# nothing that joins a tailnet or admits credentials, no agent CLI, no
# docker, no context-file heredoc. Everything this box becomes comes from
# 'rig bootstrap kimi-box' (heavy-duty/rig#31), which box auto-runs after
# mint; the agent-context file — including the #80 guard (never run
# 'box setup-host' or the drill inside a box) — is rendered by that role,
# once, instead of being copy-pasted per template.
users:
- name: kimi
shell: /bin/bash
sudo: "ALL=(ALL) NOPASSWD:ALL"
lock_passwd: true
package_update: true
# tmux: 'box tmux' runs 'tmux new-session' INSIDE the box (#65).
# curl + ca-certificates: the rig installer below rides them, and a bare
# cloud image is not guaranteed to ship either.
packages:
- tmux
- curl
- ca-certificates
runcmd:
# Preinstall rig so the box can converge — and re-converge — via
# 'rig bootstrap kimi-box'. @RIG_REPO@/@RIG_REF@ are the pin point (#81):
# box substitutes them at mint from the RIG_REPO/RIG_REF environment
# (default heavy-duty/rig @ main — unpinned, tracking main, the same
# honest edge as rig's own unpinned box install, until rig#32 ships a
# release flow). The pin covers both the installer fetched AND the tree
# it installs, so a branch under review is testable end to end.
# HOME=/root: cloud-init runs runcmd as root but with NO $HOME in the
# environment, and the rig installer (set -u) reads $HOME for its DEST —
# measured live: the mint died with "HOME: unbound variable" without it.
- curl -fsSL https://raw.githubusercontent.com/@RIG_REPO@/@RIG_REF@/install.sh | HOME=/root RIG_REPO="@RIG_REPO@" RIG_REF="@RIG_REF@" bash