CI & Non-Interactive Use
Every thyme command runs without a terminal. A prompt is only ever reached when a TTY
is attached and no flag already supplied the value, so a pipeline never blocks on a
picker nobody can answer.
# Either position works
thyme --ci upload my-task -w ws_123abc -p proj_456def --tag v2
thyme upload my-task -w ws_123abc -p proj_456def --tag v2 --ciFlags
| Flag | Alias | Description |
|---|---|---|
--ci | Never prompt. Confirmations are answered yes; any other missing value is an immediate error. | |
--yes | -y | Answer confirmations yes, but keep the other prompts. Useful on a terminal when you only want to skip Proceed with upload?. |
Both are accepted on the root command and on every command that can prompt
(init, new, run, login,
upload).
Automatic detection
You usually don't need --ci at all. Non-interactive mode turns itself on when either:
- any of
CI,CONTINUOUS_INTEGRATION,THYME_CI, orTHYME_NON_INTERACTIVEis set to anything other than0,false,off,no, or empty — this covers GitHub Actions, GitLab CI, CircleCI, Buildkite, and most others out of the box; or - stdin or stdout is not a terminal — a pipe, a container started without a TTY, or a subprocess spawned by a coding agent.
--ci exists to force the behavior where none of that applies, and THYME_CI=1 does the
same from the environment.
The failure contract
A missing value exits with code 2 and a message naming the flag that supplies it, along with the accepted values:
■ A workspace is required when prompts are unavailable (--ci was passed).
│ Pass `--workspace <id>`. Available: ws_123abc (Acme), ws_456def (Acme Staging)
Missing interactive inputs use exit code 2. Ordinary task, authentication, and upload failures use 1. Some local simulation diagnostics are warnings rather than process failures; see known limitations.
Every prompt and its flag
| Command | Prompt | Non-interactive path |
|---|---|---|
init | project name | thyme init <name> argument |
new | task name | thyme new <name> argument |
run | task picker | thyme run <task> argument |
run --simulate-callbacks | outcome picker | --callback <outcome> |
login | re-authenticate? | answered yes |
login --token | paste API key | piped on stdin |
login --rewrite-api-url | API URL | --api-url <url> |
upload | task picker | thyme upload <task> argument |
upload | workspace picker | -w, --workspace <id> |
upload | project picker | -p, --project <id> |
upload | version tag | -t, --tag <tag> |
upload | proceed? | answered yes |
list, logout, api-url, and the
management commands never prompt — they are flag-driven already, and
the management commands print raw JSON to stdout for piping into jq.
Authenticating without a browser
A pipeline can supply THYME_AUTH_TOKEN and skip thyme login. Stored credentials take precedence, so use a clean runner without saved personal credentials. Management calls need a key with the appropriate scopes and workspace binding.
export THYME_AUTH_TOKEN="$THYME_API_KEY" # Console → API Keys → Create KeyIf you do need to log in from a pipeline:
-
thyme login --tokenreads the key from stdin when there's no terminal, keeping it out of your shell history and the process list:echo "$THYME_API_KEY" | thyme login --token -
thyme login --browserlessprints a pairing code and polls, so someone can approve from another device. -
The default browser flow fails immediately without a terminal rather than polling for five minutes for an approval that can't happen.
The optional permissions manifest has a known local loader issue in CLI 0.10.0; do not treat local validation as a substitute for upload and cloud permission checks.
Output
Spinners collapse to plain single-line output off a TTY, so CI logs stay readable instead of filling with animation frames. Colors follow the usual rules — disabled when stdout isn't a terminal, kept when a CI variable is present, since most CI log viewers render ANSI.
A pipeline example
export THYME_AUTH_TOKEN="$THYME_API_KEY"
export THYME_API_URL="$API_URL" # API base supplied by your deployment
export SIMULATE_ACCOUNT="$EXECUTION_ACCOUNT"
export RPC_URL="$CHAIN_RPC_URL"
# Evaluate the task and inspect callback diagnostics
thyme run my-task --ci
thyme run my-task --callback onSuccess
thyme run my-task --callback onFail:reverted
# Ship an immutable version
thyme upload my-task --ci \
-w "$THYME_WORKSPACE_ID" \
-p "$THYME_PROJECT_ID" \
--tag "v$BUILD_NUMBER"The example assumes Deno and project dependencies are installed, the task returns calls and defines the selected callbacks, and it does not hit the manifest-loader limitation above. Callback diagnostics require inspection because callback errors do not necessarily fail the command.
Tags are immutable; choose a distinct label for changed content, such as a build number or release version. Re-uploading the exact
same name, tag, and checksum is idempotent and reuses the existing function ID; reusing a
tag with different code is a conflict. See thyme upload.
Next steps
- Configuration & Environment — where credentials and config live.
- Management Commands — the flag-driven API surface for everything the versioned management API supports.