LUCIRUNSDOCSPUBLIC CI

UI + CLI.
Same runs. Same values.

Run pages keep diagnosis close: parent failure, affected execution, actual log evidence, then configuration at recorded revision.

Read-only Nushell commands

luci status --all
luci repo r#'<repo>'#
luci show r#'<run-id|repo>'#
luci watch r#'<run-id|repo>'# --logs --timeout 30m
luci log r#'<run-id|repo>'# r#'<child-id or job>'#
luci artifact r#'<run-id|repo>'# r#'[path]'#

Run IDs display as shortest unique proquints. UI copy actions use complete proquints. CLI accepts unique prefixes, repository names, or decimal IDs.

watch resolves once, follows that run only, and has no default timeout. --timeout needs a positive duration. It exits 0 for success, 1 for an unsuccessful run, 2 for command or operational errors, 124 for timeout, and 130 when cancelled.

Configuration

job "test" {
  image "docker.io/library/alpine:latest"
  trigger { push { branch "trunk" } }
  run "project-test-command"
}

Jobs without triggers are manual-only. Manual submission resolves its requested ref or commit and validates its job before queueing; execution stays pinned to that commit while retaining requested ref provenance. Push filters, schedules, matrices, caches, secrets, and publish targets are defined in direct .ci/*.kdl files.

job "image" {
  build {
    containerfile ".ci/Containerfile"
    context ".ci/image"
  }
  run "test"
}

A job uses exactly one image or build. Build paths are pinned checkout-relative; context "." is allowed, Git metadata is always excluded, and Containerfiles cannot be Git metadata. Luci stages bounded .containerignore-filtered input privately with Docker-compatible negation handling, runs rootless Podman with normal isolated dependency networking but no job secrets, mounts, socket, registry credentials, or host network, then executes immutable image ID. Matrix children reuse same build output. Base tags refresh each build; keep package-cache freshness in Containerfile RUN steps.

Luci retains only its exact-labelled, untagged, unreferenced build images and intermediate layers. It expires old entries and conservatively budgets their engine-reported bytes, never force-removes or globally prunes images. Before a build it queries Podman's graphroot allocation and use, then requires configured free headroom. These are retention and preflight controls, not an in-flight disk quota or hard storage isolation.

Registry jobs write an OCI archive during run, then use publish "registry" { from "image.oci" to "registry.example/app:tag" }. Luci rejects legacy image registry publishing, stale checkout outputs, cache/artifact overlap, and non-registry targets; it stages archive input and copies it with daemonless Skopeo. Only a successful publication emits machine-readable evidence with requested destination, manifest digest, and canonical repository@digest reference.

Local operator maintenance

luci delete r#'<run-id>'#
luci delete r#'<run-id>'# --confirm r#'<full-id>'#
luci check --run r#'<run-id>'# --json

Run these locally with access to Luci data, not through public SSH. Delete without confirmation only previews run metadata, files, and reclaimable bytes. Use the complete ID returned by preview for confirmation. Queued or active runs cannot be deleted. Deletion hides parent and children and removes their logs and artifacts; append-only history, caches, Git, and published content remain. Repeat confirmed deletion to retry interrupted cleanup.

Both commands accept --json. check without --run inspects all runs; its JSON is {"findings":[...]}. Check exits 0 when healthy, 1 for findings or unknown run, 2 for invalid arguments or operational errors. Delete exits 0 after preview or cleanup, 1 for selector, confirmation, or busy-run rejection, 2 for operational errors.

Security model

Web UI and local CLI read same Luci data. SSH endpoints accept restricted ci commands, not copied local luci commands. luci delete and luci check are local operator-only. Connect using deployed endpoint details, then run ci docs.

Repositories, logs, and artifacts are public. Masking is best-effort, never a secret boundary.

Artifact sets stage privately, then become visible atomically. Durable cache and auth mounts live under Luci data storage, are owner-only, and serialize access with private locks. Secret binds are read-only and temporary secret files never enter workspaces, caches, artifacts, or logs.

See llms.txt for complete machine-readable reference.