Configuration
.ztd/ztd.toml is the ONE file you edit. Every dependency’s config — Terraform
variables, the lima instance YAML, cloud-init, the compose env — is generated
inside the ztd binary from ztd.toml + built-in defaults. There is no
terraform.tfvars, no lima/cloud-init/compose file you ever touch directly.
Secrets live separately in .ztd/secrets/*.env (gitignored) — never in ztd.toml,
which is meant to be committed.
Scaffold it with:
ztd initThis writes .ztd/ztd.toml with every key commented out — an all-defaults project
boots as-is; uncomment only what you want to change.
Precedence, for every key, is explicit env > .ztd/ztd.toml > built-in
default (e.g. TARGET=proxmox ./ztd up, ZTD_VCPUS=4 ./ztd up, ZTD_MAX_TURNS=3 ./ztd run … all win over the file).
[vm] — box shape + backend selection
| Key | Env override | Default | Meaning |
|---|---|---|---|
backend | TARGET | local | local (native: vz on macOS, libvirt kvm on Linux) | proxmox | ec2 |
name | NAME | derived ztd-<folder-slug>-dev | VM/domain name — the sanitized basename of the dir you ran ztd from |
vcpus | ZTD_VCPUS | 2 | Virtual CPUs |
memory_mb | ZTD_MEMORY_MB | 4096 | RAM in MiB |
disk_gb | ZTD_DISK_GB | 24 | Disk size in GiB |
username | ZTD_GUEST_USER | dev | Work user created in the guest |
arch | ZTD_ARCH | this host’s arch | Guest CPU architecture (amd64 | arm64) |
image_url | ZTD_IMAGE_URL | "" (derived from arch) | Override the Debian 12 generic qcow2 URL |
repo_dirname | ZTD_REPO_DIRNAME | basename of the dir you ran ztd from | Names the guest work dir /home/<user>/<dirname> |
repo_target | ZTD_REPO_TARGET | "" (derived /home/<user>/<repo_dirname>) | Full path of the work dir in the guest; set only to override |
repo_source (the host tree shared into the guest) is always the dir you ran
ztd from — it is not a ztd.toml key.
[agent] — agent run knobs
| Key | Env override | Default | Meaning |
|---|---|---|---|
skills | ZTD_SKILLS | project | none | user | project | both — ztd skills push mode |
commands | ZTD_COMMANDS | project | Same modes — ztd commands push mode |
max_time | ZTD_MAX_TIME | 3600 | Wall-clock cap (seconds) for ztd run |
max_turns | ZTD_MAX_TURNS | 0 (off) | Agent-iteration cap via a PostToolBatch hook |
[proxmox] — only read when backend = "proxmox"
Credentials (endpoint, api_token) are NOT here — see
Secrets below.
| Key | Env override | Default | Meaning |
|---|---|---|---|
node | TF_VAR_proxmox_node | pve | Target PVE node |
datastore | TF_VAR_proxmox_datastore | local-lvm | Datastore for the VM disk |
image_datastore | TF_VAR_proxmox_image_datastore | local | Datastore holding the imported cloud image |
snippet_datastore | TF_VAR_proxmox_snippet_datastore | local | Datastore for the cloud-init snippet |
bridge | TF_VAR_proxmox_bridge | vmbr0 | Network bridge |
ssh_username | TF_VAR_proxmox_ssh_username | root | Linux user on the node for snippet upload over SSH (NOT the API user) |
insecure | TF_VAR_proxmox_insecure | false | Skip TLS verification (self-signed PVE cert) |
vm_id | TF_VAR_proxmox_vm_id | 0 (auto-picked) | Force a specific VMID; 0 = ztd picks one (see the proxmox how-to) |
[aws] — only read when backend = "ec2"
Credentials (AWS_*) are NOT here — see Secrets below.
| Key | Env override | Default | Meaning |
|---|---|---|---|
region | TF_VAR_aws_region | us-west-2 | Region (also the provider region) |
instance_type | TF_VAR_aws_instance_type | t3.micro | Instance type |
ami | TF_VAR_aws_ami | "" | Override AMI; empty = latest official Debian 12 for region+arch |
subnet_id | TF_VAR_aws_subnet_id | "" | Empty = default VPC’s default subnet |
security_group_id | TF_VAR_aws_security_group_id | "" | Empty = ztd creates one (tag-scoped, SSH-only) in the default VPC |
ssh_ingress_cidr | TF_VAR_aws_ssh_ingress_cidr | 0.0.0.0/0 | SSH ingress CIDR for the created SG — lock this to your <ip>/32 |
Secrets (.ztd/secrets/)
Gitignored, host-side only, never read from ztd.toml:
.ztd/secrets/proxmox.env—TF_VAR_proxmox_endpoint,TF_VAR_proxmox_api_token. Copyexamples/proxmox.env.exampleto start..ztd/secrets/aws.env—AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, etc. Copyexamples/aws.env.exampleto start.
State and other project directories under .ztd/
ztd.toml— the one config file (committed).state/terraform.tfstate— Terraform state for thelocal/proxmox/ec2backends (gitignored; local to this project checkout).keys/— the per-VM ephemeral SSH keypair (gitignored).secrets/— operator-supplied host-side credential files (gitignored).claude/{skills,commands}/— project skills/commands pushed to the guest (tracked);*-incoming/staging dirs for pulled-back review (gitignored).mnt/— sshfs mountpoint for a remote guest’s repo (gitignored).runs/<run_id>/— audit records exported byztd audit(manifest, console, transcript, command log; gitignored).ztd runwrites the launch manifest here.