fix(docs): serve JSON-LD in the HTML, fix sidebar spacing, and tighten the CLI guides (#6763)

* docs(cli): use -g for the install, and cut the prose that was not pulling weight

`--global` is valid but `-g` is what every comparable CLI documents, and the
long form only came from the package README. Also drops the yarn tab: it read
`yarn global add sim`, which works on Yarn 1 only — Yarn 2 removed global
installs, so that command fails for anyone on a modern Yarn. Adds `npx sim` for
running without installing.

The guides had accumulated design rationale that belongs in code comments rather
than user docs — why the filter grammar is JSON, why the config section naming
is asymmetric, why an unexpected error keeps its stack trace. Surveying how gh,
Vercel, Turborepo, Deno, Bun and Supabase write theirs, none carry that kind of
justification, and callouts are reserved for content whose absence produces a
wrong result rather than for general asides.

So: 1016 lines to 763, and 12 callouts to 3. The three that remain are the
pairing-code check, that `sim logout` does not revoke the key, and the
`--limit 100` default on `batch-delete`/`batch-update`, which silently truncates
a larger match. Troubleshooting drops the entries whose error message already
contained its own fix and keeps the seven whose cause is not obvious.

* fix(docs): render JSON-LD as native script tags so it reaches the HTML

All four structured-data blocks — WebSite, TechArticle, BreadcrumbList,
SoftwareApplication — were rendered with `next/script`, which never emitted a
script tag. Measured on a production build, `/api-reference/getting-started`
contained zero `<script type="application/ld+json">` elements; the payload
existed only in the `__next_s` client-injection queue and the RSC flight data,
so anything reading the served HTML saw no structured data at all. React was
also logging "Encountered a script tag while rendering React component" on every
page.

`next/script` is for loading and executing JavaScript. JSON-LD is data, and
Next's own guidance is a native `<script>` in the component. `serializeJsonLd`
already escapes the `<` character to its unicode form, which is the
sanitization that guidance calls for, so only the element changes.

Same build, after: three valid tags per page with `WebSite` in `<head>`, and the
injection queue gone entirely.

* fix(docs): scope the flush-separator rule to a container's first separator

`[data-separator]:not([data-separator] ~ [data-separator])` was meant to keep the
first sidebar group flush against the top padding, but `~` only reaches siblings,
so it also matched the first separator inside every expanded folder. Under
Self-Hosting, "Install" lost its top margin and crowded the "Architecture" link
above it — 25px of gap where "Configure" and "Operate" below it had 40px.

`:first-child` expresses the intent directly. Only the four sidebar roots open
with a separator; every nested folder starts with a page, so the intended case
still goes flush and nothing else changes.

* fix(docs): move the flush-separator rule onto the separator component

Keeps the styling with the component that owns it, per the repo standard, and
lets the global rule be deleted outright rather than corrected — `global.css`
now only loses a rule in this PR. Tailwind's `first:` variant compiles to the
same `:first-child` selector, so behavior is unchanged: the build emits
`.first\:mt-0:first-child{margin-top:0}` and the prerendered HTML carries the
class on the separator.
This commit is contained in:
Waleed
2026-08-15 20:39:34 -07:00
committed by GitHub
parent 257029a60c
commit 025ea4d2bd
13 changed files with 144 additions and 403 deletions
+1 -3
View File
@@ -3,7 +3,6 @@ import { defineI18nUI } from 'fumadocs-ui/i18n'
import { DocsLayout } from 'fumadocs-ui/layouts/docs'
import { RootProvider } from 'fumadocs-ui/provider/next'
import { Geist_Mono, Inter } from 'next/font/google'
import Script from 'next/script'
import { ThemeProvider } from 'next-themes'
import {
SidebarFolder,
@@ -92,10 +91,9 @@ export default async function Layout({ children, params }: LayoutProps) {
suppressHydrationWarning
>
<head>
<Script
<script
id='website-json-ld'
type='application/ld+json'
strategy='beforeInteractive'
dangerouslySetInnerHTML={{ __html: serializeJsonLd(structuredData) }}
/>
</head>
-6
View File
@@ -489,12 +489,6 @@ html #nd-sidebar button:not([aria-label*="ollapse"]):not([aria-label*="xpand"])
padding: 0 !important;
}
/* The first group sits flush against the top padding — it has nothing to be
separated from. */
[data-separator]:not([data-separator] ~ [data-separator]) {
margin-top: 0;
}
/* Active state — aligned with platform --surface-active */
#nd-sidebar a[data-active="true"]:not(:has(span.font-mono)),
#nd-sidebar button[data-active="true"] {
@@ -193,7 +193,7 @@ export function SidebarFolder({ item, children }: { item: Folder; children: Reac
*/
export function SidebarSeparator({ item }: { item: Separator }) {
return (
<div data-separator className='mt-4 mb-1.5 px-2'>
<div data-separator className='mt-4 mb-1.5 px-2 first:mt-0'>
<p className='text-[var(--text-muted)] text-caption'>{item.name}</p>
</div>
)
+3 -4
View File
@@ -1,4 +1,3 @@
import Script from 'next/script'
import { serializeJsonLd } from '@/lib/json-ld'
import { DOCS_BASE_URL } from '@/lib/urls'
@@ -103,7 +102,7 @@ export function StructuredData({
return (
<>
<Script
<script
id={`article-json-ld-${structuredDataId}`}
type='application/ld+json'
dangerouslySetInnerHTML={{
@@ -111,7 +110,7 @@ export function StructuredData({
}}
/>
{breadcrumbStructuredData && (
<Script
<script
id={`breadcrumb-json-ld-${structuredDataId}`}
type='application/ld+json'
dangerouslySetInnerHTML={{
@@ -120,7 +119,7 @@ export function StructuredData({
/>
)}
{(url === baseUrl || url === `${baseUrl}/`) && (
<Script
<script
id={`software-json-ld-${structuredDataId}`}
type='application/ld+json'
dangerouslySetInnerHTML={{
@@ -5,9 +5,8 @@ description: Sign in from the terminal, authenticate CI with an API key, and kee
import { Callout } from 'fumadocs-ui/components/callout'
The CLI authenticates with a Sim API key. On a workstation, `sim login` mints and
stores one for you. In CI, you supply one through the environment and nothing
touches the filesystem.
The CLI authenticates with a Sim API key. `sim login` mints and stores one; in CI
you supply one through the environment instead.
## Signing in
@@ -28,13 +27,11 @@ Waiting for approval…
Personal key, defaulting to ws_abc123. Override per command with --workspace.
```
This is the same browser handoff shape as `gh auth login`. Nothing redeemable
crosses the browser leg, and there is no loopback listener — so it works over
SSH and inside containers.
There is no loopback listener, so this works over SSH and inside containers.
<Callout type="warn">
Confirm the pairing code in your terminal matches the one the browser shows
before you approve. That check is what binds the approval to *your* terminal.
Confirm the pairing code in the browser matches the one in your terminal before
approving. That check is what binds the approval to your terminal.
</Callout>
| Option | What it does |
@@ -45,10 +42,7 @@ before you approve. That check is what binds the approval to *your* terminal.
### Picking a workspace
The approval page is where you choose the workspace — the terminal has no key
yet, so it cannot list them for you.
`sim login` issues a **personal** key. The workspace you pick becomes the
You choose the workspace on the approval page. `sim login` issues a **personal** key. The workspace you pick becomes the
profile's default `workspace`; it does **not** restrict the key to that
workspace. Target another workspace the key can reach with `--workspace`:
@@ -65,9 +59,8 @@ re-logging into an existing profile preselects the one already configured.
sim whoami
```
This prints the resolved endpoint, workspace, output format, and account — and
which source each value came from. Reach for it first whenever a command targets
something you did not expect.
Prints the resolved endpoint, workspace, output format, and account, and which
source each value came from.
## Signing out
@@ -83,8 +76,8 @@ Sim under **Settings → API keys**.
## Authenticating CI
Skip `sim login` entirely. Set the key and workspace in the environment and the
CLI never reads or writes a config file:
Set the key and workspace in the environment; the CLI never reads or writes a
config file:
```bash
export SIM_API_KEY="sim_…"
@@ -96,10 +89,8 @@ sim workflows run wf_7Yb2 --input '{"source":"nightly"}' --output json
Create the key in Sim under **Settings → API keys**. Store it as a secret in your
CI provider — never commit it.
<Callout type="info">
`SIM_CONFIG_DIR` relocates both files if you do need them somewhere other than
`~/.sim` — a container image, or a runner with no writable home directory.
</Callout>
`SIM_CONFIG_DIR` relocates both files if you need them somewhere other than
`~/.sim`, such as a runner with no writable home directory.
### GitHub Actions
@@ -111,7 +102,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install --global sim
- run: npm install -g sim
- run: sim workflows run wf_7Yb2 --output json
env:
SIM_API_KEY: ${{ secrets.SIM_API_KEY }}
@@ -120,8 +111,7 @@ jobs:
## Several accounts at once
Each profile holds one identity and one set of defaults, so a production account
and a local stack can coexist without re-authenticating:
Each profile holds one identity and one set of defaults:
```bash
sim login --profile dev --endpoint http://localhost:3000
@@ -135,13 +125,13 @@ See [Configuration](/cli/configuration) for how profiles are stored and resolved
## Self-hosted and non-production deployments
Point the CLI at any Sim deployment with `--endpoint`, then sign in against it:
Point the CLI at any deployment with `--endpoint`, then sign in against it:
```bash
sim login --profile local --endpoint http://localhost:3000
```
Save it so you do not have to repeat the flag:
Save it to avoid repeating the flag:
```bash
sim configure --set-endpoint http://localhost:3000 --profile local
@@ -149,9 +139,9 @@ sim configure --set-endpoint http://localhost:3000 --profile local
## Where the key is stored
Keys live in `~/.sim/credentials`, written with `0600` permissions, kept apart
from the non-secret `~/.sim/config` so the two can be handled differently — you
can commit `config` to a dotfiles repo, and never `credentials`.
Keys live in `~/.sim/credentials`, written `0600`, separate from the non-secret
`~/.sim/config`. Commit `config` to a dotfiles repo if you like; never
`credentials`.
```ini title="~/.sim/credentials"
[default]
+14 -31
View File
@@ -3,19 +3,13 @@ title: Configuration
description: Profiles, config files, environment variables, and how each setting is resolved
---
import { Callout } from 'fumadocs-ui/components/callout'
The CLI has four settings: which **endpoint** to talk to, which **API key** to
use, which **workspace** to target, and which **output format** to print. Each
one resolves independently, so you can save a default and still override it for
a single command.
The CLI has four settings: **endpoint**, **API key**, **workspace**, and **output
format**. Each resolves independently, so a saved default can still be overridden
for a single command.
## Profiles
A profile is one identity plus one set of defaults. Profiles work like the AWS
CLI, which is what lets a production account and a local stack sit side by side
without re-authenticating.
A profile is one identity plus one set of defaults, in the style of the AWS CLI.
Select one with `-P`, `--profile`, or `SIM_PROFILE`:
```bash
@@ -46,10 +40,8 @@ sim configure --set-output json
Run `sim configure` with no flags to print the profile's stored settings.
<Callout type="info">
API keys are deliberately **not** settable through `sim configure`. Use
[`sim login`](/cli/authentication), or `SIM_API_KEY` for CI.
</Callout>
API keys are not settable here. Use [`sim login`](/cli/authentication), or
`SIM_API_KEY` for CI.
## Where settings come from
@@ -62,11 +54,7 @@ Each setting resolves independently, and the first match wins:
| 3 | `~/.sim/config` and `~/.sim/credentials`, for the selected profile |
| 4 | Built-in default — `https://sim.ai` and `table` |
Because they resolve independently, a saved profile still supplies the workspace
when you override only the output format.
`sim whoami` prints the winning source for each setting, which is usually the
fastest way to explain a surprising result:
`sim whoami` prints the winning source for each setting:
```bash
sim whoami
@@ -98,11 +86,8 @@ api_key = sim_…
api_key = sim_…
```
<Callout type="info">
The section-naming asymmetry — `[profile dev]` in config, `[dev]` in credentials
— is the AWS convention, kept so existing habits and tooling carry over. The
`default` profile is spelled `[default]` in both.
</Callout>
Section naming follows the AWS convention: `[profile dev]` in config, `[dev]` in
credentials. The `default` profile is `[default]` in both.
## Environment variables
@@ -122,8 +107,7 @@ filesystem at all.
## Choosing a workspace
Workspace-scoped commands need a workspace. Supply it per command, save it to
the profile, or set it in the environment:
Workspace-scoped commands need a workspace:
```bash
sim tables list --workspace ws_other
@@ -131,16 +115,15 @@ sim configure --set-workspace ws_abc123
export SIM_WORKSPACE=ws_abc123
```
Without one, the command fails and tells you how to set it. A few commands —
`sim billing status`, `sim billing logs`, and `sim audit-logs list` — accept
`sim billing status`, `sim billing logs`, and `sim audit-logs list` accept
`--all-workspaces` to drop the filter instead. It cannot be combined with
`--workspace`.
## Repairing a bad setting
An invalid `output` value fails with the list of accepted formats. Because a
higher-priority source still wins, you can repair a profile without editing the
file by hand:
An invalid `output` value fails with the list of accepted formats. A
higher-priority source still wins, so you can repair a profile without editing
the file:
```bash
sim --output table configure --set-output json
+12 -21
View File
@@ -3,7 +3,6 @@ title: Sim CLI
description: Drive workflows, tables, files, knowledge bases, and logs from your shell
---
import { Callout } from 'fumadocs-ui/components/callout'
import { Step, Steps } from 'fumadocs-ui/components/steps'
import { Tab, Tabs } from 'fumadocs-ui/components/tabs'
@@ -14,38 +13,31 @@ CI pipelines, and any other tool you already use.
## Install
<Tabs items={['npm', 'pnpm', 'bun', 'yarn']}>
<Tabs items={['npm', 'pnpm', 'bun']}>
<Tab value="npm">
```bash
npm install --global sim
npm install -g sim
```
</Tab>
<Tab value="pnpm">
```bash
pnpm add --global sim
pnpm add -g sim
```
</Tab>
<Tab value="bun">
```bash
bun add --global sim
```
</Tab>
<Tab value="yarn">
```bash
yarn global add sim
bun add -g sim
```
</Tab>
</Tabs>
The CLI needs **Node.js 20 or newer**. Verify the install:
Requires Node.js 20 or newer. Verify with `sim --version`.
```bash
sim --version
```
To run it without installing, use `npx sim <command>`.
Prefer using Sim as a library? See the [TypeScript](/api-reference/typescript)
and [Python](/api-reference/python) SDKs, or call the
[HTTP API](/api-reference/getting-started) directly.
Using Sim as a library instead? See the [TypeScript](/api-reference/typescript)
and [Python](/api-reference/python) SDKs, or the
[HTTP API](/api-reference/getting-started).
## Your first command
@@ -58,10 +50,9 @@ and [Python](/api-reference/python) SDKs, or call the
sim login
```
The terminal prints a pairing code and a URL. Approve it in the browser, pick a
workspace, and the key comes back over the CLI's own connection. Nothing
redeemable crosses the browser leg and there is no loopback listener, so this
works over SSH and inside containers.
The terminal prints a pairing code and a URL. Approve it in the browser and pick
a workspace. There is no loopback listener, so this works over SSH and in
containers.
See [Authentication](/cli/authentication) for CI keys, multiple accounts, and
self-hosted deployments.
+24 -59
View File
@@ -3,11 +3,7 @@ title: Output formats
description: table, json, yaml, and text — what each is for, and how to select one
---
import { Callout } from 'fumadocs-ui/components/callout'
Every command renders through the same four formats. Pick one per command with
`--output`, save a profile default with `sim configure --set-output`, or set
`SIM_OUTPUT` ambiently for CI.
Every command renders through the same four formats.
| Format | For |
| --- | --- |
@@ -16,57 +12,26 @@ Every command renders through the same four formats. Pick one per command with
| `yaml` | piping into anything that reads YAML |
| `text` | shell loops — tab-separated, no header, no colour |
```bash
sim --output json tables get tbl_123 # before the command
sim tables get tbl_123 --output json # or after; both work
sim configure --set-output json # for this profile, from now on
SIM_OUTPUT=yaml sim logs list > logs.yaml # for one invocation or a whole job
```
## Raw values versus rendered cells
`json` and `yaml` emit the API's **raw** values, not the table's formatting — a
duration stays `1500`, not `"1.5s"`. Switching format never changes the data,
only how it is displayed.
`text` uses the rendered cells, because it exists for shell plumbing rather than
parsing.
<Callout type="info">
An absent value prints as an em-dash (`—`) in `table` and as an **empty field**
in `text`, so emptiness tests downstream behave as you would expect.
</Callout>
## table
The default. Uppercase dim headers, one row per record, values formatted for
reading — timestamps without milliseconds, sizes as `4.2 MB`, booleans as
`yes`/`no`, costs as `$0.0142`.
Long cells are clipped so rows stay on one line. When you need the untruncated
value, switch to `json`.
Select one per command, save it to the profile, or set it in the environment:
```bash
sim files list
sim tables get tbl_123 --output json
sim configure --set-output json
SIM_OUTPUT=yaml sim logs list > logs.yaml
```
## json
`--output` works before or after the command.
```bash
sim logs list --level error --output json | jq -r '.[].runId'
sim tables rows query tbl_123 --output json | jq '.[] | select(.score > 10)'
```
## What each format emits
## yaml
`json` and `yaml` emit the API's raw values, not the table's formatting — a
duration stays `1500`, not `"1.5s"`.
```bash
sim workflows get wf_123 --output yaml
sim logs get run_123 --output yaml > run.yaml
```
`table` formats for reading: timestamps without milliseconds, sizes as `4.2 MB`,
booleans as `yes`/`no`, costs as `$0.0142`. Long cells are clipped to keep rows
on one line; switch to `json` for the full value.
## text
Tab-separated, no header, no colour — built for `read` loops:
`text` uses the rendered cells, tab-separated, with no header or colour:
```bash
SIM_OUTPUT=text sim files list | while IFS=$'\t' read -r id name folder size type uploader uploaded; do
@@ -74,31 +39,31 @@ SIM_OUTPUT=text sim files list | while IFS=$'\t' read -r id name folder size typ
done
```
An absent value is an em-dash in `table` and an empty field in `text`.
## Reading a run in detail
`sim logs get` keeps its default human output concise. Add `--trace` for the
expanded recursive trace — span inputs, outputs, errors, timing, and cost:
`sim logs get` prints a concise summary. Add `--trace` for the recursive trace
with span inputs, outputs, errors, timing, and cost:
```bash
sim logs get run_123 --trace
```
`json` and `yaml` always carry the complete structured response, so `--trace` is
a no-op there — the data is already present:
`json` and `yaml` always carry the complete response, so `--trace` is a no-op
there:
```bash
sim logs get run_123 --output json | jq '.traceSpans'
sim logs list --include-trace-spans --output json
```
## Commands that ignore the format
## Exceptions
`sim profiles` and `sim configure`'s listing mode always print for humans — they
report on your local configuration rather than on API data.
`sim profiles` and `sim configure` always print for humans — they report local
configuration, not API data.
`sim workflows export` is the opposite case: it emits a document rather than a
record to look at, so it prints raw JSON — or YAML when the profile says so —
whatever the display format is. That is what makes it round-trip:
`sim workflows export` always emits raw JSON, or YAML when the profile says so,
so that it round-trips through `import`:
```bash
sim workflows export wf_123 > wf.json
+6 -10
View File
@@ -4,18 +4,14 @@ description: Every sim command, argument, and flag on a single page
---
import { CommandTable } from '@/components/ui/command-table'
import { Callout } from 'fumadocs-ui/components/callout'
Every command the CLI exposes, on one page, generated from the CLI itself.
For a guided tour start at the [overview](/cli/commands); this page exists to
be searched, bookmarked, and fed to tools.
Every command on one page, generated from the CLI itself. Start at the
[overview](/cli/commands) to browse; this page is for searching and for tools.
<Callout type="info">
Append `.mdx` to any page in these docs to get its raw Markdown —
[`/cli/reference.mdx`](/cli/reference.mdx) is this page as plain text. The whole
documentation set is also published as [`/llms.txt`](/llms.txt) and
[`/llms-full.txt`](/llms-full.txt) for coding agents.
</Callout>
Append `.mdx` to any page for its raw Markdown —
[`/cli/reference.mdx`](/cli/reference.mdx) is this page as plain text. The docs
are also published as [`/llms.txt`](/llms.txt) and
[`/llms-full.txt`](/llms-full.txt).
## Global options
+13 -28
View File
@@ -5,8 +5,7 @@ description: File and stdin inputs, list flags, pagination, exit codes, and auto
import { Callout } from 'fumadocs-ui/components/callout'
The CLI is built to be driven by other programs. Everything below applies to
every command.
Everything below applies to every command.
## Reading input from files and stdin
@@ -19,9 +18,6 @@ sim tables rows query tbl_123 --filter @filter.json
cat wf.json | sim workflows import --workflow @-
```
This keeps large payloads out of your shell history and out of the argument
length limit.
## List flags
Primitive lists take space-separated values. With `@`, the file supplies one
@@ -33,14 +29,12 @@ sim files mv --file-ids @file-ids.txt --to Archive
printf 'file_1\nfile_2\n' | sim files mv --file-ids @- --to Archive
```
Arrays of objects stay JSON inputs, because they cannot be flattened to a list
without losing structure.
Arrays 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. It is JSON because the
grammar is a tree, and there is no honest flag encoding for one.
groups of `{field, op, value}` conditions, nestable.
```bash
sim tables rows query tbl_123 \
@@ -59,9 +53,6 @@ Operators: `eq`, `ne`, `gt`, `gte`, `lt`, `lte`, `in`, `nin`, `contains`,
sim tables rows query tbl_123 --sort '[{"field":"createdAt","direction":"desc"}]'
```
Row columns are discovered at runtime from the returned data, unioned across the
page, so a sparse row does not hide a column.
## Pagination
List commands page automatically up to `--limit`, which defaults to `100`. Pass
@@ -84,8 +75,9 @@ sim files delete file_123 --yes
Without `--yes` the command explains what it would have destroyed and stops.
<Callout type="warn">
`batch-delete` and `batch-update` also carry the standard `--limit` default of
`100`. Set `--limit 0` when you intend to affect every matching row.
`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.
</Callout>
## Exit codes
@@ -105,11 +97,8 @@ if ! sim workflows run wf_7Yb2 --output json > result.json; then
fi
```
<Callout type="info">
An unexpected error keeps its stack trace on purpose — that is a bug in the CLI,
and hiding it behind a friendly message would make it unreportable. Please
[open an issue](https://github.com/simstudioai/sim/issues) if you see one.
</Callout>
An unexpected error prints a stack trace — that is a bug in the CLI, so please
[open an issue](https://github.com/simstudioai/sim/issues).
## Selecting workflow output
@@ -135,8 +124,8 @@ done
sim logs get "$run_id" --trace
```
`workflows runs get` is the lightweight status resource; `logs get` is the full
diagnostic one. For a paused run, the status includes the context ID that
`workflows 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
@@ -151,13 +140,9 @@ sim tables folders mv Reports/Quarterly Archive/Quarterly
sim tables folders delete Archive --recursive --yes
```
`ls` is a directory view: it combines the resources at its path with that
folder's direct child folders, and never includes deeper descendants. Its `ref`
column is the resource ID or canonical folder path to pass to the next command.
Use `list` when you want resources only, or `folders ls` for folders only.
The leading `/` is optional on input; the API returns the canonical
leading-slash form.
`ls` 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
+43 -198
View File
@@ -1,244 +1,89 @@
---
title: Troubleshooting
description: What the CLI's errors mean, and the fastest way to resolve each one
description: The failures whose cause is not obvious from the error message
---
import { Callout } from 'fumadocs-ui/components/callout'
Errors print one line to stderr, prefixed `Error:`, and exit `1`. Most say what
to do next; the cases below are the ones that do not.
Every error the CLI can explain prints one line to stderr, prefixed `Error:`, and
exits `1`. Where the API supplies an error code or validation details, those
follow on dimmed lines.
Start with `sim whoami`. It prints the resolved endpoint, workspace, and output
format, **and where each came from** — which explains most surprises on its own.
<Callout type="info">
Start with `sim whoami`. Most surprises are a command running against a different
profile, endpoint, or workspace than you assumed, and `whoami` prints the winning
value for each setting **and where it came from**.
</Callout>
## A command targets the wrong workspace or deployment
## Authentication
### `Not logged in on profile "default". Run: sim login --profile default`
No API key resolved for the profile. Either sign in, or supply a key through the
environment:
```bash
sim login
# or, for CI
export SIM_API_KEY="sim_…"
```
Remember that the key is per profile. If you signed in as `dev` and are running
without `--profile dev`, the default profile is still unauthenticated.
### An error ending in `— run: sim login --profile <name>`
The API rejected the key with a `401`. The key was revoked, or it belongs to a
different deployment than the endpoint you are pointed at. Sign in again:
```bash
sim login --profile <name>
```
Check the endpoint first if you did not expect this — a key minted against a
local stack will not authenticate against production:
```bash
sim whoami --profile <name>
```
### `Timed out waiting for browser approval.`
`sim login` waits 15 minutes for you to approve the pairing code. Run it again.
If the browser never opened, use the printed URL directly:
```bash
sim login --no-browser
```
### `Profile "default" already exists. Re-run with --yes to overwrite it.`
Signing in again over a profile that already holds a key. This is a guard, not a
failure — confirm you mean to replace it:
```bash
sim login --yes
```
## Workspace
### `No workspace set for profile "default". Pass --workspace, or run: sim configure --profile default --set-workspace <id>`
The command is workspace-scoped and no workspace resolved. Set one for the
profile, pass it per command, or export it:
```bash
sim configure --set-workspace ws_abc123
sim tables list --workspace ws_abc123
export SIM_WORKSPACE=ws_abc123
```
The workspace ID is in the Sim URL: `https://sim.ai/workspace/{workspaceId}/…`.
<Callout type="warn">
`sim login` sets the profile's default workspace to whichever one you picked on
the approval page. It does **not** limit the key to that workspace — use
`--workspace` to reach any other workspace the key can access.
</Callout>
### A command returns rows from the wrong workspace
The workspace resolved from a higher-priority source than you expected. `--workspace`
beats `SIM_WORKSPACE`, which beats the profile. Confirm with `sim whoami`.
`sim billing status`, `sim billing logs`, and `sim audit-logs list` also accept
`--all-workspaces`, which drops the filter entirely and cannot be combined with
`--workspace`.
## Connectivity
### `Could not reach https://sim.ai: <reason>`
The request never got a response — DNS, TLS, a proxy, or a self-hosted stack that
is not running. Check the endpoint the CLI actually used:
Each setting resolves independently, and a flag beats the environment, which
beats the profile. A stale `SIM_WORKSPACE` in your shell silently outranks the
workspace you configured.
```bash
sim whoami
```
For a local deployment, confirm it is up and that the endpoint has the right port
and scheme:
Note that `sim login` sets the profile's default workspace to whichever one you
picked on the approval page. It does **not** limit the key to that workspace —
use `--workspace` to reach any other workspace the key can access.
## An error ends in `— run: sim login --profile <name>`
The API rejected the key with a `401`. Either it was revoked, or it belongs to a
different deployment than the endpoint you are pointed at — a key minted against
a local stack will not authenticate against production. Check the endpoint before
re-authenticating:
```bash
sim whoami --profile <name>
```
## `Could not reach https://sim.ai: <reason>`
The request never got a response: DNS, TLS, a proxy, or a self-hosted stack that
is not running. Confirm the endpoint the CLI actually used with `sim whoami`, and
that it has the right scheme and port:
```bash
sim configure --set-endpoint http://localhost:3000 --profile local
```
### `Request cancelled.`
## A JSON flag rejects a value that looks like valid JSON
The request was aborted, usually by `Ctrl-C` or a CI job timeout. Re-run it.
## Arguments and flags
### `error: missing required argument '<name>'`
The CLI prints an `Example:` line beneath showing the full invocation. `--help`
gives the complete signature at any depth:
```bash
sim tables rows query --help
```
### `error: option '--x <value>' argument 'y' is invalid. Allowed choices are …`
The value is outside the accepted set. The accepted values are in `--help` and in
this section's [command reference](/cli/commands).
### `<message> Re-run with --yes to confirm.`
A destructive command needs explicit confirmation. The message says what would be
destroyed — read it, then repeat the command with `--yes`:
```bash
sim files delete file_123 --yes
```
There is no "delete everything" default: deletions require an explicit selector
**and** `--yes`.
### `--limit must be a non-negative number`
Use `0` for "everything" rather than a negative number:
```bash
sim logs list --limit 0
```
### `--input @- reads stdin, but nothing is piped in`
`@-` reads from stdin, so something has to be piped to it. Either pipe a value or
point at a file:
```bash
cat wf.json | sim workflows import --workflow @-
sim workflows import --workflow @wf.json
```
### A JSON flag rejects a value that looks like valid JSON
Your shell probably consumed the quotes. Wrap the whole value in single quotes,
or read it from a file:
Your shell consumed the quotes. Wrap the whole value in single quotes, or read it
from a file:
```bash
sim tables rows query tbl_123 --filter '{"all":[{"field":"status","op":"eq","value":"open"}]}'
sim tables rows query tbl_123 --filter @filter.json
```
## Output
## A value looks truncated
### `Error: … output …` naming the accepted formats
A stored or exported output format is not one of `table`, `json`, `yaml`, or
`text`. A higher-priority source still wins, so you can repair the profile
without editing the file:
```bash
sim --output table configure --set-output json
```
### A value looks truncated
`table` clips long cells so rows stay on one line. The data is not truncated —
`table` clips long cells to keep rows on one line. The data is not truncated —
switch to a machine format to see it in full:
```bash
sim logs get run_123 --output json
```
### `sim profiles` ignores `--output`
`sim profiles` and `sim configure`'s listing mode always print for humans; they
report on your local configuration rather than on API data.
## Files
### `<path> already exists. Pass --force to overwrite it, or choose another output path.`
`sim files get -o` will not overwrite an existing file by accident:
```bash
sim files get file_123 -o ./report.csv --force
```
### `sim files get` refuses to print to the terminal
## `sim files get` refuses to print to the terminal
Writing arbitrary binary to an interactive terminal can corrupt it, so non-text
content must go to a file or a pipe:
content has to go to a file or a pipe:
```bash
sim files get file_123 -o ./image.png
sim files get file_123 | shasum
```
## Secrets
## A stored output format is invalid
### `Interactive secret input requires a terminal. Pass --value instead.`
`sim secrets set` prompts with masked input when it can. In CI there is no
terminal, so supply the value directly — from a CI secret, not a literal:
A higher-priority source still wins, so you can repair the profile without
editing the file by hand:
```bash
sim secrets set MY_KEY --scope workspace --value "$MY_KEY"
sim --output table configure --set-output json
```
## Something else
## Anything else
An unexpected error keeps its stack trace on purpose — that is a bug in the CLI,
not a message meant for you. Please
An unexpected error prints a stack trace. That is a bug in the CLI — please
[open an issue](https://github.com/simstudioai/sim/issues) with the command you
ran and the trace.
Include the version:
```bash
sim --version
```
ran, the trace, and the output of `sim --version`.