Yuvu CLI - command-line interface for Yuvu platform
  • Go 97%
  • Shell 2.6%
  • Makefile 0.3%
Find a file
formatjn2019 654f4c83da ci: publish isolated feature image channels
Main keeps its stable floating tag; feat and feature branches get independent latest and fixed tags with an explicit branch-scoped builder.

Validation: shell syntax and publish-scope regressions. Actual registry publishing remains for CI.
2026-10-04 22:21:55 +08:00
cmd/yuvu feat(task): add lifecycle and quick run commands 2026-06-12 21:22:44 +08:00
deployments/docker/yuvu-cli build: publish yuvu cli binaries and image 2026-06-21 19:38:19 +08:00
internal feat(cli): report runtime image identity evidence 2026-10-04 15:34:07 +08:00
scripts ci: publish isolated feature image channels 2026-10-04 22:21:55 +08:00
vendor feat(cli): report runtime image identity evidence 2026-10-04 15:34:07 +08:00
.dockerignore build: publish yuvu cli binaries and image 2026-06-21 19:38:19 +08:00
.gitignore chore: ignore local IDE metadata 2026-07-23 19:03:03 +08:00
.woodpecker.yml ci: publish isolated feature image channels 2026-10-04 22:21:55 +08:00
go.mod feat(cli): report runtime image identity evidence 2026-10-04 15:34:07 +08:00
go.sum feat: improve node CLI resource handling 2026-07-18 13:56:42 +08:00
Makefile ci: gate publish scope via make check 2026-10-01 18:45:16 +08:00
README.md Expose safe provider and allocation controls in CLI 2026-10-03 22:06:00 +08:00

yuvuCli

Agent-friendly CLI for Yuvu's Protobuf/Connect API.

Task files are editable YAML or JSON representations of yuvu.task.v1.InvokeTaskRequest. Stable platform fields are validated against the Protobuf contract before a request is sent; dynamic capability inputs remain flexible and are validated by Yuvu Core.

Installation

Woodpecker builds Linux amd64/arm64 binaries and publishes the same binaries in the multi-architecture image:

docker.lib.zuixue.site/yuvu/cli:latest
docker.lib.zuixue.site/yuvu/cli:<YYYYMMDD-short-sha>

Run the image directly:

docker run --rm \
  -e YUVU_BASE_URL=http://core.yuvu.zuixue.site \
  docker.lib.zuixue.site/yuvu/cli:latest \
  task list --limit 10

For task/workflow files, mount the current directory:

docker run --rm -i \
  -e YUVU_BASE_URL \
  -e YUVU_TOKEN \
  -v "$PWD:/work" -w /work \
  docker.lib.zuixue.site/yuvu/cli:latest \
  workflow apply daily.yaml --output workflow-id

The image is also a durable binary distribution source:

container="$(docker create docker.lib.zuixue.site/yuvu/cli:latest)"
docker cp "$container:/usr/local/bin/yuvu" ./yuvu
docker rm "$container"
chmod +x ./yuvu

For a local source build, run make build. make dist creates amd64/arm64 tarballs and SHA256SUMS; make image creates yuvu/cli:dev from them.

export YUVU_BASE_URL=http://core.yuvu.zuixue.site

yuvu capability list --output names
yuvu capability get maa.run
yuvu capability definition CAPABILITY_ID
yuvu capability traits CAPABILITY_ID
yuvu capability windows --capability maa.run
yuvu capability windows --format json
yuvu task init openwrt.artifacts.bundle > task.yaml
yuvu task validate task.yaml
yuvu task render task.yaml --format json
yuvu task run task.yaml
yuvu task run task.yaml --set max_attempts=3 --set inputs.jobs=8
yuvu task run - < task.yaml
yuvu task run task.yaml --wait --output status
yuvu task run --async --input jobs=8 --input 'profile="x86_64"' openwrt.build.run
yuvu task get TASK_ID
yuvu task wait --timeout 30m --output status TASK_ID
yuvu task cancel --output id TASK_ID
yuvu task list --status running
yuvu task list --caller-type workflow --caller-id WORKFLOW_ID
yuvu task events TASK_ID
yuvu task attempts TASK_ID
yuvu task summary ROOT_TASK_ID
yuvu task dependencies TASK_ID
yuvu task dependents TASK_ID
yuvu task events --follow TASK_ID
yuvu task logs --follow --stream stderr --timestamps TASK_ID
yuvu task watch --exit-code TASK_ID
yuvu task graph TASK_ID
yuvu task inputs TASK_ID
yuvu task outputs TASK_ID
yuvu task output TASK_ID OUTPUT_NAME
yuvu task output download TASK_ID OUTPUT_NAME --file ./output.bin
yuvu task output download --all --dir ./outputs TASK_ID
yuvu task export --dir ./task-archive TASK_ID
yuvu task rerun --output id TASK_ID
yuvu task retry --force --wait --output status TASK_ID
yuvu task dependency add --output id TASK_ID DEPENDS_ON_TASK_ID
yuvu task dependency remove --output status TASK_ID DEPENDS_ON_TASK_ID
yuvu task dependency edit --add DEPENDS_ON_TASK_ID --remove OLD_DEPENDS_ON_TASK_ID TASK_ID
yuvu task export-python task.yaml > task.py

Allocations and concurrency windows

Concurrency is enforced per capability (max_concurrency). yuvu capability windows shows the running occupants, the window limit, and the tasks waiting in ready, so max_inflight_reached rejections no longer require direct database access:

yuvu capability windows
yuvu capability windows --capability maa.run --format json

Managed resource allocations (leases) are visible without hand-written REST:

yuvu allocation list
yuvu allocation list --include-released
yuvu allocation show ALLOCATION_ID --format json
yuvu allocation renew TASK_ID
yuvu allocation release ALLOCATION_ID --operator OPERATOR --reason 'provider stopped' --force

allocation renew extends the task lease through RenewTaskLease. allocation show scans active and released records by allocation id and exits 4 (not found) when the id is unknown. Release requires an auditable operator and reason. Use --force only after confirming the provider process has stopped; a lease timeout alone is not stop confirmation.

Provider inspection and managed operations use the Core API:

yuvu provider list CAPABILITY_ID
yuvu provider get PROVIDER_ID
yuvu provider pin PROVIDER_ID https://node.example.test:9083
yuvu provider unpin PROVIDER_ID
yuvu provider restart PROVIDER_ID

provider list is scoped to one capability. Restart is available only for agent-managed instances; it does not restart arbitrary external providers.

Public resources and templates

yuvuCli reads reusable task and workflow templates from the public yuvuResources manifest. Every downloaded file is verified by SHA-256 and stored as a last-known-good cache, so an already used template remains available during a temporary repository outage.

yuvu resources status
yuvu resources refresh
yuvu template list
yuvu template show maa/daily
yuvu template validate maa/daily
yuvu template render maa/daily --set tasks.fight.inputs.stage=CE-6
yuvu template run maa/daily --set tasks.fight.inputs.stage=CE-6 --wait

Templates define an explicit allow_overrides list. The CLI rejects any override outside that list before contacting Core. Runtime secrets, node permissions, mount roots, and Docker grants are not resource-template fields. Use YUVU_RESOURCE_MANIFEST_URL to select another reviewed manifest and YUVU_RESOURCE_CACHE to select the local cache directory. Set YUVU_RESOURCE_REVISION to pin an exact content revision for production or rollback. Add --offline to template commands to require cached resources only. A downloaded template is promoted to last-known-good only after the CLI has parsed and validated its task or workflow document.

Node deployment control uses the same Protobuf/Connect contract. It is meant for operator-side upgrades and smoke checks, replacing hand-written control HTTP requests:

export YUVU_NODE_TARGETS='{"nas123":{"url":"http://192.168.99.123:39110","controller_id":"yuvu-core","secret_env":"YUVU_NODE_123_SECRET"}}'
export YUVU_NODE_DEFAULT=nas123
export YUVU_NODE_123_SECRET=...

yuvu node targets
yuvu node facts
yuvu node runtime report
yuvu node runtime report --all-nodes --format json
yuvu node runtime exec RUNTIME_SESSION_ID -- nvidia-smi
yuvu node deployments list --check-update
yuvu node adapter validate --instance restic --image registry/restic:latest --port 0:18115 --mount /config/restic:/config --mount /data/restic:/data
yuvu node adapter deploy --instance restic --image registry/restic:latest --port 0:18115 --mount /config/restic:/config --mount /data/restic:/data --core-url http://core:8080
yuvu node deployment show core --compose
yuvu node deployment show --deployment core --format json
yuvu node bootstrap show core --compose
yuvu node bootstrap plan core --tag latest
yuvu node bootstrap upgrade core --tag latest --apply
yuvu node check-update core notify rclone-adapter
yuvu node update core notify
yuvu node status core
yuvu node logs rclone-adapter
yuvu node exec rclone-adapter -- rclone version
yuvu node exec --timeout 60 --max-output 1048576 openwrt-build -- git status --short
yuvu node exec --container yuvu-runtime-RUNTIME_ID -- nvidia-smi
yuvu node restart notify
yuvu node check-update yuvu-node
yuvu node update yuvu-node

node adapter validate performs a read-only policy and deployment-plan check. node adapter deploy validates first, then carries the allocated port, provider base URL, and deployment trace into the signed deploy request. Set --core-url to enable provider registration without manually assembling its environment. node check-update, node update, and lifecycle commands accept one or more instance ids. The CLI signs every request from the complete Protobuf control payload; the shared secret is read from the environment or secret_env and is never written to task files. yuvu-node and yuvuNode are the only self-upgrade aliases for yuvuNode itself.

node deployment show/export report the declared plan plus the runtime facts from the node runtime report: resolved_image_digest, runtime_state (state, health, running, started_at, restart_count, configuration drift), and instances[]. When the runtime report is unavailable the command still shows the declared plan and marks runtime_state.status as unavailable.

Instance-taking commands accept --instance and deployment-taking commands accept --deployment as alternatives to the positional id, so an instance id and a deployment id are no longer confused. Passing both forms is rejected. Credential and target errors name the exact missing environment variable and list the configured node targets.

node exec is a bounded, non-interactive diagnostic command for one managed container. Pass the node instance id positionally, or pass a full managed container name with --container yuvu-<instance> (the CLI strips the yuvu- prefix so yuvuNode derives the exact container name; this is how runtime containers are addressed). The two forms are mutually exclusive. Options must precede the instance id. Arguments after -- are sent as an argv array without implicit shell parsing, TTY, or stdin. Use an explicit -- sh -lc '...' only when shell syntax is genuinely required. Remote stdout and stderr are printed directly in the default text format; JSON and YAML keep the typed execution result.

node runtime exec addresses a model runtime container directly by session id. Pass the bare session id, the runtime instance id (runtime-<session>), or the full managed container name (yuvu-runtime-<session>); the CLI normalizes the reference to the runtime-<session> instance id that yuvuCore derives and the node expands to yuvu-runtime-<session>. It shares node exec's argv, timeout, max-output, and output-format contract.

task run accepts either a YAML/JSON task file, stdin (-), or a capability name for quick mode. Repeat --input key=value to build dynamic inputs. Repeat --set path=value to override any task field in file, stdin, or quick mode. Values are parsed as JSON when possible and otherwise remain strings.

task logs prints human-readable log text by default. It supports --stream stdout|stderr|log, --since 10m, and --timestamps; use --format json|yaml for the underlying structured events. task watch prints status and progress changes, and --exit-code fails when the Task does not succeed.

task output download --all downloads every artifact and bundle output using safe output names and refuses to overwrite files unless --overwrite is set. task export creates a portable directory containing task metadata, inputs, outputs, graph, events, text logs, and downloadable outputs.

task rerun creates a new independent TaskInvocation from the original request snapshot. It clears the original idempotency key, parent, dependencies, and schedule. Workflow output references are materialized from their source task before the new task is created.

task retry schedules another attempt on the same failed, expired, or blocked TaskInvocation. By default it respects retryability and the configured attempt budget; --force permits a non-retryable task and extends the budget by one attempt when needed.

For scripts and agents, use --fields id or --fields status to keep stdout to a single stable value; --output remains as a legacy alias. Status values are lowercase (succeeded, failed, ready) to match workflow output. Full responses support --format json and --format yaml. Pass global --machine before the command to emit errors as JSON on stderr with a stable exit_code.

Exit codes are 1 general failure, 2 invalid RPC argument, 4 not found, 5 timeout, 6 unavailable, and 7 cancelled.

Workflow planning

Workflow files declare a task DAG. The CLI validates every task against yuvu.task.v1.InvokeTaskRequest, rejects missing dependencies and cycles, and produces a deterministic topological plan.

api_version: yuvu/v1
kind: Workflow
metadata:
  name: build-and-deploy
  idempotency_key: release-2026-06-12
  retry_policy: partial_allowed
tasks:
  build:
    capability: openwrt.build.run
    execution_mode: async
    inputs:
      profile: x86_64
  deploy:
    capability: firmware.deploy
    execution_mode: async
    depends_on: [build]
yuvu workflow validate workflow.yaml
yuvu workflow validate --remote=false workflow.yaml
yuvu workflow plan workflow.yaml
yuvu workflow plan workflow.yaml --format json
yuvu workflow apply workflow.yaml
yuvu workflow apply --output workflow-id workflow.yaml
yuvu workflow get WORKFLOW_ID
yuvu workflow wait --output status WORKFLOW_ID
yuvu workflow cancel WORKFLOW_ID
yuvu workflow retry --output workflow-id WORKFLOW_ID
yuvu workflow retry --mode failed_branch WORKFLOW_ID
yuvu workflow retry --mode from_tasks --task build WORKFLOW_ID
yuvu workflow history WORKFLOW_ID

workflow apply submits the complete DAG through the atomic Protobuf WorkflowService. Workflow lifecycle operations and capability validation also use Protobuf RPCs; the CLI does not depend on Core's HTTP JSON endpoints.

Task ordering is always defined by depends_on. Workflows default to retry_policy: full_only; set partial_allowed to permit failed_branch or from_tasks retries. Partial retries preserve dependencies inside the selected subgraph and include every downstream task.

Downstream task inputs can reference outputs from a declared dependency:

deploy:
  depends_on: [build]
  capability: firmware.deploy
  inputs:
    firmware: ${tasks.build.outputs.firmware}

Output references are resolved immediately before execution. Partial retries reuse outputs from successful tasks that were not retried. workflow history shows workflow and task retry lineage.