Unikraft
Open-source AI coding skills for Claude Code, Cursor, Copilot, and AI agents
npx -y skills add guillempuche/ai-standards --skill unikraftAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
Unikraft CLI (`unikraft`) commands for building and deploying to Unikraft Cloud. Use when working with Kraftfiles, deploying unikernels, or managing Unikraft Cloud instances/services/images. Covers the new `unikraft` CLI that replaces the legacy kraftkit `kraft`.
SKILL.md
13.9 KB, as published. Nobody here has run it
Unikraft CLI Reference
Build and deploy unikernels with the unikraft CLI.
- Documentation: https://unikraft.com/docs/cli
- CLI source & releases: https://github.com/unikraft-cloud/cli
- Platform: https://unikraft.cloud
Targets the new unikraft CLI 0.4.x (verified against 0.4.1) and the Unikraft Cloud REST API v1.
Run unikraft version to check; if the major or minor differs, re-verify flags/commands against --help before following this skill.
New CLI vs legacy kraftkit — they are different tools
The binary is unikraft (from unikraft-cloud/cli).
It replaces the legacy kraftkit kraft (v0.12.x).
They are separate programs with:
- a different command tree (
unikraft run/unikraft build/unikraft instances …, notkraft cloud deploy), - a separate auth store — a
kraft login/UKC_TOKENenv from kraftkit does not authenticateunikraft; you must rununikraft login(see below). The new CLI writes its own profile under~/.config/unikraft, kraftkit uses~/.config/kraftkit, - packaging split from deploy —
unikraft build --output <ref>publishes an image, thenunikraft run --image <ref>deploys it (kraftkit did both in onekraft cloud deploy).
If you see kraft, UKC_TOKEN, kraft cloud, or --rollout in a config or runbook, it is the legacy CLI — translate it to the new commands here.
Important: running commands
When working with unikraft commands:
- Show the command first — display it in a copy-paste code block before running it.
- Authenticated (cloud) commands need a login — anything hitting Unikraft Cloud (
run,instances,services,images,metros,api, a publishingbuild) fails withprofile not setupuntilunikraft loginhas run in that environment. The AI's shell may not be logged in; if a command returnsprofile not setup, hand it to the developer to run. - Let the developer run it when a login or a real deploy is involved.
Installation
-
CI (GitHub Actions):
unikraft/setup-action@v1— installs the CLI and logs in headlessly. Inputs:version(latest/stable,dev/staging, or a release tag),token(login token),organization. It downloads the release assetunikraft-cli_<version>_<os>_<arch>.tar.gzfromunikraft-cloud/cli.- uses: unikraft/setup-action@v1 with: version: 0.4.1 token: ${{ secrets.KRAFTCLOUD_TOKEN }} organization: my-org -
Local:
unikraft upgradeself-updates an installed CLI. Otherwise pull the tarball for your platform from https://github.com/unikraft-cloud/cli/releases (it holds theunikraftbinary at its root). -
Nix: the CLI is not in nixpkgs (only the legacy
kraftis), but the Unikraft team maintains a NUR flake atgithub:unikraft/nurexposingpackages.<system>.{unikraft-cli, unikraft-cli-staging, kraftkit}(+ an overlay). Add it as a flake input and takeunikraft-cli— orunikraft-cli-stagingwhile the stable attr is being fixed upstream.
Authentication
The new CLI reads the token from a file or stdin, not an env var, and associates the session with an organization.
# From a file:
unikraft login --token /path/to/token --organization my-org
# From stdin (no token on disk / no token in argv):
printf '%s' "$UKC_TOKEN" | unikraft login --token - --organization my-org
--organization is resolved from the control plane if omitted.
A successful login stores a profile (named after the organization) under ~/.config/unikraft.
Manage profiles with:
unikraft profile list # profiles + their metros + which is active
unikraft profile use <name> # switch active profile
Global flags / env available on every command: --profile ($UNIKRAFT_PROFILE), --config ($UNIKRAFT_CONFIG), --timeout ($UNIKRAFT_TIMEOUT), --log-level ($UNIKRAFT_LOG_LEVEL), --log-type, --[no-]telemetry.
Metros
Most write operations take --metro <m>.
List them with unikraft metros list:
| Use (current) | Endpoint |
|---|---|
fra, dal, sin, was, sfo | https://api.<metro>.unikraft.cloud |
unikraft metros list also shows legacy metros fra0, dal0, sin0, was1 on api.<metro>.kraft.cloud — these are the old kraft.cloud endpoints.
Use the suffix-less names only; treat any <metro>0 as legacy.
[!IMPORTANT] Only the create verbs take
--metro—unikraft runandunikraft services create. The read/manage verbs (instances list/get/delete/logs,images list,services get) reject--metrowithunknown flag --metro; they take a bare name (the logged-in profile spans metros) or a--filter 'metro==<m>'. This bites in CI: piping a failedinstances delete <name> --metro frathrough|| truesilently skips the delete, and the nextrunthen fails with "instance already exists".
Command tree
Commands
unikraft run # Run an image as an instance (deploy)
unikraft build # Build a Unikraft project into a container image
unikraft tui # Browse resources in a TUI
Resources
unikraft metros # List/inspect cloud metros
unikraft quotas # Show quota usage
unikraft instances # Manage instances (aliases: instance, vm, vms)
unikraft services # Manage service groups (svc, svcs)
unikraft volumes # Manage persistent volumes (vol, vols)
unikraft certificates # Manage TLS certificates (cert, certs)
unikraft images # Manage images (image, img, imgs)
Utilities
unikraft api <endpoint> # Authenticated raw REST call (e.g. /v1/instances)
unikraft version # Version info
unikraft upgrade # Self-update the CLI
unikraft completion # Shell completions
Config
unikraft login / logout # Authentication
unikraft profile # get / list / use
unikraft config # Manage CLI configuration
Build (package an image)
# Build the project in the current directory and PUBLISH to the registry.
# The <org> prefix is your organization (see `unikraft profile list`).
unikraft build . --output <org>/my-app:latest
# Build and save to a LOCAL OCI archive (no publish):
unikraft build . --output ./dist/my-app.oci.tar
# Build-time inputs and secrets:
unikraft build . --build-arg VERSION=1.2.3 --secret id=npm,src=$HOME/.npmrc
Flags: -o/--output, --build-arg, --no-cache, --secret, --ssh, --insecure, plus the global --timeout=<duration>.
The input path defaults to ..
Run (deploy an instance)
# Deploy a new instance exposing an HTTPS service:
unikraft run --metro fra --image <org>/my-app:latest \
-p 443:8080/http+tls -p 80:443/http+redirect \
-m 2048M --restart on-failure -e NODE_ENV=production
# Preview without deploying:
unikraft run --metro fra --image <org>/my-app:latest --dry-run
Common flags: --metro, --image, -n/--name, -e/--env, -m/--memory (binary units, e.g. 2048M), --vcpus, -p/--publish (<src>:<dest>[/<handlers>]), --domain, --service (attach to an existing service group), --restart (on-failure …), --scale-to-zero, -v/--volume, --replicas, --rm, --follow, --dry-run.
Memory units changed from legacy kraftkit:
-M 2048(MiB) →-m 2048M.
Instances, services, images
unikraft instances list # or: ls
unikraft instances get <name> # inspect
unikraft instances logs <name> # console output
unikraft instances wait <filter> # block until instances match (readiness gate)
unikraft instances delete <name> # remove
unikraft instances start|stop|suspend|restart <name>
unikraft services list # service groups (load balancers)
unikraft services get <name>
unikraft services create … # create a named service group
unikraft services edit <name> # change its config / instance set
unikraft images list # image refs + digests (--filter 'ref~="my-app"')
unikraft images build # same engine as `unikraft build`
unikraft images delete <ref>
volumes (create/attach/detach/clone/import/…) and certificates (create/get/wait/…) follow the same verb pattern.
[!WARNING] Reading an instance dumps its secrets.
instances list -o json/-o yamlandinstances get(without-f) return the instance's fullruntime.env— including secret values such asDATABASE_URL— in cleartext. When you only need identifiers, field-limit the output:unikraft instances list -f name -o quiet(names only, no env). Never pipe an un-limited instance read into shared logs, CI output, or an issue.
Rolling updates (zero-downtime)
The new CLI has no single --rollout flag (kraftkit's kraft cloud deploy --rollout remove_sequential).
A zero-downtime swap of an instance behind an existing service group is composed from primitives:
unikraft run --service=<group> --image <new-ref> …— start a new instance and attach it to the service group that owns the domain/ports (do not re-pass-p/--domain; the group owns those). Omit--nameso the new instance gets a unique name and can run alongside the old one.unikraft instances wait <filter>— wait until the new instance is ready.unikraft instances delete <old-name>— remove the previous instance.
Confirm the exact recommended sequence (and whether a built-in rollout exists in your CLI version) with unikraft run --help / the Unikraft team before relying on it for a production deploy.
[!IMPORTANT] Check quota headroom before a rolling update. The overlap briefly runs two instances, so it needs ~2× the instance's memory + vCPUs at once. Run
unikraft quotas [--metro <m>]first (optional--metro, no subcommand): if adding a second instance would exceed the memory or instance cap, fall back to delete-then-recreate (accepting a brief gap) or request a quota bump. Near the cap, a rollingrunfails with a quota error mid-deploy.
Kraftfile (spec v0.7)
Keep the Kraftfile (and the Dockerfile it references) at the build context root — the rootfs path can't reach parent directories, and the Docker build needs the repo root as context to COPY sibling folders.
spec: v0.7
name: my-server
# base-compat runs the node binary bundled in the image.
runtime: base-compat:latest
labels:
cloud.unikraft.v1.instances/scale_to_zero.policy: "off"
rootfs:
source: ./Dockerfile
format: erofs
cmd: ["/usr/local/bin/node", "/app/dist/main.mjs"]
Deployment example (build once, deploy the image)
# 1) Log in (once per environment).
printf '%s' "$UKC_TOKEN" | unikraft login --token - --organization my-org
# 2) Build + publish a versioned image.
unikraft build . --output my-org/my-app:2026.7.9 --timeout 10m
# 3) First deploy — create the service group, then run into it.
unikraft services create --name my-app \
--domain my-app.example.com 443:8080/http+tls 80:443/http+redirect
unikraft run --metro fra --service my-app --image my-org/my-app:2026.7.9 \
-m 2048M --restart on-failure -e NODE_ENV=production
# 4) Subsequent deploys — see "Rolling updates" above.
# Verify:
unikraft instances list
curl -sf https://my-app.example.com/health
unikraft instances logs my-app-<suffix>
Troubleshooting
| Symptom | Cause / fix |
|---|---|
profile not setup | Not logged in — run unikraft login (kraftkit's login/UKC_TOKEN doesn't count). |
unknown flag --metro on */list | List/get subcommands scope by profile/--filter, not --metro. |
| Image builds but instance won't boot | Check runtime, the cmd path, and that env vars the app needs are passed with -e. |
504 Gateway Timeout | Scale-to-zero cold start — set the scale-to-zero policy off for latency-sensitive services. |
rootfs / COPY build failures | Keep the Kraftfile + Dockerfile at the build-context root; no ../ in the rootfs path. |
Legacy fra0/kraft.cloud host in a ref | Replace with the suffix-less metro (fra, api.fra.unikraft.cloud). |
Unikraft Cloud REST API (v1)
The CLI wraps a REST API.
Reach for it via unikraft api <endpoint> (uses the logged-in profile), or call it directly with a bearer token for automation.
unikraft api /v1/instances # via the CLI (logged-in profile)
curl https://api.fra.unikraft.cloud/v1/instances \
-H "Authorization: Bearer $UKC_TOKEN" # raw, any HTTP client
- Base URLs are metro-scoped:
https://api.<metro>.unikraft.cloud/v1forfra,dal,sin,was,sfo. Never use a<metro>0legacy host. - Every response uses the
{status, message, data, errors, op_time_us}envelope; bulk endpoints return per-itemstatus.
Full endpoint tables, curl examples, and gotchas: references/api-v1.md.
Examples repository
Reference examples (Kraftfiles + Dockerfiles for many runtimes): https://github.com/unikraft-cloud/examples.