General Input
Exec

geni exec bash

Run a bash command with credentials resolved by the cloud and injected as environment variables.

geni exec bash [flags] -- <command>

Runs a bash command on the operator's machine with one or more credentials' env vars injected. The cloud resolves the credentials under audit; the CLI injects them into a fresh subprocess; output streams back through a scrubber that redacts the resolved secrets.

The agent's general-purpose execution primitive. Use it for anything that's a shell command, curl, git, gh, aws, language-specific CLIs, ad-hoc scripts.

Synopsis

geni exec bash \
  --cred cred_01HX… --reason "Validating Slack token" \
  --cred cred_01HY… --reason "Reading GitHub repo" \
  -- 'curl -H "Authorization: Bearer $SLACK_ACCESS_TOKEN" https://slack.com/api/auth.test'
FlagRequiredNotes
--cred <id>repeatCredential id to inject. Use as many times as you need (one per credential). Each needs a paired --reason.
--reason <text>repeatWhy this credential is being accessed. Lands in credential_access_logs and is shown to the operator. Re-state on every call, the audit log is per-call.
--cwd <path>noWorking directory. Defaults to the current working directory.
--yesSeparator. Everything after is the bash command, passed to bash -lc as a single string.

The command is executed under bash -lc in a fresh shell (no inherited shell aliases, no shared state with previous calls). Chain with && if multiple commands need to share state.

What env vars get set

The cloud derives env var names from the credential's secret schema. For each declared field, geni sets <SERVICE>_<FIELD>_<id> (e.g. $SALESFORCE_ACCESS_TOKEN_KG931YMIE9, $SALESFORCE_INSTANCE_URL_KG931YMIE9, $AWS_ACCESS_KEY_ID_K3N2…, $AWS_SECRET_ACCESS_KEY_K3N2…). The <id> suffix is the credential id with the cred_ prefix stripped and uppercased — guarantees no two credentials of the same service collide in one call. Plus a few SDK-canonical aliases ($GH_TOKEN, $OPENAI_API_KEY, $SLACK_BOT_TOKEN) without the suffix, where the official tooling reads a fixed env var name.

Don't derive these names, read them from geni credential list --json (envVars field) or the operation's docs (Bash env vars line). The names you see there are the names geni will set.

In addition, two platform env vars are always set regardless of --cred flags:

  • $PLATFORM_API_KEY, short-lived bearer for $PLATFORM_BASE_URL/... calls.
  • $PLATFORM_BASE_URL, the cloud's base URL.

Output

$ geni exec bash --cred cred_01HX… --reason "..." -- 'curl -s https://api.example.com/'
{"data":[...]}

stdout, stderr, and exit code are forwarded to the caller transparently, same as any well-behaved Unix command.

The agent's transcript will also see geni's own status lines on stderr (one line per resolved credential, prefixed with geni:):

geni: resolved cred_01HX… (Slack, Acme prod) → SLACK_ACCESS_TOKEN_01HX…, SLACK_BOT_TOKEN

Suppress with --quiet if you want stderr to carry only the subprocess's output.

Output scrubbing

Every secret value the cloud returns is registered with a streaming scrubber before the subprocess starts. Any literal occurrence in stdout or stderr gets replaced inline:

[REDACTED:cred_01HX…]

The scrubber operates on bytes, not on shell-escaped output, so a token that ends up in a JSON response, a log line, an error message, or anywhere else gets caught. Non-secret config values (e.g. Salesforce's instanceUrl, AWS's region) are not scrubbed, they're not secrets, and redacting them would mangle URLs and metadata in output.

Exit codes

CodeMeaning
0Subprocess exited zero
1–125Subprocess's own exit code
77Cloud refused to resolve one of the requested credentials (--cred rejected). Agent should not retry.
78Runner session missing or expired. Operator needs to run geni login.
125Internal geni error (resolver unreachable, malformed flags).

Examples

One credential, simple curl

geni exec bash \
  --cred cred_01HX7AB --reason "Listing Salesforce contacts" \
  -- 'curl -s -H "Authorization: Bearer $SALESFORCE_ACCESS_TOKEN_01HX7AB" "$SALESFORCE_INSTANCE_URL_01HX7AB/services/data/v59.0/sobjects/Contact"'

Multiple credentials, fan-out

geni exec bash \
  --cred cred_slackA --reason "Posting to #engineering" \
  --cred cred_slackB --reason "Posting to #marketing" \
  -- 'curl -s -X POST "https://slack.com/api/chat.postMessage" -H "Authorization: Bearer $SLACK_ACCESS_TOKEN_SLACKA" -d "channel=#engineering&text=hi" && \
      curl -s -X POST "https://slack.com/api/chat.postMessage" -H "Authorization: Bearer $SLACK_ACCESS_TOKEN_SLACKB" -d "channel=#marketing&text=hi"'

The <id> suffix on every per-credential env var means two credentials of the same service can coexist in one call without colliding — $SLACK_ACCESS_TOKEN_SLACKA and $SLACK_ACCESS_TOKEN_SLACKB are separate variables. Canonical aliases like $SLACK_BOT_TOKEN (unsuffixed) would still last-write-wins; reach for the suffixed name when fanning out.

Calling a platform service without declaring credentials

geni exec bash \
  -- 'curl -s -X POST "$PLATFORM_BASE_URL/v1/web-search" -H "Authorization: Bearer $PLATFORM_API_KEY" -d "{\"query\":\"general input\"}"'

$PLATFORM_API_KEY and $PLATFORM_BASE_URL are always set; no --cred flag needed.

On this page