Everything below applies to every command.
Reading input from files and stdin
Any flag that takes JSON or a list also accepts @path to read a file, or @-
to read stdin.
sim workflows import --workflow @wf.json
sim tables rows query tbl_123 --filter @filter.json
cat wf.json | sim workflows import --workflow @-List flags
Primitive lists take space-separated values. With @, the file supplies one
value per line:
sim files mv --file-ids file_1 file_2 --to Archive
sim files mv --file-ids @file-ids.txt --to Archive
printf 'file_1\nfile_2\n' | sim files mv --file-ids @- --to ArchiveArrays of objects stay JSON.
Filtering table rows
--filter takes the same predicate tree the API uses: all (AND) or any (OR)
groups of {field, op, value} conditions, nestable.
sim tables rows query tbl_123 \
--filter '{"all":[{"field":"status","op":"eq","value":"open"},
{"field":"score","op":"gt","value":10}]}' \
--limit 50Operators: eq, ne, gt, gte, lt, lte, in, nin, contains,
ncontains, startsWith, endsWith, like, ilike, nlike, nilike,
isEmpty, isNotEmpty, isNull, isNotNull.
--sort is also JSON, an ordered list of keys:
sim tables rows query tbl_123 --sort '[{"field":"createdAt","direction":"desc"}]'Pagination
List commands page automatically up to --limit, which defaults to 100. Pass
--limit 0 to fetch everything:
sim logs list --limit 0 --output json > all-logs.jsonDestructive commands
Deletions require an explicit selector and --yes. There is no "delete
everything" default:
sim tables rows batch-delete tbl_123 --row row_1 row_2 --yes
sim files delete file_123 --yesWithout --yes the command explains what it would have destroyed and stops.
batch-delete and batch-update carry the default --limit of 100, so a
filter matching more rows than that silently affects only the first 100. Pass
--limit 0 to affect every matching row.
Exit codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Anything else — API error, bad configuration, invalid arguments, or a missing --yes |
Errors print one line to stderr, prefixed Error:, plus the API's error code and
validation details when it supplies them. Failures are safe to branch on:
if ! sim workflows run wf_7Yb2 --output json > result.json; then
echo "run failed" >&2
exit 1
fiAn unexpected error prints a stack trace — that is a bug in the CLI, so please open an issue.
Selecting workflow output
--select-output takes blockName.field selectors. Fields that a run did not
produce are simply omitted:
sim workflows run wf_7Yb2 --select-output agent_1.content --output jsonPolling a long run
Start the run asynchronously, then poll its status:
run_id=$(sim workflows run wf_7Yb2 --async --output json | jq -r '.runId')
until sim workflows runs get "$run_id" --workflow wf_7Yb2 --output json \
| jq -e '.status | IN("completed","failed","cancelled")' > /dev/null; do
sleep 5
done
sim logs get "$run_id" --traceworkflows runs get is the lightweight status check; logs get is the full
diagnostic. For a paused run, the status includes the context ID that
sim workflows runs resume needs.
Working with folders
Every folder-backed resource — workflows, tables, files, knowledge —
shares the same 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 the resources at a path plus that folder's direct children, never
deeper. Its ref column is the value to pass to the next command. Use list for
resources only, or folders ls for folders only. A leading / is optional.
A nightly job, end to end
#!/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
run_id=$(sim workflows run wf_7Yb2 --input '{"source":"nightly"}' | jq -r '.runId')
if [ "$(sim workflows runs get "$run_id" --workflow wf_7Yb2 | jq -r '.status')" != "completed" ]; then
sim logs get "$run_id" >&2
exit 1
fi