Use JSON output and explicit authentication/workspace settings for unattended commands. Enable pipeline failure handling in shell scripts so a failed command is not hidden by a successful parser:
set -euo pipefail
export SIM_API_KEY="${SIM_API_KEY:?missing}"
export SIM_WORKSPACE="${SIM_WORKSPACE:?missing}"
export SIM_OUTPUT=jsonSee Authentication for CI setup. Examples below assume Bash and jq.
Reading input from files and stdin
JSON flags and primitive-list flags accept @path to read a file or @- to read stdin:
sim workflows import --workflow @wf.json
sim tables rows query tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --filter @filter.json
cat wf.json | sim workflows import --workflow @-JSON input and the assembled JSON request body have a 10 MiB limit. JSON flags require JSON, including workflow imports; YAML exports must be converted before import. File-aware text flags, such as secret --value, are identified in the command reference; ordinary string flags do not all support file input.
When Sim runs a command inside Chat, @path reads the Chat sandbox rather than workspace Files. Use sim files read for workspace file content. That embedded invocation has no stdin, so use @path or inline input instead of @-.
List flags
Primitive lists use space-separated values. An input file supplies one value per line:
sim files mv --file-ids wf_3Qm8ZtLpR2yVnKd7BsXwC wf_5Hn1JvTqW9xUcMb4RzPgL --to Archive
sim files mv --file-ids @file-ids.txt --to Archive
printf 'wf_3Qm8ZtLpR2yVnKd7BsXwC\nwf_5Hn1JvTqW9xUcMb4RzPgL\n' | sim files mv --file-ids @- --to ArchiveEmpty list entries are rejected. Arrays of objects remain JSON. Dependency-manifest flags can ignore blank lines and # comments; this exception does not apply to every list file.
Passing a literal leading @
File-aware flags interpret a leading @ as a file reference. Write @@ to pass a literal leading @; only the first character is removed:
sim files share set wf_3Qm8ZtLpR2yVnKd7BsXwC --is-active true --auth-type email --allowed-emails @@example.org
sim secrets set API_HOST --scope workspace --value @@internalWithout escaping, --allowed-emails @example.org tries to open a file named example.org.
Filtering table rows
--filter accepts a predicate tree. Use all for AND, any for OR, and {field, op, value} for a condition. Groups can be nested:
sim tables rows query tbl_9f3c1a05d4b7426e8c2f0917ab35de64 \
--filter '{"all":[{"field":"status","op":"eq","value":"open"},
{"field":"score","op":"gt","value":10}]}' \
--limit 50Operators are eq, ne, gt, gte, lt, lte, in, nin, contains, ncontains, startsWith, endsWith, like, ilike, nlike, nilike, isEmpty, isNotEmpty, isNull, and isNotNull. Supported operators depend on the column type. Omit value for the empty/null checks.
--sort is an ordered JSON list:
sim tables rows query tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --sort '[{"field":"createdAt","direction":"desc"}]'Pagination
Inventory commands such as workflows list and files list, and resource directory ls, fetch all pages by default. Use a limit for a smaller result:
sim workflows list --output json
sim files ls /Reports --limit 50Data/history lists default to 100 items, including table rows and queries, logs, audit/billing events, workflow runs/versions, and knowledge documents/chunks. Connector document lists and other bounded collections also use this default. The command reference states each invocation's limit; these CLI limits differ from API per-page defaults.
--limit 0 fetches every remaining page:
sim logs list --limit 0 --output json > all-logs.jsonPages are fetched sequentially, accumulated in memory, and printed as one result. Each paginated API request fetches at most 100 items. For large datasets, use filters or an explicit limit.
Paginated JSON/YAML output has { data: [...], nextCursor }. The cursor follows the last returned row; null ends pagination:
sim logs list --output json | jq -r '.data[].runId'Commands with --cursor can continue from the previous result. Keep the same scope, resource, filters, and sort order:
sim tables rows list tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --limit 100 --output json > page.json
if next_cursor=$(jq -er '.nextCursor' page.json); then
sim tables rows list tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --limit 100 --cursor "$next_cursor" --output json
fiRun the next command only when the cursor is non-null. --limit applies to each invocation starting at its cursor; --limit 0 --cursor ... fetches all remaining pages. Table-row queries, logs, billing/audit logs, workflow run/version histories, and knowledge document/chunk lists support continuation.
Exit codes
Results go to stdout; diagnostics go to stderr. JSON/YAML modes serialize API errors as {error:{code,message,details?}}. Display formats use Error: plus any supplied code/details. Configuration and argument-parser errors, run-wait outcome messages, and unexpected stack traces can remain text. Do not assume every stderr stream is a single JSON document.
Most successful actions exit 0; API, configuration, or argument failures exit 1. Interactive secret entry cancelled with Ctrl-C exits 130. Other outcomes are command-specific:
| Code | sim whoami |
|---|---|
0 | Verified, or verification skipped with --no-verify |
1 | Missing credential or definitive refusal, including workspace access |
2 | No verification verdict: unset workspace or unreachable endpoint |
| Code | sim workflows runs wait |
|---|---|
0 | Completed |
1 | Failed run or command/request failure |
2 | Cancelled run |
3 | Human pause or unspecified pause kind; input is needed |
4 | Wait timed out |
| Code | Workspace operation wait, or import/fork/push/pull with --wait |
|---|---|
0 | Completed, including completion with warnings |
1 | Failed completion or command/request failure |
3 | Committed operation requires configuration |
4 | Wait timed out |
Both waits default to 3600 seconds; --wait-timeout 0 waits indefinitely. SIM_TIMEOUT_SECONDS independently bounds one API request. A timeout does not cancel the underlying run or operation.
A synchronous or followed workflow run prints its result before exiting 1 for failure/cancellation. A paused run is not failed and can return 0; use runs wait or inspect status if your script requires completion. Fetching a failed run or listing runs only reports their state.
Capture a failure without losing its output:
if sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --output json > result.json; then
printf 'command succeeded\n'
else
status=$?
printf 'command exited %s; inspect result.json and stderr\n' "$status" >&2
exit "$status"
fiFor verification failures, inspect the endpoint, credential, and workspace before logging in again:
if sim whoami --output json > identity.json; then
:
else
status=$?
case "$status" in
1) printf 'profile refused; inspect identity.json\n' >&2 ;;
2) printf 'verification incomplete; check workspace and endpoint\n' >&2 ;;
esac
exit "$status"
fiSee Troubleshooting for recovery and reporting unexpected failures.
Polling a long run
Start asynchronously, retain the run ID, then wait:
run_id=$(sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --async --output json | jq -er '.runId')
sim workflows runs wait "$run_id" --workflow 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --wait-timeout 3600 --output jsonTime-based pauses continue waiting. Human or unspecified pauses return exit 3 and include the pause context needed by sim workflows runs resume. Inspect the saved result before resuming; use sim logs get "$run_id" --trace --output table for diagnostics.
Starting another run is not an idempotent retry of the first. After a lost response or wait timeout, inspect the existing run rather than starting another execution blindly.
Selecting workflow output
--select-output returns named values in blockOutputs on a synchronous run or its streamed result with --follow. It cannot be combined with --async. Use blockName.field selectors; outputs not produced by the run are omitted:
sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --follow --select-output agent_1.content --output jsonFor a finished run, runs get accepts blockName.path or blockId.path. Names resolve against the workflow's current blocks:
sim workflows runs get "$run_id" --workflow 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 \
--select-output 1d4c8f02-7b63-4a19-8e52-63f0a7c5d9b1.content --output jsonDestructive commands
Deletion requires an explicit target and --yes; omission does not select everything:
sim tables rows batch-delete tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --row row_2f81c0a94db54e6f8a13c7e0526bd94a row_6b3e59d0af1c42d7b80e94f3a271c568 --yes
sim files delete wf_8Kd2NpVrY6zTfQa3XwBmS --yesWithout confirmation, the command explains the consequence and stops. Commands that support a non-writing --dry-run do not require --yes for that preview.
For row batch-delete and batch-update, --limit caps how many matching rows one call may change. It has no default: omission affects every matching row. --limit 0 is rejected; use a whole number of at least 1. On batch-delete, an explicit --row list cannot be combined with this filter cap.
Other commands require confirmation for replacement or cancellation too. Read the command reference for consequences, including chat-setting resets and partial table imports. Cancelling an import does not undo rows already written; replace mode clears the table before loading.
Working with folders
Workflow, table, file, and knowledge-base directories share path commands:
sim tables ls Reports
sim tables mkdir Reports/Quarterly
sim tables folders mv Reports/Quarterly Archive/Quarterly
sim tables folders delete Archive --recursive --yesls lists resources at a path and that folder's direct children. It does not descend further. Pass the displayed ref to the next command. Use list for resources only or folders ls for folders only. A leading / is optional.
Organization access and invitations
Organization commands use --organization; workspace commands use --workspace or the active profile. Get userId from organizations members list or workspaces members list when setting member credit caps, including external collaborators.
access-requests mine shows your requests in the selected scope. Organization access-requests list is the Admin inbox across organization workspaces. Discover the target before submitting:
sim workspaces access-requests discover --workspace "$workspace_id" --state requestable --output json
sim workspaces access-requests create --workspace "$workspace_id" \
--target '{"kind":"feature","configKey":"hideTablesTab"}' --reason 'Maintain team data'
sim workspaces access-requests mine --workspace "$workspace_id"An Admin previews a request before applying it. Inspect canApply, changes, and impact: a permission approval changes the governing group for all affected members. Apply the reviewed fingerprint; a conflict requires a new preview:
sim organizations access-requests preview "$request_id" --organization "$organization_id" --output json > preview.json
sim organizations access-requests resolve "$request_id" --organization "$organization_id" \
--action apply --expected-fingerprint "$(jq -er '.fingerprint' preview.json)"Applying a credit-cap request also requires --new-limit-credits greater than the current cap. To decline, use --action decline --reason 'Explanation'.
An Admin can set a cap directly. Zero prevents further credit-consuming usage; null removes only the per-person cap, leaving organization limits in effect:
sim organizations members usage-limit update "$user_id" --organization "$organization_id" --credit-limit 5000
sim organizations members usage-limit update "$user_id" --organization "$organization_id" --credit-limit nullWorkspace invitations accept up to 50 emails. Recipients are processed independently. Any failure makes the CLI print the full result and exit 1; successful invitations and grants remain committed. Inspect failed and current invitations before retrying, especially when delivery was uncertain:
sim workspaces invitations create --workspace "$workspace_id" \
--emails alex@example.com sam@example.com --permission write --membership member --output jsonA nightly job, end to end
This script starts one run, waits for its outcome, and preserves the run ID for recovery. The wait is inside an if so set -e does not exit before outcome handling:
#!/usr/bin/env bash
set -euo pipefail
export SIM_API_KEY="${SIM_API_KEY:?missing}"
export SIM_WORKSPACE="${SIM_WORKSPACE:?missing}"
export SIM_OUTPUT=json
workflow_id=3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8
sim workflows run "$workflow_id" --async --input '{"source":"nightly"}' > started.json
run_id=$(jq -er '.runId' started.json)
if sim workflows runs wait "$run_id" --workflow "$workflow_id" --wait-timeout 3600 > result.json; then
exit 0
else
status=$?
fi
case "$status" in
1|2) sim logs get "$run_id" --trace --output table >&2 || true ;;
3) printf 'run %s needs input; inspect result.json before resuming\n' "$run_id" >&2 ;;
4) printf 'wait expired; inspect existing run %s before retrying\n' "$run_id" >&2 ;;
esac
exit "$status"