Scripts and agents
How to run the nuvelics tool unattended from a script or an AI agent, safely, with the checks to make before every run.
The nuvelics tool is built to be driven by a script or an AI agent with no person at the keyboard. This
page is the set of rules that makes that safe. Most of them exist so that an unattended job cannot act on
the wrong organization or leak a secret.
Always pass -o json. Most commands then print one JSON object on standard output, and every failure prints
one on standard error. The exceptions are the delete, revoke and remove commands (including
story photos rm), the local context and config commands, and login and logout, which print plain
text instead of the envelope. For the confirmation lines, rely on exit code 0 and do not parse standard
output; context list, context current, config list and config get print a plain list or value you
can read. See Output.
A person signs in first
Signing in is a human step. The tool reads no credential from the environment and an unattended job has no
way to get one. A person runs nuvelics login once on the machine, which needs a
keychain. The job then uses what is stored. A machine with no keychain, such as most
build servers, cannot run the tool unattended today.
Start with whoami
Make nuvelics whoami -o json the first call of every run:
nuvelics whoami -o json- Exit
0means you are ready..data.contextis the active context name, which you will need for writes, and.data.organization.idis the organization you are about to act on..data.userisnullfor a service key. - The kind
unauthenticated(exit2) means no credential is stored for the context. The kindforbidden(exit3) fromwhoamimeans the API rejected the stored credential, because it was revoked or can no longer be renewed. Both are hard stops, and a person must sign in again. Report that the machine needsnuvelics login --context <name>and do nothing else. Do not retry, try another context, or look for another way in.
The sign-in check runs on the machine before any request is sent, so on a signed-out machine it costs nothing and changes nothing.
Name the context on every write
Reads use the active context. Anything that creates, changes, approves, pushes or deletes must name its
context, or the tool refuses with ambiguous-context and sends nothing:
nuvelics pitch approve <id> --context acme -o jsonTake the name from whoami, or from a context the person who set up the job chose on purpose. Do not infer
it from what a name looks like; the tool gives names no meaning. Destructive commands also need --yes.
The command reference marks which ones. See Contexts.
Find out what exists
Do not rely on a memorized command list. The tool prints its own:
nuvelics reference -o jsonIt lists every command with its options and what each option accepts, straight from the commands the tool actually has. Lists can be asked what they filter on, as described in Filters and paging.
Handle errors by kind
Branch on error.kind and error.retryable, as set out on Exit codes and errors:
- Retry only when
retryableis true, with a wait between attempts and a small limit. usagemeans fix the command. Do not run it again unchanged.forbiddenis a real answer, not a fault to work around. Report it.rejectedmeans the item's state already rules the action out. Look at the item if you need to confirm, then move on.- Include
requestIdin anything you escalate.
Keep secrets out of commands
No flag takes a secret as its value, because a value on the command line is visible in process lists and
shell history. Pass a secret on standard input with --secret-stdin:
printf '%s' "$SECRET" | nuvelics credential create \
--name "CI bearer" --type bearer --secret-stdin --context acme -o jsonA command that would ask for a hidden value fails at once when there is no terminal, naming
--secret-stdin. It never waits for input nobody can give. Do not print a secret, put it in a log, or echo
it back. The output of nuvelics api-key list never contains a key's secret, so it is safe to log.
What an unattended job must not do
- Do not try to sign in. No
nuvelics login, no borrowed key. Anunauthenticatederror goes to a person. - Do not create or revoke API keys from the command line. The tool has no command for it, on purpose. People manage keys in the web app, on the API keys tab. Do not reach for a direct API call to do the same.
- Do not act outside the organization you were given. If a response names an organization or context you did not expect, stop and report it.
Example: review new pitches
# 1. Ready? Stop here on kind "unauthenticated".
nuvelics whoami -o json
# 2. What can pitches be filtered on?
nuvelics pitch list --limit 1 -o json | jq '.data.filters.available'
# 3. List the new ones, using a field from step 2.
nuvelics pitch list --filter status.eq=new --limit 50 -o json | jq '.data.items[] | {id, title}'
# 4. Act. The write names its context.
nuvelics pitch approve <id> --context acme -o jsonIf step 4 returns rejected, someone already approved or dismissed the pitch. Do not run it again. If it
returns forbidden or not-found, stop and report; neither improves on a retry.
If you would rather give an assistant access through a chat client, with no shell involved, see Agents.