# Documentation (/)
Welcome to Sim, the open-source AI workspace where teams build, deploy, and manage AI agents. Create agents visually with the workflow builder, conversationally through Chat, or programmatically with the API — connected to the integration catalog and every major LLM.
## Quick Start [#quick-start]
Learn what you can build with Sim
Build your first agent in 10 minutes
Learn about the building blocks
Explore the integration catalog
## Core Concepts [#core-concepts]
Understand how data flows between blocks
Work with workflow and environment variables
Inspect workflow runs and diagnose failures
Start agents via API, webhooks, or schedules
## Advanced Features [#advanced-features]
Set up workspace roles and permissions
Connect external services with Model Context Protocol
Integrate Sim into your applications
---
# What is Sim? (/academy)
Sim is a unified workspace for **building and operating AI systems**. Everything you make lives in one place, and everything connects.
## The workspace [#the-workspace]
A **workspace** is a collection of shared resources and the workflows that use them.
* **Resources** are your data: [tables](/academy/tables/intro) (structured records), [knowledge bases](/academy/knowledge-bases/intro) (searchable memory), and [files](/academy/files/intro) (documents and media).
* **Workflows** are your processes: the agents and automations that read those resources, act, and write results back.
Workflows can use workspace resources they have access to: read a table, search a knowledge base, or produce a file for another workflow.
## Integrations connect you to the outside world [#integrations-connect-you-to-the-outside-world]
**Integrations** are plugins. They let your resources and workflows reach services beyond Sim, send a Slack message, read a Gmail inbox, write a row to a CRM, call any API. Connect an account and share access with the people or workflows that need it.
So the whole picture is small: a workspace is **data + processes**, integrations plug it into **everything else**, and the rest of this course is just learning each piece and watching them compose.
## Related documentation [#related-documentation]
* [Introduction](/introduction)
* [Getting started](/getting-started)
---
# Choosing what to use (/agents/choosing)
When you build an agent, several features overlap: a deterministic block and an agent tool can run the same integration, and a custom tool, an MCP tool, and a workflow-as-tool can all give an agent the same action. This page lays out the differences so you pick the right one. They vary along three lines: whether the action is **deterministic** (always runs) or **model-decided** (an agent chooses), whether it lives in one workflow or is **reusable** across your workspace, and whether it comes from Sim or an **external** provider.
The running example is a workflow that scores inbound sales leads. It reads a new lead, enriches it, decides on a score, logs the result, and notifies the team. Each option below builds part of it:
{/* VISUAL: decision tree. Always happens? → deterministic block. Else agent chooses? → agent tool. Reuse across workspace? → custom tool. External toolset? → MCP. Whole workflow? → workflow-as-tool. Reusable instructions? → skill. */}
## Deterministic block [#deterministic-block]
A **block** is a single step that runs at a fixed point on the path, with no model deciding whether to. It always runs when the workflow reaches it. Use one when the action must happen every time: an API call, a data transform, a branch.
In the lead scorer, a [Google Sheets](/integrations) block always appends the scored lead to a tracking sheet, and a [Function](/workflows/blocks/function) block always reshapes the enrichment response into the fields the next step expects. The block runs at that point in the graph; an execution error can still stop it.
Most steps in a workflow are blocks. Reach for the kinds below only when you want a model to decide, or you want to reuse something.
## Agent tool [#agent-tool]
An **agent tool** is an action you hand to an [Agent](/workflows/blocks/agent) block. The agent reads the task and decides whether and when to call it. The same catalog of [integrations](/integrations) that exist as standalone blocks can also be attached to an agent as tools.
In the lead scorer, the Agent has a Search tool and a Send Email tool. For a lead with a thin profile it runs Search to gather context; for a strong lead it calls Send Email. A thin, obvious lead might trigger neither. The agent chooses per run.
Each tool carries a `usageControl` setting. **Auto** lets the model decide (the default). **Force** makes the agent call the tool every run, for actions that should never be skipped, like always logging the decision. **None** removes the tool from that agent.
A block and an agent tool can be the same underlying integration. The difference is who decides. A block runs because the path reached it. An agent tool runs because the agent chose it.
## Custom tool [#custom-tool]
A **custom tool** is a tool you define once with an object schema and a JavaScript function body, then reuse across your workspace. It needs no external account. Use one when you have logic that several agents or workflows would otherwise duplicate.
In the lead scorer, a `normalizeCompanyDomain` custom tool cleans a raw website into a canonical domain. The same tool serves the lead scorer, a deduplication workflow, and a reporting agent. Define it in the workspace, then pick it from any Agent block's tool list.
## MCP server [#mcp-server]
**MCP** (Model Context Protocol) is a standard for connecting an external tool provider. Connect an [MCP server](/agents/mcp) and its tools appear in the agent's tool list as a set. Use it to bring in a complete toolset that Sim does not provide natively, rather than wiring each action by hand.
In the lead scorer, your CRM vendor ships an MCP server. After you connect it once, the agent can read accounts and update records through the vendor's own tools. The difference from a custom tool is who maintains it: a custom tool is code you wrote, while an MCP server is a toolbox someone else maintains.
## Workflow-as-tool [#workflow-as-tool]
A **workflow-as-tool** is a whole workflow handed to an agent as one callable tool. You pick the workflow in the [Agent](/workflows/blocks/agent) block's tool list; the agent decides when to call it and supplies the inputs, which arrive at the child's [Start](/workflows/triggers/start) trigger, and the child's result comes back as the tool's output. Use it when a multi-step procedure should be at the agent's disposal, not on the path.
In the lead scorer, the agent has a `Deep Enrich` workflow as a tool — its own five-step procedure. For a thin lead, the agent calls it to fill out the profile before scoring; for a complete lead, it never runs. The agent weighs a whole procedure the same way it weighs a single action.
A workflow can also run as a fixed step: the [Workflow](/workflows/blocks/workflow) block calls a child workflow because the path reached it. Same child workflow, same Start trigger — the difference, as with blocks and agent tools, is who decides. The Enrich step in the diagram is that deterministic case.
## Skill [#skill]
A **skill** is reusable instructions, a written playbook an agent can follow. Each skill has a short name and description that are always visible to the agent, plus a longer body the agent loads only when it decides the skill applies. Use one to capture how something should be done, separate from the tools that do it.
In the lead scorer, a `lead-scoring-rubric` skill spells out the bands and disqualifiers. The agent sees the skill's name and description on every run, and when a lead is ambiguous it loads the full rubric and applies it. The distinction is simple: a tool is an action the agent takes, and a skill is guidance the agent reads. Manage skills in your [workspace](/agents/skills).
| Feature | Who decides it runs | Where it lives | How you author it |
| -------------------- | ------------------- | ------------------ | --------------------------------------- |
| **Block** | The path | The workflow | Drag in and configure |
| **Agent tool** | The agent | On the Agent block | Pick from the integrations |
| **Custom tool** | The agent | The workspace | Write the code once |
| **MCP server** | The agent | An external server | Connect it |
| **Workflow-as-tool** | The agent | Its own workflow | Build it, then pick it in the tool list |
| **Skill** | The agent | The workspace | Write the instructions |
---
# Custom Tools (/agents/custom-tools)
Custom tools let you write your own JavaScript functions and make them available as callable tools in Agent blocks. This is useful when you need functionality that isn't covered by Sim's built-in integrations — for example, calling an internal API, performing a custom calculation, or transforming data in a specific way.
## How Custom Tools Work [#how-custom-tools-work]
A custom tool has two parts:
1. **Schema** — A JSON definition describing the tool's name, description, and parameters (using the OpenAI function-calling format). This tells the AI agent what the tool does and what inputs it expects.
2. **Code** — A JavaScript function body that runs when the agent calls the tool. Parameters defined in the schema are available as variables in your code.
When an Agent block has access to a custom tool, the AI model decides when to call it based on the schema description and the conversation context — just like built-in tools.
## Creating a Custom Tool [#creating-a-custom-tool]
### Open Custom Tools settings [#open-custom-tools-settings]
Navigate to **Settings → Custom Tools** in your workspace and click **Add**.
### Define the schema [#define-the-schema]
In the **Schema** tab, define your tool using JSON in the OpenAI function-calling format:
```json
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a city",
"parameters": {
"type": "object",
"properties": {
"city": {
"type": "string",
"description": "The city name"
},
"units": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature units"
}
},
"required": ["city"]
}
}
}
```
You can use the AI wand button to generate a schema from a natural language description of what the tool should do.
### Write the code [#write-the-code]
Switch to the **Code** tab and write the JavaScript function body. Parameters from your schema are available directly as variables:
```javascript
const response = await fetch(
`https://api.openweathermap.org/data/2.5/weather?q=${city}&units=${units === 'celsius' ? 'metric' : 'imperial'}&appid={{OPENWEATHER_API_KEY}}`
);
const data = await response.json();
return {
temperature: data.main.temp,
description: data.weather[0].description,
humidity: data.main.humidity
};
```
For a secret used as a complete JavaScript expression, prefer the unquoted form, such as `const apiKey = {{OPENWEATHER_API_KEY}};`. Quoted and embedded forms remain supported, including the placeholder embedded in the URL above, `"Bearer {{KEY}}"`, template literals, and JavaScript regex literals. The value is bound separately when the tool executes rather than pasted into its source, so its exact string contents are preserved.
You can also use the AI wand to generate code from a description. Environment variables are referenced with `{{KEY}}` syntax.
### Save [#save]
Click **Save** to create the tool. It's now available to use in any Agent block across your workspace.
## Using Custom Tools in Workflows [#using-custom-tools-in-workflows]
Once created, custom tools appear alongside built-in tools when configuring an Agent block:
1. Open an Agent block
2. Click **Add Tools**
3. Find your custom tool in the tool list
4. The agent will call the tool when it determines it's relevant to the task
## Code Environment [#code-environment]
### Available Features [#available-features]
* **Async/await** — Your code runs in an async context, so you can use `await` directly
* **fetch()** — Make HTTP requests to external APIs
* **Node.js built-ins** — Access to `crypto`, `Buffer`, and other standard modules
* **Environment variables** — Use `{{KEY}}` syntax to bind secrets at execution time without placing plaintext in source code
### Limitations [#limitations]
* **No npm packages** — External libraries like `axios` or `lodash` are not available. Use built-in APIs instead
* **Parameters by name** — Schema parameters are available directly as variables (e.g., `city`), not via a `params` object
### Returning Results [#returning-results]
Return a value from your code to send it back to the agent:
```javascript
const result = await fetch(`https://api.example.com/data?q=${query}`);
const data = await result.json();
return data;
```
The returned value becomes the tool output that the agent sees and can use in its response.
## Managing Custom Tools [#managing-custom-tools]
From **Settings → Custom Tools** you can:
* **Search** tools by name, function name, or description
* **Edit** any tool's schema or code
* **Delete** tools that are no longer needed
Deleting a custom tool removes it from all Agent blocks that reference it. Make sure no active workflows depend on the tool before deleting.
## Permissions [#permissions]
| Action | Required Permission |
| -------------------- | --------------------------------- |
| View custom tools | **Read**, **Write**, or **Admin** |
| Create or edit tools | **Write** or **Admin** |
| Delete tools | **Admin** |
---
# Agents (/agents)
An **agent** is a [workflow](/workflows) that reasons and acts on its own. It reads an input, decides what to do, and carries it out, calling tools and using your data along the way. You build a custom agent in Sim by composing a workflow whose thinking runs through one or more [Agent blocks](/workflows/blocks/agent).
An **Agent block** is the reasoning step inside that workflow: a model reads the values available to it, decides, and returns a result that later blocks read by reference. A simple agent is a single Agent block; a larger one wires several together with other blocks. The Agent block is where the model thinks; the rest of the workflow is what it acts on and through.
The example throughout is an agent that scores inbound sales leads.
## The Agent block [#the-agent-block]
You set up the reasoning step by giving the Agent block a **model** and a **prompt**. The model is the LLM that powers it; you pick one from the available providers, and the default is `claude-sonnet-4-6`. The prompt is a system message that defines who the agent is and how it should behave, plus a user message that carries the input, usually a reference like ``.
When it runs, the Agent block reasons, calls any tools it needs, and stores its result under its own name. By default that result is free text in `content`, read by a later block as ``, alongside run details like the model used, token counts, tool calls, and cost. Every setting and output field is in the [Agent block reference](/workflows/blocks/agent).
## What you give an agent [#what-you-give-an-agent]
On its own, an Agent block can only reason and write text. You extend it so it can act, follow your rules, use your data, remember, and return results other blocks can rely on. Each feature maps to something you'd want an agent to do.
### Take an action: tools [#take-an-action-tools]
To let an agent do something in the world, give it **tools**. A tool is an action the agent can call, like sending an email, searching the web, updating a CRM record, or running another workflow. You attach tools to the Agent block, and the agent decides which to call for the task in front of it. In the lead scorer, the agent has a search tool to gather context on a thin profile and an email tool to reach out to a strong lead.
Tools come from a few places:
* **[Integrations](/integrations)** are the catalog of external services: Gmail, Slack, Airtable, Linear, and hundreds more.
* **[Custom tools](/agents/custom-tools)** are tools you define once with a schema and a snippet of code, then reuse.
* **[MCP tools](/agents/mcp)** come from an external provider you connect through the Model Context Protocol.
* **[Workflow-as-tool](/workflows)** makes another workflow callable, so the agent runs a whole procedure as one step.
The same integration can run two ways. As a [block](/workflows#blocks) it runs because the path reached it. As an agent tool it runs because the agent chose it. Per-tool usage controls (force a tool, or disable one) are in the [Agent block reference](/workflows/blocks/agent).
### Follow a procedure: skills [#follow-a-procedure-skills]
To give an agent instructions it can follow, write a [skill](/agents/skills). A skill is a reusable playbook with a short name and description the agent always sees, plus a longer body it loads only when the skill applies. In the lead scorer, a `lead-scoring-rubric` skill spells out the bands and disqualifiers, and the agent reads the full rubric only when a lead is ambiguous. A tool is an action the agent takes; a skill is guidance it reads.
### Use your documents: knowledge [#use-your-documents-knowledge]
To let an agent answer from your own content, connect a [knowledge base](/knowledgebase). The agent searches it and grounds its answers in what it finds, instead of relying only on the model's general training. Give the lead scorer a knowledge base of past deals and it can compare a new lead against ones you've closed before.
### Remember across runs: memory [#remember-across-runs-memory]
To let an agent reuse information from one run to the next, give it [memory](/workflows/blocks/agent#memory), which stores and recalls values keyed to a conversation. Without it, each run starts fresh; with it, an agent in a chat carries what was said earlier into later messages.
### Return a usable result: structured output [#return-a-usable-result-structured-output]
To make an agent's result something later blocks can act on, give it a **structured output**: a typed object you define instead of free text. In the lead scorer, the agent returns `{ score, tier, reason }`, and a later [Condition](/workflows/blocks/condition) block reads `` to branch. See [how blocks pass data](/workflows/data-flow) for reading fields.
## Choosing what to use [#choosing-what-to-use]
Start with one Agent block and a prompt, then add only what the task needs: a tool when the agent should act, a skill when it needs written guidance, a knowledge base when it should answer from your documents, memory when it should remember, and a structured output when a later block has to read its result.
---
# Using MCP tools (/agents/mcp)
The Model Context Protocol ([MCP](https://modelcontextprotocol.com/)) is an open standard for connecting AI to external tools and data. Add an MCP server to your workspace and its tools become available to your agents — a way to integrate services Sim doesn't have a built-in integration for.
## Adding an MCP Server as a Tool [#adding-an-mcp-server-as-a-tool]
MCP servers provide collections of tools that your agents can use.
To add one:
1. Navigate to **Settings → MCP Tools**
2. Click **Add** to open the configuration modal
3. Enter a **Server Name** and **Server URL**
4. Add any required **Headers** (e.g. API keys)
5. Click **Add MCP** to save
You can also configure MCP servers directly from the toolbar in an Agent block for quick setup.
### Server Configuration Options [#server-configuration-options]
| Field | Description |
| ------------- | ---------------------------------------------------- |
| **Name** | Display name for the server |
| **URL** | The MCP server endpoint |
| **Transport** | Currently supports `streamable-http` |
| **Headers** | Key-value pairs for authentication or custom headers |
| **Timeout** | Connection timeout in milliseconds (default: 30,000) |
### Environment Variables in Configuration [#environment-variables-in-configuration]
Server URLs and headers support environment variable substitution using `{{VAR_NAME}}` syntax. This keeps sensitive values like API keys out of the server configuration.
```
URL: https://api.example.com/mcp
Authorization: Bearer {{MCP_API_TOKEN}}
```
When you type `{{` in the URL or header fields, a dropdown appears showing available workspace environment variables.
When a saved secret is successfully substituted this way, exact occurrences of its value are masked in stored MCP tool-call traces. The real URL or header value still reaches the MCP server unchanged. See [Execution log protection](/platform/credentials#execution-log-protection) for the exact scope and limitations.
### Testing and Validation [#testing-and-validation]
Click **Test Connection** before saving to verify the server is reachable and discover available tools. The test response shows the number of tools found and the protocol version.
After saving, each server displays its available tools with parameter names, types, and required flags. If a server's tools change (e.g., after a server update), click **Refresh** to fetch the latest schemas. This automatically updates any agent blocks using those tools.
Tool validation badges appear on servers with issues — for example, if a tool was removed from the server but is still referenced in a workflow. Click the badge to see which workflows are affected.
### Domain Allowlisting [#domain-allowlisting]
Self-hosted deployments can restrict which MCP server domains are allowed by setting the `ALLOWED_MCP_DOMAINS` environment variable (comma-separated list). When set, only servers on approved domains can be added. When unset, all domains are allowed.
This governs which domains may be used. It is separate from where those domains are allowed to resolve: an MCP server on a private address is reached by naming it in `EGRESS_ALLOWED_HOSTS` or `EGRESS_ALLOWED_IP_RANGES`, described in [Security](/platform/self-hosting/security#the-ssrf-boundary). Both checks apply.
The allowlist covers the server URL itself. If the server requires OAuth, any endpoint its metadata names on a *different* origin than the server you configured is treated as content rather than as configuration, so that one has to be publicly routable. Endpoints on the server's own origin keep the server's reachability.
## Using MCP Tools in Agents [#using-mcp-tools-in-agents]
Once MCP servers are configured, their tools become available within your agent blocks:
1. Open an **Agent** block
2. In the **Tools** section, click **Add tool…**
3. Under **MCP Servers**, click a server to see its tools
4. Select individual tools, or choose **Use all N tools** to add every tool from that server
5. The agent can now access these tools during execution
If you haven't configured a server yet, click **Add MCP Server** at the top of the dropdown to open the setup modal without leaving the block.
## Standalone MCP Tool Block [#standalone-mcp-tool-block]
For more granular control, you can use the dedicated MCP Tool block to execute specific MCP tools:
The MCP Tool block runs one configured tool with parameters you set explicitly, and its output is readable by later blocks like any other.
## When to Use MCP Tool vs Agent [#when-to-use-mcp-tool-vs-agent]
| Feature | **Agent with MCP tools** | **MCP Tool block** |
| -------------- | -------------------------------- | -------------------------------------- |
| **Execution** | AI decides which tools to call | Deterministic — runs the tool you pick |
| **Parameters** | AI chooses at runtime | You set them explicitly |
| **Best for** | Dynamic, conversational flows | Structured, repeatable steps |
| **Reasoning** | Handles complex multi-step logic | One tool, one call |
## Permission Requirements [#permission-requirements]
MCP functionality requires specific workspace permissions:
| Action | Required Permission |
| ---------------------------- | --------------------------------- |
| Create or update MCP servers | **Write** or **Admin** |
| Delete MCP servers | **Admin** |
| Use MCP tools in agents | **Write** or **Admin** |
| View available MCP tools | **Read**, **Write**, or **Admin** |
| Execute MCP Tool blocks | **Read**, **Write**, or **Admin** |
MCP servers run with the permissions of the user who configured them — only connect servers you trust, and review a server's tools before handing them to agents.
---
# Agent skills (/agents/skills)
Agent Skills are reusable packages of instructions that give your AI agents specialized capabilities. Based on the open [Agent Skills](https://agentskills.io) format, skills let you capture domain expertise, workflows, and best practices that agents can load on demand.
## How Skills Work [#how-skills-work]
Skills use **progressive disclosure** to keep agent context lean:
1. **Discovery** — Only skill names and descriptions are included in the agent's system prompt (\~50-100 tokens each)
2. **Activation** — When the agent decides a skill is relevant, it calls the `load_skill` tool to load the full instructions into context
3. **Execution** — The agent follows the loaded instructions to complete the task
## Creating Skills [#creating-skills]
Skills live on the **Integrations** page: click **Integrations** in the workspace sidebar, then switch to the **Skills** tab. It lists every skill in the workspace, searchable by name. Click a skill to open its detail page, where you edit, share, and delete it.
Click **+ Add to Sim** to open the skill create page, which takes three fields:
| Field | Description |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Name** | A kebab-case identifier (e.g. `sql-expert`, `code-reviewer`). Max 64 characters. |
| **Description** | A short explanation of what the skill does and when to use it. This is what the agent reads to decide whether to activate the skill. Max 1024 characters. |
| **Content** | The full skill instructions in markdown. This is loaded when the agent activates the skill. |
The description is critical — it's the only thing the agent sees before deciding to load a skill. Be specific about when and why the skill should be used.
### Importing skills [#importing-skills]
Bring in an existing skill in the open [SKILL.md](https://agentskills.io/specification) format two ways:
* **Import** — the **Import** action on the create page takes a `.md` file with YAML frontmatter, or a `.zip` containing a `SKILL.md`.
* **Paste content** — paste the `SKILL.md` straight into **Content**. The frontmatter carries the `name` and `description`; the markdown body is the content.
Integration pages suggest **curated skills** for their service — open one (HubSpot, for example) and add a suggested skill with one click.
### Writing Good Skill Content [#writing-good-skill-content]
Skill content follows the same conventions as [SKILL.md files](https://agentskills.io/specification):
```markdown
# SQL Expert
## When to use this skill
Use when the user asks you to write, optimize, or debug SQL queries.
## Instructions
1. Always ask which database engine (PostgreSQL, MySQL, SQLite)
2. Use CTEs over subqueries for readability
3. Add index recommendations when relevant
4. Explain query plans for optimization requests
## Common Patterns
...
```
**Recommended structure:**
* **When to use** — Specific triggers and scenarios
* **Instructions** — Step-by-step guidance with numbered lists
* **Examples** — Input/output samples showing expected behavior
* **Common Patterns** — Reusable approaches for frequent tasks
* **Edge Cases** — Gotchas and special considerations
Keep skills focused and under 500 lines. If a skill grows too large, split it into multiple specialized skills.
## Skill Editors [#skill-editors]
Everyone in the workspace sees and uses every skill — including members who join later. Nobody needs to be added to a skill to use it.
Each skill has an explicit **editors** list. Editors can edit the skill, delete it, and manage the editors list. Workspace admins can always do this too — they are editors of every skill automatically and cannot be removed from the list. Whoever creates a skill becomes an editor.
Open a skill from the Skills tab to manage it. The detail page has the editable fields, a **Share** action for adding editors from your workspace members, and the **Skill Editors** list at the bottom.
The editors list controls who can edit a skill — it never affects who can see, use, or run it. A workflow that references a skill always executes it, no matter who runs the workflow. Treat skill content as shared team instructions, not as a secret.
## Using Skills in Chat [#using-skills-in-chat]
Skills work in Chat too. Type `/` in the message box to open the skills menu, then pick a skill — or keep typing to filter by name. The skill appears in your message as a tag, e.g. `/format-markdown`.
Tagging a skill loads its full instructions into the conversation, so Sim follows them for that request — no waiting for Sim to decide the skill is relevant on its own.
## Adding Skills to an Agent [#adding-skills-to-an-agent]
Open any **Agent** block and find the **Skills** dropdown below the tools section. Select the skills you want the agent to have access to.
Selected skills appear as cards that you can click to edit or remove.
### What Happens at Runtime [#what-happens-at-runtime]
When the workflow runs:
1. The agent's system prompt includes an `` section listing each skill's name and description
2. A `load_skill` tool is automatically added to the agent's available tools
3. When the agent determines a skill is relevant to the current task, it calls `load_skill` with the skill name
4. The full skill content is returned as a tool response, giving the agent detailed instructions
This works across all supported LLM providers — the `load_skill` tool uses standard tool-calling, so no provider-specific configuration is needed.
## When to use a skill [#when-to-use-a-skill]
Use a skill for reusable procedures or knowledge shared across agents, such as a company style guide or a debugging checklist. Keep task-specific instructions in the Agent block.
## Best Practices [#best-practices]
**Writing Effective Descriptions**
* **Be specific and keyword-rich** — Instead of "Helps with SQL", write "Write optimized SQL queries for PostgreSQL, MySQL, and SQLite, including index recommendations and query plan analysis"
* **Include activation triggers** — Mention specific words or phrases that should prompt the skill (e.g., "Use when the user mentions PDFs, forms, or document extraction")
* **Keep it under 200 words** — Agents scan descriptions quickly; make every word count
**Skill Scope and Organization**
* **One skill per domain** — A focused `sql-expert` skill works better than a broad `database-everything` skill
* **Limit to 5-10 skills per agent** — More skills = more decision overhead; start small and add as needed
* **Split large skills** — If a skill exceeds 500 lines, break it into focused sub-skills
**Content Structure**
* **Use markdown formatting** — Headers, lists, and code blocks help agents parse and follow instructions
* **Provide examples** — Show input/output pairs so agents understand expected behavior
* **Be explicit about edge cases** — Don't assume agents will infer special handling
**Testing and Iteration**
* **Test activation** — Run your workflow and verify the agent loads the skill when expected
* **Check for false positives** — Make sure skills aren't activating when they shouldn't
* **Refine descriptions** — If a skill isn't loading when needed, add more keywords to the description
## Learn More [#learn-more]
* [Agent Skills specification](https://agentskills.io) — The open format for portable agent skills
* [Example skills](https://github.com/anthropics/skills) — Browse community skill examples
* [Best practices](https://agentskills.io/what-are-skills) — Writing effective skills
---
# Authentication (/api-reference/authentication)
The Sim API accepts API keys and, when enabled by your deployment, OAuth access tokens. API keys support automation and the SDKs. OAuth lets the CLI and registered applications act on your behalf with permissions you approve.
Sim supports two types of API keys — **personal keys** and **workspace keys** — each with different billing and access behaviors.
## Key Types [#key-types]
| Feature | **Personal Keys** | **Workspace Keys** |
| --------------- | ------------------------------------------ | --------------------------- |
| **Billing** | Workspace payer for workspace-hosted usage | Workspace payer |
| **Scope** | Across workspaces you have access to | Shared across the workspace |
| **Managed by** | Each user individually | Workspace admins |
| **Permissions** | Must be enabled at workspace level | Require admin permissions |
Personal keys identify the user making a request; they do not select who pays.
Hosted usage is billed to the workspace's organization or personal billing
account and, for organizations, is attributed to the actor's member cap.
Workspace admins can disable personal API key usage for their workspace. If
disabled, only workspace keys can be used.
## Generating API Keys [#generating-api-keys]
To generate a personal key, open **Account settings** → **Sim API keys**. Workspace
administrators can create shared keys from **Workspace settings** → **Sim API keys**.
API keys are only shown once when generated. Store your key securely — you will not be able to view it again.
## Using API Keys [#using-api-keys]
Pass your API key in the `X-API-Key` header with every request:
```bash
curl -X POST https://www.sim.ai/api/v2/workflows/{workflowId}/execute \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"input": {}}'
```
```typescript
const response = await fetch(
'https://www.sim.ai/api/v2/workflows/{workflowId}/execute',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIM_API_KEY!,
},
body: JSON.stringify({ input: {} }),
}
)
```
```python
import requests
response = requests.post(
"https://www.sim.ai/api/v2/workflows/{workflowId}/execute",
headers={
"Content-Type": "application/json",
"X-API-Key": os.environ["SIM_API_KEY"],
},
json={"input": {}},
)
```
## Where Keys Are Used [#where-keys-are-used]
API keys authenticate access to:
* **Workflow execution** — run deployed workflows via the API
* **Logs API** — query workflow execution logs and metrics
* **MCP servers** — authenticate connections to deployed MCP servers
* **SDKs** — the [Python](/api-reference/python) and [TypeScript](/api-reference/typescript) SDKs use API keys for all operations
## OAuth access tokens [#oauth-access-tokens]
Use `sim login` to authorize the CLI in your browser, or `sim login --read-only` to request read access. The CLI stores the login locally and refreshes access tokens automatically. See [CLI authentication](/cli/authentication) for profiles, sign-in, and sign-out.
Registered OAuth applications send access tokens in the `Authorization` header:
```bash
curl https://www.sim.ai/api/v2/workspaces \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"
```
| Scope | Access |
| ---------------- | ---------------------------------------------------------------------------------------------------- |
| `api:read` | Read operations, including searches sent as POST requests |
| `api:write` | Includes `api:read`, plus mutations and execution, including operations that can start external work |
| `offline_access` | Refresh tokens for continued access after the access token expires |
Scopes limit what an application may do; your current workspace membership and role still apply. Each endpoint documents its required scope. Some GET endpoints that perform external discovery require `api:write`, so HTTP method alone does not determine the permission.
Manage grants in **Settings** → **General** → **Authorized apps**. Revoking an application signs out all of its logins. `sim logout` revokes the current CLI login and removes it from your machine. The Python and TypeScript SDKs currently use API keys; they do not manage OAuth sign-in or refresh tokens.
## Security [#security]
* Keys use the `sk-sim-` prefix and are encrypted at rest
* Keys can be revoked at any time from the dashboard
* Use environment variables to store keys — never hardcode them in source code
* For browser-based applications, use a backend proxy to avoid exposing keys to the client
Never expose your API key in client-side code. Use a server-side proxy to make authenticated requests on behalf of your frontend.
---
# Getting Started (/api-reference/getting-started)
## Base URL [#base-url]
All API requests are made to:
```
https://www.sim.ai
```
## OpenAPI specification [#openapi-specification]
Download the [complete OpenAPI 3.1 specification](/openapi.json) as JSON for client generation, request validation, and API tooling.
## Quick Start [#quick-start]
### Get your API key [#get-your-api-key]
Open **Account settings** → **Sim API keys** to create a personal key, or **Workspace settings** → **Sim API keys** for a workspace key. These examples and the SDKs use API keys; the CLI also supports browser sign-in with `sim login`. See [Authentication](/api-reference/authentication) for key types and OAuth permissions.
### Find your workflow ID [#find-your-workflow-id]
Open a workflow in the Sim editor. The workflow ID is in the URL:
```
https://www.sim.ai/workspace/{workspaceId}/w/{workflowId}
```
You can also use the [List Workflows](/api-reference/workflows/listWorkflows) endpoint to get all workflow IDs in a workspace.
### Deploy your workflow [#deploy-your-workflow]
A workflow must be deployed before it can be executed via the API. Click the **Deploy** button in the editor toolbar, or use the dashboard to manage deployments.
### Make your first request [#make-your-first-request]
```bash
curl -X POST https://www.sim.ai/api/v2/workflows/{workflowId}/execute \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"input": {}}'
```
```typescript
const response = await fetch(
`https://www.sim.ai/api/v2/workflows/${workflowId}/execute`,
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.SIM_API_KEY!,
},
body: JSON.stringify({ input: {} }),
}
)
const data = await response.json()
console.log(data.data.output)
```
```python
import requests
import os
response = requests.post(
f"https://www.sim.ai/api/v2/workflows/{workflow_id}/execute",
headers={
"Content-Type": "application/json",
"X-API-Key": os.environ["SIM_API_KEY"],
},
json={"input": {}},
)
data = response.json()
print(data["data"]["output"])
```
## Sync vs Async Execution [#sync-vs-async-execution]
By default, workflow executions are **synchronous** — the API blocks until the workflow completes and returns the result directly.
For long-running workflows, use **asynchronous execution** by passing `async: true`:
```bash
curl -X POST https://www.sim.ai/api/v2/workflows/{workflowId}/execute \
-H "Content-Type: application/json" \
-H "X-API-Key: YOUR_API_KEY" \
-d '{"input": {}, "async": true}'
```
Keyed callers can optionally provide `X-Run-Id: my-run-123` to choose the run ID. Run IDs cannot be reused; a duplicate returns `409`.
This returns immediately with a `runId` and `statusUrl`:
```json
{
"data": {
"runId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
"statusUrl": "https://www.sim.ai/api/v2/workflows/{workflowId}/runs/c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74"
}
}
```
Poll the run status endpoint until the status is terminal:
```bash
curl https://www.sim.ai/api/v2/workflows/{workflowId}/runs/{runId}?includeOutput=true \
-H "X-API-Key: YOUR_API_KEY"
```
Execution status transitions follow: `queued` → `running` → `completed`, `failed`, `cancelled`, or `paused`. The `data.output` field is populated for completed executions when `includeOutput=true`.
## Response Format [#response-format]
Successful v2 responses wrap the run resource in `data`:
```json
{
"data": {
"runId": "c7a92e15-3f4b-4d8c-a1e6-9b0d5f2c8e74",
"workflowId": "{workflowId}",
"status": "completed",
"output": { "result": "Hello, world!" },
"error": null,
"durationMs": 842
}
}
```
## Error Handling [#error-handling]
The API uses standard HTTP status codes. v2 errors include a stable code and human-readable message:
```json
{
"error": {
"code": "NOT_FOUND",
"message": "Workflow not found"
}
}
```
| Status | Meaning | What to do |
| ------ | -------------------------- | --------------------------------------------------- |
| `400` | Invalid request parameters | Check the `details` array for specific field errors |
| `401` | Missing or invalid API key | Verify your `X-API-Key` header |
| `403` | Access denied | Check you have permission for this resource |
| `404` | Resource not found | Verify the ID exists and belongs to your workspace |
| `429` | Rate limit exceeded | Wait for the duration in the `Retry-After` header |
### Unrecognized fields are rejected [#unrecognized-fields-are-rejected]
Every v2 endpoint validates the request against its published schema — path parameters, query string, and body — and answers `400` for any field it does not declare. A misspelled parameter is an error rather than a silent no-op, so `?limt=20` fails instead of quietly returning an unbounded list.
This holds for endpoints that declare no query parameters at all. Do not append tracking tags, cache busters, or other extra parameters to a v2 URL; send only what the endpoint documents.
```json
{
"error": {
"code": "BAD_REQUEST",
"message": "Invalid request",
"details": [
{ "code": "unrecognized_keys", "keys": ["limt"], "path": [], "message": "Unrecognized key: \"limt\"" }
]
}
}
```
Use [Get Billing Status](/api-reference/billing/getBillingStatus) to inspect current credit and storage usage.
## Rate Limits [#rate-limits]
Rate limits depend on your subscription plan and apply separately to synchronous and asynchronous executions.
When rate limited, the API returns a `429` response with a `Retry-After` header indicating how many seconds to wait before retrying.
## Pagination [#pagination]
List endpoints (workflows, logs, audit logs) use **cursor-based pagination**:
```bash
# First page
curl "https://www.sim.ai/api/v2/logs?limit=20" \
-H "X-API-Key: YOUR_API_KEY"
# Next page — use the nextCursor from the previous response
curl "https://www.sim.ai/api/v2/logs?limit=20&cursor=abc123" \
-H "X-API-Key: YOUR_API_KEY"
```
The response includes a `nextCursor` field. When `nextCursor` is absent or `null`, you have reached the last page.
---
# Python (/api-reference/python)
Use the Python SDK to execute workflows from Python applications.
The Python SDK supports Python 3.8+ with async execution support, retry helpers with exponential backoff, and usage tracking.
## Installation [#installation]
Install the SDK using pip:
```bash
pip install simstudio-sdk
```
## Quick Start [#quick-start]
Here's a simple example to get you started:
```python
from simstudio import SimStudioClient
# Initialize the client
client = SimStudioClient(
api_key="your-api-key-here",
base_url="https://sim.ai" # optional, defaults to https://sim.ai
)
# Execute a workflow
try:
result = client.execute_workflow("workflow-id")
print("Workflow executed successfully:", result)
except Exception as error:
print("Workflow execution failed:", error)
```
## API Reference [#api-reference]
### SimStudioClient [#simstudioclient]
#### Constructor [#constructor]
```python
SimStudioClient(api_key: str, base_url: str = "https://sim.ai")
```
**Parameters:**
* `api_key` (str): Your Sim API key
* `base_url` (str, optional): Base URL for the Sim API
#### Methods [#methods]
##### execute\_workflow() [#execute_workflow]
Execute a workflow with optional input data.
```python
result = client.execute_workflow(
"workflow-id",
input={"message": "Hello, world!"},
timeout=30.0 # 30 seconds
)
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow to execute
* `input` (dict, optional): Input data to pass to the workflow
* `timeout` (float, optional): Timeout in seconds (default: 30.0)
* `stream` (bool, optional): Enable streaming responses (default: False)
* `selected_outputs` (list\[str], optional): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
* `async_execution` (bool, optional): Execute asynchronously (default: False)
* `execution_timeout_seconds` (int, optional): Optional server-side async execution cap from 1 to 604800 seconds. Requires `async_execution=True` and cannot extend the account policy.
**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`
When `async_execution=True`, returns immediately with a `run_id` and `status_url` for polling. Otherwise, waits for completion.
##### get\_workflow\_status() [#get_workflow_status]
Get the status of a workflow (deployment status, etc.).
```python
status = client.get_workflow_status("workflow-id")
print("Is deployed:", status.is_deployed)
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow
**Returns:** `WorkflowStatus`
##### validate\_workflow() [#validate_workflow]
Validate that a workflow is ready for execution.
```python
is_ready = client.validate_workflow("workflow-id")
if is_ready:
# Workflow is deployed and ready
pass
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow
**Returns:** `bool`
##### get\_workflow\_run() [#get_workflow_run]
Get the status and optional outputs of a workflow execution.
```python
status = client.get_workflow_run("workflow-id", "run-id", include_output=True)
print("Status:", status["status"]) # 'queued', 'running', 'completed', 'failed'
if status["status"] == "completed":
print("Output:", status["output"])
```
**Parameters:**
* `workflow_id` (str): The workflow ID
* `run_id` (str): The run ID returned from async execution
* `include_output` (bool, optional): Include the final output for completed executions
* `selected_outputs` (list\[str], optional): Block output selectors to include
**Returns:** `Dict[str, Any]`
**Response fields:**
* `runId` (str): The run ID
* `workflowId` (str): The workflow ID
* `status` (str): One of `'queued'`, `'pending'`, `'running'`, `'paused'`, `'completed'`, `'failed'`, `'cancelled'`
* `startedAt` / `endedAt` (str): Execution timestamps
* `durationMs` (int, optional): Duration in milliseconds
* `output` (any, optional): The workflow output when requested for a completed execution
* `blockOutputs` (dict, optional): Requested block outputs
* `error` (dict, optional): Structured failure details with `code`, `message`, and optional `details`
##### get\_job\_status() [#get_job_status]
Get the status of a job created through the legacy async execution endpoint. New integrations should use `get_workflow_run()` with the run ID instead.
```python
status = client.get_job_status("legacy-job-id")
```
##### execute\_with\_retry() [#execute_with_retry]
Execute a workflow with automatic retry on rate limit errors using exponential backoff.
```python
result = client.execute_with_retry(
"workflow-id",
input={"message": "Hello"},
timeout=30.0,
max_retries=3, # Maximum number of retries
initial_delay=1.0, # Initial delay in seconds
max_delay=30.0, # Maximum delay in seconds
backoff_multiplier=2.0 # Exponential backoff multiplier
)
```
**Parameters:**
* `workflow_id` (str): The ID of the workflow to execute
* `input` (dict, optional): Input data to pass to the workflow
* `timeout` (float, optional): Timeout in seconds
* `stream` (bool, optional): Enable streaming responses
* `selected_outputs` (list, optional): Block outputs to stream
* `async_execution` (bool, optional): Execute asynchronously
* `max_retries` (int, optional): Maximum number of retries (default: 3)
* `initial_delay` (float, optional): Initial delay in seconds (default: 1.0)
* `max_delay` (float, optional): Maximum delay in seconds (default: 30.0)
* `backoff_multiplier` (float, optional): Backoff multiplier (default: 2.0)
**Returns:** `WorkflowExecutionResult | AsyncExecutionResult`
The retry logic uses exponential backoff (1s → 2s → 4s → 8s...) with ±25% jitter to prevent thundering herd. If the API provides a `retry-after` header, it will be used instead.
##### get\_rate\_limit\_info() [#get_rate_limit_info]
Get the current rate limit information from the last API response.
```python
rate_limit_info = client.get_rate_limit_info()
if rate_limit_info:
print("Limit:", rate_limit_info.limit)
print("Remaining:", rate_limit_info.remaining)
print("Reset:", datetime.fromtimestamp(rate_limit_info.reset))
```
**Returns:** `RateLimitInfo | None`
##### get\_usage\_limits() [#get_usage_limits]
Get current usage limits and quota information for your account.
```python
limits = client.get_usage_limits()
print("Sync requests remaining:", limits.rate_limit["sync"]["remaining"])
print("Async requests remaining:", limits.rate_limit["async"]["remaining"])
print("Current period cost:", limits.usage["currentPeriodCost"])
print("Plan:", limits.usage["plan"])
```
**Returns:** `UsageLimits`
**Response structure:**
```python
{
"success": bool,
"rateLimit": {
"sync": {
"isLimited": bool,
"limit": int,
"remaining": int,
"resetAt": str
},
"async": {
"isLimited": bool,
"limit": int,
"remaining": int,
"resetAt": str
},
"authType": str # 'api' or 'manual'
},
"usage": {
"currentPeriodCost": float,
"limit": float,
"plan": str # e.g., 'free', 'pro'
}
}
```
##### set\_api\_key() [#set_api_key]
Update the API key.
```python
client.set_api_key("new-api-key")
```
##### set\_base\_url() [#set_base_url]
Update the base URL.
```python
client.set_base_url("https://my-custom-domain.com")
```
##### close() [#close]
Close the underlying HTTP session.
```python
client.close()
```
## Data Classes [#data-classes]
### WorkflowExecutionResult [#workflowexecutionresult]
```python
@dataclass
class WorkflowExecutionResult:
success: bool
output: Optional[Any] = None
error: Optional[str] = None
logs: Optional[List[Any]] = None
metadata: Optional[Dict[str, Any]] = None
trace_spans: Optional[List[Any]] = None
total_duration: Optional[float] = None
status: Optional[str] = None
```
`success` is `True` only for the `completed` and `paused` statuses. `status` carries the server's terminal status verbatim, so a cancelled run (`success=False`, `error=None`) is distinguishable from a failed one.
### AsyncExecutionResult [#asyncexecutionresult]
```python
@dataclass
class AsyncExecutionResult:
success: bool
run_id: str
status_url: str
message: str = ""
async_execution: bool = True
```
### WorkflowStatus [#workflowstatus]
```python
@dataclass
class WorkflowStatus:
is_deployed: bool
deployed_at: Optional[str] = None
needs_redeployment: bool = False
```
### RateLimitInfo [#ratelimitinfo]
```python
@dataclass
class RateLimitInfo:
limit: int
remaining: int
reset: int
retry_after: Optional[int] = None
```
### UsageLimits [#usagelimits]
```python
@dataclass
class UsageLimits:
success: bool
rate_limit: Dict[str, Any]
usage: Dict[str, Any]
```
### SimStudioError [#simstudioerror]
```python
class SimStudioError(Exception):
def __init__(self, message: str, code: Optional[str] = None, status: Optional[int] = None):
super().__init__(message)
self.code = code
self.status = status
```
**Common error codes:**
* `UNAUTHORIZED`: Invalid API key
* `TIMEOUT`: Request timed out
* `RATE_LIMIT_EXCEEDED`: Rate limit exceeded
* `USAGE_LIMIT_EXCEEDED`: Usage limit exceeded
* `EXECUTION_ERROR`: Workflow execution failed
## Examples [#examples]
### Basic Workflow Execution [#basic-workflow-execution]
Set up the SimStudioClient with your API key.
Check if the workflow is deployed and ready for execution.
Run the workflow with your input data.
Process the execution result and handle any errors.
```python
import os
from simstudio import SimStudioClient
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def run_workflow():
try:
# Check if workflow is ready
is_ready = client.validate_workflow("my-workflow-id")
if not is_ready:
raise Exception("Workflow is not deployed or ready")
# Execute the workflow
result = client.execute_workflow(
"my-workflow-id",
input={
"message": "Process this data",
"user_id": "12345"
}
)
if result.success:
print("Output:", result.output)
print("Duration:", result.metadata.get("duration") if result.metadata else None)
else:
print("Workflow failed:", result.error)
except Exception as error:
print("Error:", error)
run_workflow()
```
### Error Handling [#error-handling]
Handle different types of errors that may occur during workflow execution:
```python
from simstudio import SimStudioClient, SimStudioError
import os
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_with_error_handling():
try:
result = client.execute_workflow("workflow-id")
return result
except SimStudioError as error:
if error.code == "UNAUTHORIZED":
print("Invalid API key")
elif error.code == "TIMEOUT":
print("Workflow execution timed out")
elif error.code == "USAGE_LIMIT_EXCEEDED":
print("Usage limit exceeded")
elif error.code == "INVALID_JSON":
print("Invalid JSON in request body")
else:
print(f"Workflow error: {error}")
raise
except Exception as error:
print(f"Unexpected error: {error}")
raise
```
### Context Manager Usage [#context-manager-usage]
Use the client as a context manager to automatically handle resource cleanup:
```python
from simstudio import SimStudioClient
import os
# Using context manager to automatically close the session
with SimStudioClient(api_key=os.getenv("SIM_API_KEY")) as client:
result = client.execute_workflow("workflow-id")
print("Result:", result)
# Session is automatically closed here
```
### Batch Workflow Execution [#batch-workflow-execution]
Execute multiple workflows efficiently:
```python
from simstudio import SimStudioClient
import os
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_workflows_batch(workflow_data_pairs):
"""Execute multiple workflows with different input data."""
results = []
for workflow_id, input_data in workflow_data_pairs:
try:
# Validate workflow before execution
if not client.validate_workflow(workflow_id):
print(f"Skipping {workflow_id}: not deployed")
continue
result = client.execute_workflow(workflow_id, input_data)
results.append({
"workflow_id": workflow_id,
"success": result.success,
"output": result.output,
"error": result.error
})
except Exception as error:
results.append({
"workflow_id": workflow_id,
"success": False,
"error": str(error)
})
return results
# Example usage
workflows = [
("workflow-1", {"type": "analysis", "data": "sample1"}),
("workflow-2", {"type": "processing", "data": "sample2"}),
]
results = execute_workflows_batch(workflows)
for result in results:
print(f"Workflow {result['workflow_id']}: {'Success' if result['success'] else 'Failed'}")
```
### Async Workflow Execution [#async-workflow-execution]
Execute workflows asynchronously for long-running tasks:
```python
import os
import time
from simstudio import SimStudioClient
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_async():
try:
# Start async execution
result = client.execute_workflow(
"workflow-id",
input={"data": "large dataset"},
async_execution=True # Execute asynchronously
)
# Check if result is an async execution
if hasattr(result, 'async_execution') and result.async_execution:
print(f"Run ID: {result.run_id}")
print(f"Status endpoint: {result.status_url}")
# Poll for completion
status = client.get_workflow_run(
"workflow-id", result.run_id, include_output=True
)
while status["status"] in ["queued", "pending", "running"]:
print(f"Current status: {status['status']}")
time.sleep(2) # Wait 2 seconds
status = client.get_workflow_run(
"workflow-id", result.run_id, include_output=True
)
if status["status"] == "completed":
print("Workflow completed!")
print(f"Output: {status['output']}")
print(f"Duration: {status['durationMs']}")
elif status["status"] == "paused":
print("Workflow is paused and waiting for input or resumption.")
elif status["status"] == "cancelled":
print("Workflow was cancelled.")
else:
print(f"Workflow failed: {status['error']}")
except Exception as error:
print(f"Error: {error}")
execute_async()
```
### Rate Limiting and Retry [#rate-limiting-and-retry]
Handle rate limits automatically with exponential backoff:
```python
import os
from simstudio import SimStudioClient, SimStudioError
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_with_retry_handling():
try:
# Automatically retries on rate limit
result = client.execute_with_retry(
"workflow-id",
input={"message": "Process this"},
max_retries=5,
initial_delay=1.0,
max_delay=60.0,
backoff_multiplier=2.0
)
print(f"Success: {result}")
except SimStudioError as error:
if error.code == "RATE_LIMIT_EXCEEDED":
print("Rate limit exceeded after all retries")
# Check rate limit info
rate_limit_info = client.get_rate_limit_info()
if rate_limit_info:
from datetime import datetime
reset_time = datetime.fromtimestamp(rate_limit_info.reset)
print(f"Rate limit resets at: {reset_time}")
execute_with_retry_handling()
```
### Usage Monitoring [#usage-monitoring]
Monitor your account usage and limits:
```python
import os
from simstudio import SimStudioClient
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def check_usage():
try:
limits = client.get_usage_limits()
print("=== Rate Limits ===")
print("Sync requests:")
print(f" Limit: {limits.rate_limit['sync']['limit']}")
print(f" Remaining: {limits.rate_limit['sync']['remaining']}")
print(f" Resets at: {limits.rate_limit['sync']['resetAt']}")
print(f" Is limited: {limits.rate_limit['sync']['isLimited']}")
print("\nAsync requests:")
print(f" Limit: {limits.rate_limit['async']['limit']}")
print(f" Remaining: {limits.rate_limit['async']['remaining']}")
print(f" Resets at: {limits.rate_limit['async']['resetAt']}")
print(f" Is limited: {limits.rate_limit['async']['isLimited']}")
print("\n=== Usage ===")
print(f"Current period cost: ${limits.usage['currentPeriodCost']:.2f}")
print(f"Limit: ${limits.usage['limit']:.2f}")
print(f"Plan: {limits.usage['plan']}")
percent_used = (limits.usage['currentPeriodCost'] / limits.usage['limit']) * 100
print(f"Usage: {percent_used:.1f}%")
if percent_used > 80:
print("⚠️ Warning: You are approaching your usage limit!")
except Exception as error:
print(f"Error checking usage: {error}")
check_usage()
```
### Streaming Workflow Execution [#streaming-workflow-execution]
Execute workflows with real-time streaming responses:
```python
from simstudio import SimStudioClient
import os
client = SimStudioClient(api_key=os.getenv("SIM_API_KEY"))
def execute_with_streaming():
"""Execute workflow with streaming enabled."""
try:
# Enable streaming for specific block outputs
result = client.execute_workflow(
"workflow-id",
input={"message": "Count to five"},
stream=True,
selected_outputs=["agent1.content"] # Use blockName.attribute format
)
print("Workflow result:", result)
except Exception as error:
print("Error:", error)
execute_with_streaming()
```
The streaming response follows the Server-Sent Events (SSE) format:
```
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"}
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"}
data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
data: [DONE]
```
**Flask Streaming Example:**
```python
from flask import Flask, Response, stream_with_context
import requests
import json
import os
app = Flask(__name__)
@app.route('/stream-workflow')
def stream_workflow():
"""Stream workflow execution to the client."""
def generate():
response = requests.post(
'https://sim.ai/api/v2/workflows/WORKFLOW_ID/execute',
headers={
'Content-Type': 'application/json',
'X-API-Key': os.getenv('SIM_API_KEY')
},
json={
'input': {'message': 'Generate a story'},
'stream': True,
'selectedOutputs': ['agent1.content']
},
stream=True
)
for line in response.iter_lines():
if line:
decoded_line = line.decode('utf-8')
if decoded_line.startswith('data: '):
data = decoded_line[6:] # Remove 'data: ' prefix
if data == '[DONE]':
break
try:
parsed = json.loads(data)
if 'chunk' in parsed:
yield f"data: {json.dumps(parsed)}\n\n"
elif parsed.get('event') == 'done':
yield f"data: {json.dumps(parsed)}\n\n"
print("Execution complete:", parsed.get('metadata'))
except json.JSONDecodeError:
pass
return Response(
stream_with_context(generate()),
mimetype='text/event-stream'
)
if __name__ == '__main__':
app.run(debug=True)
```
### Environment Configuration [#environment-configuration]
Configure the client using environment variables:
```python
import os
from simstudio import SimStudioClient
# Development configuration
client = SimStudioClient(
api_key=os.getenv("SIM_API_KEY"),
base_url=os.getenv("SIM_BASE_URL", "https://sim.ai")
)
```
```python
import os
from simstudio import SimStudioClient
# Production configuration with error handling
api_key = os.getenv("SIM_API_KEY")
if not api_key:
raise ValueError("SIM_API_KEY environment variable is required")
client = SimStudioClient(
api_key=api_key,
base_url=os.getenv("SIM_BASE_URL", "https://sim.ai")
)
```
## Getting Your API Key [#getting-your-api-key]
Create a key in **Account settings → Sim API keys**, or use a workspace key if your administrator requires one. See [Authentication](/api-reference/authentication) for key types and permissions. Deploy the workflow before calling it through the SDK. Keep the key in a server-side environment variable.
## Requirements [#requirements]
* Python 3.8+
* requests >= 2.25.0
## License [#license]
Apache-2.0
---
# TypeScript (/api-reference/typescript)
Use the TypeScript SDK to execute workflows from server-side JavaScript or TypeScript. For browser applications, call the SDK through your authenticated backend.
The TypeScript SDK provides full type safety, async execution support, retry helpers with exponential backoff, and usage tracking.
## Installation [#installation]
Install the SDK using your preferred package manager:
```bash
npm install simstudio-ts-sdk
```
```bash
yarn add simstudio-ts-sdk
```
```bash
bun add simstudio-ts-sdk
```
## Quick Start [#quick-start]
Here's a simple example to get you started:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Initialize the client
const client = new SimStudioClient({
apiKey: 'your-api-key-here',
baseUrl: 'https://sim.ai' // optional, defaults to https://sim.ai
});
// Execute a workflow
try {
const result = await client.executeWorkflow('workflow-id');
console.log('Workflow executed successfully:', result);
} catch (error) {
console.error('Workflow execution failed:', error);
}
```
## API Reference [#api-reference]
### SimStudioClient [#simstudioclient]
#### Constructor [#constructor]
```typescript
new SimStudioClient(config: SimStudioConfig)
```
**Configuration:**
* `config.apiKey` (string): Your Sim API key
* `config.baseUrl` (string, optional): Base URL for the Sim API (defaults to `https://sim.ai`)
#### Methods [#methods]
##### executeWorkflow() [#executeworkflow]
Execute a workflow with optional input data.
```typescript
const result = await client.executeWorkflow('workflow-id', { message: 'Hello, world!' }, {
timeout: 30000 // 30 seconds
});
```
**Parameters:**
* `workflowId` (string): The ID of the workflow to execute
* `input` (any, optional): Input data to pass to the workflow
* `options` (ExecutionOptions, optional):
* `timeout` (number): Timeout in milliseconds (default: 30000)
* `stream` (boolean): Enable streaming responses (default: false)
* `selectedOutputs` (string\[]): Block outputs to stream in `blockName.attribute` format (e.g., `["agent1.content"]`)
* `async` (boolean): Execute asynchronously (default: false)
* `executionTimeoutSeconds` (number): Optional server-side async execution cap from 1 to 604800 seconds. Requires `async: true` and cannot extend the account policy.
**Returns:** `Promise`
When `async: true`, returns immediately with a `runId` and `statusUrl` for polling. Otherwise, waits for completion.
##### getWorkflowStatus() [#getworkflowstatus]
Get the status of a workflow (deployment status, etc.).
```typescript
const status = await client.getWorkflowStatus('workflow-id');
console.log('Is deployed:', status.isDeployed);
```
**Parameters:**
* `workflowId` (string): The ID of the workflow
**Returns:** `Promise`
##### validateWorkflow() [#validateworkflow]
Validate that a workflow is ready for execution.
```typescript
const isReady = await client.validateWorkflow('workflow-id');
if (isReady) {
// Workflow is deployed and ready
}
```
**Parameters:**
* `workflowId` (string): The ID of the workflow
**Returns:** `Promise`
##### getWorkflowRun() [#getworkflowrun]
Get the status and optional outputs of a workflow run.
```typescript
const status = await client.getWorkflowRun('workflow-id', 'run-id', {
includeOutput: true
});
console.log('Status:', status.status); // 'queued', 'running', 'completed', 'failed'
if (status.status === 'completed') {
console.log('Output:', status.output);
}
```
**Parameters:**
* `workflowId` (string): The workflow ID
* `runId` (string): The run ID returned from async execution
* `options.includeOutput` (boolean, optional): Include the final output for completed executions
* `options.selectedOutputs` (string\[], optional): Block output selectors to include
**Returns:** `Promise`
**Response fields:**
* `runId` (string): The run ID
* `workflowId` (string): The workflow ID
* `status` (string): One of `'queued'`, `'pending'`, `'running'`, `'paused'`, `'completed'`, `'failed'`, `'cancelled'`
* `startedAt` / `endedAt` (string): Execution timestamps
* `durationMs` (number, nullable): Duration in milliseconds
* `output` (any, nullable): The workflow output when requested for a completed execution
* `blockOutputs` (object, nullable): Requested block outputs
* `error` (object, nullable): Structured failure details with `code`, `message`, and optional `details`
##### getJobStatus() [#getjobstatus]
Get the status of a job created through the legacy async execution endpoint. New integrations should use `getWorkflowRun()` with the run ID instead.
```typescript
const status = await client.getJobStatus('legacy-job-id');
```
##### executeWithRetry() [#executewithretry]
Execute a workflow with automatic retry on rate limit errors using exponential backoff.
```typescript
const result = await client.executeWithRetry('workflow-id', { message: 'Hello' }, {
timeout: 30000
}, {
maxRetries: 3, // Maximum number of retries
initialDelay: 1000, // Initial delay in ms (1 second)
maxDelay: 30000, // Maximum delay in ms (30 seconds)
backoffMultiplier: 2 // Exponential backoff multiplier
});
```
**Parameters:**
* `workflowId` (string): The ID of the workflow to execute
* `input` (any, optional): Input data to pass to the workflow
* `options` (ExecutionOptions, optional): Same as `executeWorkflow()`
* `retryOptions` (RetryOptions, optional):
* `maxRetries` (number): Maximum number of retries (default: 3)
* `initialDelay` (number): Initial delay in ms (default: 1000)
* `maxDelay` (number): Maximum delay in ms (default: 30000)
* `backoffMultiplier` (number): Backoff multiplier (default: 2)
**Returns:** `Promise`
The retry logic uses exponential backoff (1s → 2s → 4s → 8s...) with ±25% jitter to prevent thundering herd. If the API provides a `retry-after` header, it will be used instead.
##### getRateLimitInfo() [#getratelimitinfo]
Get the current rate limit information from the last API response.
```typescript
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Limit:', rateLimitInfo.limit);
console.log('Remaining:', rateLimitInfo.remaining);
console.log('Reset:', new Date(rateLimitInfo.reset * 1000));
}
```
**Returns:** `RateLimitInfo | null`
##### getUsageLimits() [#getusagelimits]
Get current usage limits and quota information for your account.
```typescript
const limits = await client.getUsageLimits();
console.log('Sync requests remaining:', limits.rateLimit.sync.remaining);
console.log('Async requests remaining:', limits.rateLimit.async.remaining);
console.log('Current period cost:', limits.usage.currentPeriodCost);
console.log('Plan:', limits.usage.plan);
```
**Returns:** `Promise`
**Response structure:**
```typescript
{
success: boolean
rateLimit: {
sync: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
async: {
isLimited: boolean
limit: number
remaining: number
resetAt: string
}
authType: string // 'api' or 'manual'
}
usage: {
currentPeriodCost: number
limit: number
plan: string // e.g., 'free', 'pro'
}
}
```
##### setApiKey() [#setapikey]
Update the API key.
```typescript
client.setApiKey('new-api-key');
```
##### setBaseUrl() [#setbaseurl]
Update the base URL.
```typescript
client.setBaseUrl('https://my-custom-domain.com');
```
## Types [#types]
### WorkflowExecutionResult [#workflowexecutionresult]
```typescript
interface WorkflowExecutionResult {
success: boolean;
output?: any;
error?: string;
logs?: any[];
metadata?: {
duration?: number;
runId?: string;
[key: string]: any;
};
traceSpans?: any[];
totalDuration?: number;
}
```
### AsyncExecutionResult [#asyncexecutionresult]
```typescript
interface AsyncExecutionResult {
success: boolean;
runId: string;
statusUrl: string;
message: string;
async: true;
}
```
### WorkflowStatus [#workflowstatus]
```typescript
interface WorkflowStatus {
isDeployed: boolean;
deployedAt?: string;
needsRedeployment: boolean;
}
```
### RateLimitInfo [#ratelimitinfo]
```typescript
interface RateLimitInfo {
limit: number;
remaining: number;
reset: number;
retryAfter?: number;
}
```
### UsageLimits [#usagelimits]
```typescript
interface UsageLimits {
success: boolean;
rateLimit: {
sync: {
isLimited: boolean;
limit: number;
remaining: number;
resetAt: string;
};
async: {
isLimited: boolean;
limit: number;
remaining: number;
resetAt: string;
};
authType: string;
};
usage: {
currentPeriodCost: number;
limit: number;
plan: string;
};
}
```
### SimStudioError [#simstudioerror]
```typescript
class SimStudioError extends Error {
code?: string;
status?: number;
}
```
**Common error codes:**
* `UNAUTHORIZED`: Invalid API key
* `TIMEOUT`: Request timed out
* `RATE_LIMIT_EXCEEDED`: Rate limit exceeded
* `USAGE_LIMIT_EXCEEDED`: Usage limit exceeded
* `EXECUTION_ERROR`: Workflow execution failed
## Examples [#examples]
### Basic Workflow Execution [#basic-workflow-execution]
Set up the SimStudioClient with your API key.
Check if the workflow is deployed and ready for execution.
Run the workflow with your input data.
Process the execution result and handle any errors.
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function runWorkflow() {
try {
// Check if workflow is ready
const isReady = await client.validateWorkflow('my-workflow-id');
if (!isReady) {
throw new Error('Workflow is not deployed or ready');
}
// Execute the workflow
const result = await client.executeWorkflow('my-workflow-id', {
message: 'Process this data',
userId: '12345'
});
if (result.success) {
console.log('Output:', result.output);
console.log('Duration:', result.metadata?.duration);
} else {
console.error('Workflow failed:', result.error);
}
} catch (error) {
console.error('Error:', error);
}
}
runWorkflow();
```
### Error Handling [#error-handling]
Handle different types of errors that may occur during workflow execution:
```typescript
import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithErrorHandling() {
try {
const result = await client.executeWorkflow('workflow-id');
return result;
} catch (error) {
if (error instanceof SimStudioError) {
switch (error.code) {
case 'UNAUTHORIZED':
console.error('Invalid API key');
break;
case 'TIMEOUT':
console.error('Workflow execution timed out');
break;
case 'USAGE_LIMIT_EXCEEDED':
console.error('Usage limit exceeded');
break;
case 'INVALID_JSON':
console.error('Invalid JSON in request body');
break;
default:
console.error('Workflow error:', error.message);
}
} else {
console.error('Unexpected error:', error);
}
throw error;
}
}
```
### Environment Configuration [#environment-configuration]
Configure the client using environment variables:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Development configuration
const apiKey = process.env.SIM_API_KEY;
if (!apiKey) {
throw new Error('SIM_API_KEY environment variable is required');
}
const client = new SimStudioClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL // optional
});
```
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
// Production configuration with validation
const apiKey = process.env.SIM_API_KEY;
if (!apiKey) {
throw new Error('SIM_API_KEY environment variable is required');
}
const client = new SimStudioClient({
apiKey,
baseUrl: process.env.SIM_BASE_URL || 'https://sim.ai'
});
```
### Node.js Express Integration [#nodejs-express-integration]
Integrate with an Express.js server:
```typescript
import express from 'express';
import { SimStudioClient } from 'simstudio-ts-sdk';
const app = express();
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
app.use(express.json());
app.post('/execute-workflow', async (req, res) => {
try {
const { workflowId, input } = req.body;
const result = await client.executeWorkflow(workflowId, input, {
timeout: 60000
});
res.json({
success: true,
data: result
});
} catch (error) {
console.error('Workflow execution error:', error);
res.status(500).json({
success: false,
error: error instanceof Error ? error.message : 'Unknown error'
});
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
```
### Next.js API Route [#nextjs-api-route]
Use with Next.js API routes:
```typescript
// pages/api/workflow.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
const { workflowId, input } = req.body;
const result = await client.executeWorkflow(workflowId, input, {
timeout: 30000
});
res.status(200).json(result);
} catch (error) {
console.error('Error executing workflow:', error);
res.status(500).json({
error: 'Failed to execute workflow'
});
}
}
```
### Browser Usage [#browser-usage]
Keep the Sim API key on your server. A browser application should call an authenticated backend endpoint that checks which workflow the user can run, then calls the SDK. The [Next.js API Route](#nextjs-api-route) example shows where the server-side SDK call belongs; add your application authentication and authorization before executing a workflow.
### File Upload [#file-upload]
File objects are automatically detected and converted to base64 format. Include them in your input under the field name matching your workflow's API trigger input format.
The SDK converts File objects to this format:
```typescript
{
type: 'file',
data: 'data:mime/type;base64,base64data',
name: 'filename',
mime: 'mime/type'
}
```
Alternatively, you can manually provide files using the URL format:
```typescript
{
type: 'url',
data: 'https://example.com/file.pdf',
name: 'file.pdf',
mime: 'application/pdf'
}
```
Run file uploads on your backend after authenticating the caller and validating the upload. For example, in Node.js:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
import { readFile } from 'node:fs/promises';
const client = new SimStudioClient({ apiKey: process.env.SIM_API_KEY! });
const fileBuffer = await readFile('./document.pdf');
const file = new File([fileBuffer], 'document.pdf', { type: 'application/pdf' });
const result = await client.executeWorkflow('workflow-id', {
documents: [file],
query: 'Summarize this document'
});
```
### Async Workflow Execution [#async-workflow-execution]
Execute workflows asynchronously for long-running tasks:
```typescript
import { SimStudioClient, AsyncExecutionResult } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeAsync() {
try {
// Start async execution
const result = await client.executeWorkflow('workflow-id', { data: 'large dataset' }, {
async: true // Execute asynchronously
});
// Check if result is an async execution
if ('async' in result && result.async) {
console.log('Run ID:', result.runId);
console.log('Status endpoint:', result.statusUrl);
// Poll for completion
let status = await client.getWorkflowRun('workflow-id', result.runId, {
includeOutput: true
});
while (status.status === 'queued' || status.status === 'pending' || status.status === 'running') {
console.log('Current status:', status.status);
await new Promise(resolve => setTimeout(resolve, 2000)); // Wait 2 seconds
status = await client.getWorkflowRun('workflow-id', result.runId, {
includeOutput: true
});
}
if (status.status === 'completed') {
console.log('Workflow completed!');
console.log('Output:', status.output);
console.log('Duration:', status.durationMs);
} else if (status.status === 'paused') {
console.log('Workflow is paused and waiting for input or resumption.');
} else if (status.status === 'cancelled') {
console.log('Workflow was cancelled.');
} else {
console.error('Workflow failed:', status.error);
}
}
} catch (error) {
console.error('Error:', error);
}
}
executeAsync();
```
### Rate Limiting and Retry [#rate-limiting-and-retry]
Handle rate limits automatically with exponential backoff:
```typescript
import { SimStudioClient, SimStudioError } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithRetryHandling() {
try {
// Automatically retries on rate limit
const result = await client.executeWithRetry('workflow-id', { message: 'Process this' }, {}, {
maxRetries: 5,
initialDelay: 1000,
maxDelay: 60000,
backoffMultiplier: 2
});
console.log('Success:', result);
} catch (error) {
if (error instanceof SimStudioError && error.code === 'RATE_LIMIT_EXCEEDED') {
console.error('Rate limit exceeded after all retries');
// Check rate limit info
const rateLimitInfo = client.getRateLimitInfo();
if (rateLimitInfo) {
console.log('Rate limit resets at:', new Date(rateLimitInfo.reset * 1000));
}
}
}
}
```
### Usage Monitoring [#usage-monitoring]
Monitor your account usage and limits:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function checkUsage() {
try {
const limits = await client.getUsageLimits();
console.log('=== Rate Limits ===');
console.log('Sync requests:');
console.log(' Limit:', limits.rateLimit.sync.limit);
console.log(' Remaining:', limits.rateLimit.sync.remaining);
console.log(' Resets at:', limits.rateLimit.sync.resetAt);
console.log(' Is limited:', limits.rateLimit.sync.isLimited);
console.log('\nAsync requests:');
console.log(' Limit:', limits.rateLimit.async.limit);
console.log(' Remaining:', limits.rateLimit.async.remaining);
console.log(' Resets at:', limits.rateLimit.async.resetAt);
console.log(' Is limited:', limits.rateLimit.async.isLimited);
console.log('\n=== Usage ===');
console.log('Current period cost: $' + limits.usage.currentPeriodCost.toFixed(2));
console.log('Limit: $' + limits.usage.limit.toFixed(2));
console.log('Plan:', limits.usage.plan);
const percentUsed = (limits.usage.currentPeriodCost / limits.usage.limit) * 100;
console.log('Usage: ' + percentUsed.toFixed(1) + '%');
if (percentUsed > 80) {
console.warn('⚠️ Warning: You are approaching your usage limit!');
}
} catch (error) {
console.error('Error checking usage:', error);
}
}
checkUsage();
```
### Streaming Workflow Execution [#streaming-workflow-execution]
Execute workflows with real-time streaming responses:
```typescript
import { SimStudioClient } from 'simstudio-ts-sdk';
const client = new SimStudioClient({
apiKey: process.env.SIM_API_KEY!
});
async function executeWithStreaming() {
try {
// Enable streaming for specific block outputs
const result = await client.executeWorkflow('workflow-id', { message: 'Count to five' }, {
stream: true,
selectedOutputs: ['agent1.content'] // Use blockName.attribute format
});
console.log('Workflow result:', result);
} catch (error) {
console.error('Error:', error);
}
}
```
The streaming response follows the Server-Sent Events (SSE) format:
```
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":"One"}
data: {"blockId":"7b7735b9-19e5-4bd6-818b-46aae2596e9f","chunk":", two"}
data: {"event":"done","success":true,"output":{},"metadata":{"duration":610}}
data: [DONE]
```
For browser streaming, have your authenticated backend forward the Sim SSE response. Keep the Sim API key on the backend, check the upstream response status, and parse complete SSE events across network chunks. See [streaming responses](/workflows/deployment/api#streaming) for the event format.
## Getting Your API Key [#getting-your-api-key]
Create a key in **Account settings → Sim API keys**, or use a workspace key if your administrator requires one. See [Authentication](/api-reference/authentication) for key types and permissions. Deploy the workflow before calling it through the SDK. Keep the key in a server-side environment variable.
## Requirements [#requirements]
* Node.js 16+
* TypeScript 5.0+ (for TypeScript projects)
## License [#license]
Apache-2.0
---
# Sim Desktop (/desktop)
Sim Desktop is the macOS app for your Sim workspace. Everything the web app does, it does — plus the things a browser tab cannot: a built-in browser and terminal, read-only access to folders you pick, and native notifications when a task finishes.
## Download [#download]
**[Download Sim Desktop for macOS](https://sim.ai/api/desktop/update/download)**
One universal build runs natively on both Apple Silicon and Intel Macs. It is signed and notarized by Sim, so Gatekeeper accepts it with no override.
That link is never version-pinned — it is a redirect resolved at request time, so it always lands on the newest release. Bookmark it, share it, or put it in an MDM policy; it stays correct.
It resolves against sim.ai. Every deployment serves the same endpoint on its own origin, so if you self-host use yours — `https://sim.example.com/api/desktop/update/download` — to get the build your deployment offers.
To install a specific version instead of the newest one, pick it from [the releases page](https://github.com/simstudioai/sim/releases) and download that release's `Sim--universal.dmg`.
## Install [#install]
### Open the disk image and drag Sim to Applications [#open-the-disk-image-and-drag-sim-to-applications]
Install to `/Applications`. macOS App Translocation runs an app from a randomized read-only path when it is launched from Downloads, which silently breaks auto-updates.
### Sign in [#sign-in]
Launch Sim and sign in as you normally would.
Google, Microsoft, and SSO sign-ins finish in your default browser — those providers refuse to render inside an embedded browser. Sim opens the page, you approve, and the browser hands the session back to the app. The app gets its own session, so signing out of one surface does not sign out the other.
### Point it at your deployment, if you self-host [#point-it-at-your-deployment-if-you-self-host]
Fresh installs open sim.ai. To use your own deployment, choose **Sim → Server…** in the menu bar and enter its URL. See [Desktop App on Your Deployment](/platform/self-hosting/desktop) for what changes when you switch.
## What the desktop app adds [#what-the-desktop-app-adds]
* **A built-in browser.** A real browser inside the app, with its own tabs, saved passwords, and sessions. Chat can drive it — sign in once and your agents work on the sites you are already signed into.
* **A built-in terminal.** Real shell sessions in a panel next to Chat, with tmux and shell integration, that Chat can run commands in.
* **Local folder access.** When a task needs a folder on your Mac, Chat offers to open the native folder picker. The grant is read-only, scoped to the folder you picked, and revocable.
* **Notifications.** A native notification when a Chat task finishes. Clicking it opens that chat. Tasks that end in an error, or that have another message queued behind them, do not notify.
* **Control Center.** A menu-bar icon with your recent chats, so Sim is one click away from any app.
* **Launch at login.** Sim starts with your Mac, and however you launch it, it opens where you left off.
Both the browser and the terminal are capabilities you grant, not defaults you are stuck with — each has a single switch in settings that turns it off entirely.
**What a folder grant does and does not do.** Granting a folder does not copy or upload it, and an agent cannot attach or stage a file from it — that stays your deliberate act. But when an agent reads or searches inside the grant, what it reads is a tool result, and tool results go to your Sim server and to the model like anything else in the conversation. The file stays on your Mac; what an agent reads out of it does not.
## Keyboard shortcuts [#keyboard-shortcuts]
These are the app's own shortcuts. The [workflow editor and table shortcuts](/keyboard-shortcuts) work the same in the app as in the browser.
| Shortcut | Action |
| ----------------------- | --------------------------------- |
| `Cmd` + `K` | Search |
| `Cmd` + `B` | Toggle the sidebar |
| `Cmd` + `N` | New chat |
| `Cmd` + `Shift` + `N` | New window |
| `Cmd` + `,` | Settings |
| `Cmd` + `[` | Back |
| `Cmd` + `R` | Reload |
| `Cmd` + `0` / `+` / `-` | Reset, increase, or decrease zoom |
With the built-in browser or terminal focused, the tab shortcuts act on its tabs rather than on the window:
| Shortcut | Action |
| ----------------------------------------- | ------------------------------------ |
| `Cmd` + `T` | New tab |
| `Cmd` + `W` | Close tab |
| `Cmd` + `Shift` + `T` | Reopen the last closed tab |
| `Ctrl` + `Tab` / `Ctrl` + `Shift` + `Tab` | Next / previous tab |
| `Cmd` + `1`–`8` | Jump to that tab |
| `Cmd` + `9` | Jump to the last tab |
| `Cmd` + `L` | Focus the address bar (browser only) |
| `Cmd` + `F` | Find on the page (browser only) |
## Settings [#settings]
The desktop app adds three sections under **Settings → Account**. They appear only when you are running the app, and they apply to this Mac rather than to your account.
### Desktop [#desktop]
* **Launch Sim at login**
* **Show Sim in Control Center** — the menu-bar icon
* **Automatically download updates**
* **Enable desktop notifications**, with **Play notification sounds** and **Notify only when Sim isn't focused**
It also shows the installed version, and the version waiting to be applied when an update is ready.
### Browser [#browser]
* **Let Chat browse the web** — the master switch for the built-in browser
* **Search suggestions**, **Theme**, **Default zoom**, and **Download location**
* **Browsing data** — clear cookies, site data, and cached images and files
### Terminal [#terminal]
* **Let Chat run commands** — the master switch for the built-in terminal
* **Theme** and **Default zoom**
The menu bar carries the rest: **Sim → Settings…** (`Cmd` + `,`), **Server…** to change deployments, **Check for Updates…**, and **Sign Out**.
## Updates [#updates]
Sim checks the deployment it is pointed at rather than a global feed. How it applies what it finds depends on how the app was installed. Nothing is ever forced mid-session either way.
**Installed in `/Applications`, signed by Sim** — what the download link above gives you. The app replaces itself. With **Automatically download updates** on, it downloads in the background and offers to restart; choose **Later** and the update applies the next time you quit. With it off, nothing downloads until you ask: **Sim → Check for Updates…** reports the available version and waits for you to choose **Download**.
**Anywhere else** — outside `/Applications`, or a build not signed with a Developer ID. The app cannot replace itself, so it offers you the installer to download and swap in by hand.
Updates come from the deployment you are connected to, so a self-hosted install controls which build its own users are offered. That control depends on the feed staying reachable: if it is not, a self-updating stable build falls back to Sim's public GitHub releases rather than stalling. See [Desktop App on Your Deployment](/platform/self-hosting/desktop).
## Requirements [#requirements]
* **macOS 12 Monterey or later**, on Apple Silicon or Intel.
* **Outbound access to your Sim deployment**, and to `github.com`, which is where installers and updates are downloaded from.
* **If you self-host**, your Sim server needs its own outbound access to both `api.github.com`, which is what resolves *which* release to offer, and `github.com`. An allowlist carrying only `github.com` leaves the download endpoint answering `502`.
* **A system-trusted TLS certificate**, if you self-host. The app rejects certificate errors outright and offers no override, so a private CA must be installed in the macOS keychain.
The desktop app is macOS-only today. The web app works in any browser on any platform, and your account, workspaces, and workflows are the same either way.
---
# Editor (/files/editor)
Every markdown file in your workspace opens in a **rich editor**. Type markdown and it renders as you go, or format visually with the toolbar and slash menu. The file is saved as plain markdown.
## Formatting text [#formatting-text]
Select any text to bring up the formatting toolbar — bold, italic, strikethrough, inline code, and links. The same marks appear instantly as you type the markdown for them, like `**bold**` or `*italic*`. Links show a hover card so you can open, copy, edit, or remove them without hunting through the source.
## Structure [#structure]
Headings, blockquotes, and dividers keep long documents scannable. Type `# ` through `###### ` for headings, `> ` for a quote, and `---` for a divider.
## Lists and checklists [#lists-and-checklists]
Bullet, ordered, and nested lists all work, plus task lists you can tick right in the document.
## Tables [#tables]
Insert a table from the slash menu, then click any cell for the floating table toolbar — add or remove rows and columns, toggle the header row, or delete the table. Drag a column border to resize it.
## Code blocks [#code-blocks]
Fenced code blocks are syntax-highlighted, with a language picker in the corner. Pick `mermaid` to render a live diagram instead of code.
## Images [#images]
Paste or drag an image straight into the document, then drag a corner to resize it.
## Slash menu and shortcuts [#slash-menu-and-shortcuts]
Type `/` anywhere to insert any block — heading, list, table, code block, image, and more — without leaving the keyboard. Familiar shortcuts work too: **Cmd/Ctrl + B** for bold, **Cmd/Ctrl + I** for italic, and **Cmd/Ctrl + K** to add a link over selected text.
## Markdown fidelity [#markdown-fidelity]
The editor round-trips your markdown exactly — it saves what you wrote, with no reformatting churn.
A few constructs can't be represented visually without losing information on save — footnotes, raw HTML, and HTML comments. When a file contains one of these, it opens **read-only** so the original source is preserved untouched. Everything is still rendered faithfully; you just can't edit that file inline.
---
# Generating files (/files/generating)
A generated file is an artifact a workflow run creates: a report, a CSV, a rendered audio clip. It starts as a value a block produces and becomes a workspace file when a [File](/integrations/file) block writes it to the [Files](/files) store. Once saved, it has a name, a size, and a URL, and any later run can read it back.
{/* VISUAL: flow diagram: [Agent/Function block produces content] → [File block, Write] → [Files panel, file visible] */}
## What produces file content [#what-produces-file-content]
Most generated files start as the output of an earlier block. Two patterns are common.
A block returns **text content** you want to keep. An [Agent](/workflows/blocks/agent) writes an analysis or summary; a [Function](/workflows/blocks/function) builds a CSV or formats a report. That text is part of the block's output, read by reference as `` or ``. To make it a file, you pass that value into a File block set to Write.
A block returns a **file object** directly. ElevenLabs text-to-speech returns an `audioFile`; an image generator returns a generated image; the File block's own Read operation returns parsed files. These are already [UserFile](/files/passing-files) objects (an object with `id`, `name`, `url`, `size`, and `type`), so they appear in the output panel as files with no Write step. You can hand one to a downstream block, or write its content to the Files store to persist it.
A block's output is remembered under the block's name for the rest of the run, and a later block reads it by key, like `` or ``. Producing content and saving it are two separate steps: the producing block holds the value, the File block persists it.
## Saving content with the File block [#saving-content-with-the-file-block]
The [File](/integrations/file) block's **Write** operation creates a new workspace file. It takes two required fields: a `fileName` (like `report.md`) and the `content` string to store. It returns the saved file's details.
{/* VISUAL: File Write anatomy: inputs (fileName, content, contentType?) → outputs (id, name, size, url) */}
To save an Agent's analysis, connect Agent into a File block, set the operation to Write, and reference the Agent's output: `fileName` = `research_summary.md`, `content` = ``. When the workflow runs, the File block writes the file and produces:
* `id`: the canonical file ID, used to fetch the file later.
* `name`: the final file name after any deduplication (see below).
* `size`: the byte count.
* `url`: an absolute URL to download or preview the file.
The content type is detected from the file extension: `.csv` becomes `text/csv`, `.pdf` becomes `application/pdf`, `.md` becomes `text/markdown`. To set it yourself, fill in `contentType` in advanced mode.
If a file with the same name already exists in the workspace, Write does not overwrite it. It appends a numeric suffix instead: a second `data.csv` is saved as `data (1).csv`, a third as `data (2).csv`. To add to an existing file rather than create a new one, use the **Append** operation, which writes content to the end of a named file.
## Where the file goes [#where-the-file-goes]
A saved file lands in the workspace [Files](/files) store, the same place uploads live. It shows up in the Files panel in the sidebar with its name, size, type icon, and modified date, grouped by category: document, image, audio, video, or code. From there you can preview it, rename it, move it into a folder, or download it by URL.
{/* VISUAL: Files panel UI: generated files listed with name, size, type icon, owner, modified date, folder */}
Files are scoped to the workspace, not to one workflow. A file written by one workflow is visible to every other workflow in the same workspace. Any later run can read it back with the File block's Read or Get operation, or by selecting it in a file picker.
During a run, the file also appears in the output panel as the File block's output, shown as a structured object with its `id`, `name`, `url`, and `size`. The output panel shows you one run as it happens, while the Files store is where the file stays afterward.
{/* VISUAL: output panel tree: file object (id, name, url, size, type) during a run, beside the same file in the Files store */}
## Returning a generated file from a deployment [#returning-a-generated-file-from-a-deployment]
When a workflow is deployed as an [API](/workflows/deployment/api), a generated file can be part of the response. Reference the file in a [Response](/workflows/blocks/response) block, or include its ID in the object you return. The caller uses the `url` or `id` to fetch the file from the workspace store. The file itself stays in the Files store, and the response carries a pointer to it, not the bytes.
---
# Files (/files)
A **file** is a document, image, spreadsheet, or PDF in your workspace. Files are how documents and media move into and out of your agents. Your team uploads them, you create them in the editor, or a workflow produces them, and they all live in one store shared across the workspace.
Any [workflow](/workflows) can read a file or produce one. You might upload a contract for an agent to review, generate a report from a table, or hand a workflow the document it needs to answer a question.
## How files fit the workspace [#how-files-fit-the-workspace]
* **[Workflows](/workflows)** read files, like a PDF to summarize, and produce them, like a rendered report. See [using files in workflows](/files/using-in-workflows).
* **[Knowledge bases](/knowledgebase)** are built from files you upload, turning their contents into searchable memory.
* **[Deployments](/workflows/deployment)** can take a file as input and return one as output.
Use a file when the document or media itself is what matters. Use a [table](/tables) when you need structured rows and fields, and a [knowledge base](/knowledgebase) when an agent needs to search across many documents.
---
# Passing files (/files/passing-files)
A file moves through a workflow as a standardized **file object**. Blocks receive it, act on it, and pass it on — this page covers the object's shape, how to reference it between blocks, and how files enter and leave through the API.
## File Objects [#file-objects]
When blocks output files (like Gmail attachments, generated images, or parsed documents), they return a standardized file object:
```json
{
"id": "f_8c2...",
"name": "report.pdf",
"url": "https://...",
"size": 245678,
"type": "application/pdf",
"base64": "JVBERi0xLjQK..."
}
```
You can access any of these properties when referencing files from previous blocks.
## The File Block [#the-file-block]
The **File block** brings a file into a workflow. It accepts files from any source and outputs standardized file objects every block understands.
**Inputs:**
* **Uploaded files** - Drag and drop or select files directly
* **External URLs** - Any publicly accessible file URL
* **Files from other blocks** - Pass files from Gmail attachments, Slack downloads, etc.
**Outputs:**
* A list of `UserFile` objects with consistent structure (`id`, `name`, `url`, `size`, `type`, `base64`)
* `contents` - Extracted text per file (the Get Content operation)
* `combinedContent` - All fetched files' text merged into one string (the Fetch operation)
**Example usage:**
```
// Get all files from the File block
// Get the first file
// Get the first file's extracted text (Get Content operation)
```
The File block automatically:
* Detects file types from URLs and extensions
* Extracts text from PDFs, CSVs, and documents
* Generates base64 encoding for binary files
* Creates presigned URLs for secure access
Use the File block when you need to normalize files from different sources before passing them to other blocks like Vision, STT, or email integrations.
## Passing Files Between Blocks [#passing-files-between-blocks]
Reference files from previous blocks using the tag dropdown. Click in any file input field and type `<` to see available outputs.
**Common patterns:**
```
// Single file from a block
// Pass the whole file object
// Access specific properties
```
Most blocks accept the full file object and extract what they need automatically. You don't need to manually extract `base64` or `url` in most cases.
## Triggering Workflows with Files [#triggering-workflows-with-files]
When calling a workflow via API that expects file input, include files in your request:
```bash
curl -X POST "https://sim.ai/api/v2/workflows/YOUR_WORKFLOW_ID/execute" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"document": {
"name": "report.pdf",
"base64": "JVBERi0xLjQK...",
"type": "application/pdf"
}
}'
```
```bash
curl -X POST "https://sim.ai/api/v2/workflows/YOUR_WORKFLOW_ID/execute" \
-H "Content-Type: application/json" \
-H "x-api-key: YOUR_API_KEY" \
-d '{
"document": {
"name": "report.pdf",
"url": "https://example.com/report.pdf",
"type": "application/pdf"
}
}'
```
The workflow's Start block should have an input field configured to receive the file parameter.
## Receiving Files in API Responses [#receiving-files-in-api-responses]
When a workflow outputs files, they're included in the response:
```json
{
"success": true,
"output": {
"generatedFile": {
"name": "output.png",
"url": "https://...",
"base64": "iVBORw0KGgo...",
"type": "image/png",
"size": 34567
}
}
}
```
Use `url` for direct downloads or `base64` for inline processing.
## Blocks That Work with Files [#blocks-that-work-with-files]
**File inputs:**
* **File** - Parse documents, images, and text files
* **Agent** - Read images with a vision-capable model, or documents as text
* **Mistral Parser** - Extract text from PDFs
**File outputs:**
* **Gmail** - Email attachments
* **Slack** - Downloaded files
* **TTS** - Generated audio files
* **Video Generator** - Generated videos
* **Image Generator** - Generated images
**File storage:**
* **Supabase** - Upload/download from storage
* **S3** - AWS S3 operations
* **Google Drive** - Drive file operations
* **Dropbox** - Dropbox file operations
Files are automatically available to downstream blocks. The engine handles all file transfer and format conversion.
## Best Practices [#best-practices]
1. **Use file objects directly** - Pass the full file object rather than extracting individual properties. Blocks handle the conversion automatically.
2. **Check file types** - Ensure the file type matches what the receiving block expects. An Agent using a vision-capable model can read images, while the File block handles documents.
3. **Consider file size** - Large files increase run time. For very large files, consider using storage blocks (S3, Supabase) for intermediate storage.
---
# Using files in workflows (/files/using-in-workflows)
A file is a document, image, spreadsheet, or PDF in your workspace. A workflow can read a file to act on its contents, pass a file to a block or tool that needs one (attach a PDF to an email, send an image to a vision model), or produce a new file and save it. The [File](/integrations/file) block is how a file enters or leaves a workflow; the work in between is done by whatever block the task calls for.
What you do with a file depends on the task, so this page covers the File block's operations and how a file moves between blocks rather than one fixed recipe. The example we'll use throughout reads `report.pdf`, asks an agent to summarize it, and saves the summary as `summary.md`, which exercises reading, processing, and writing in one workflow.
## The File block [#the-file-block]
The **File** block is one block with five operations, chosen from a dropdown. Each operation is a different way a file, or its contents, enters or leaves the workflow.
| Operation | What it does | Outputs |
| --------------- | -------------------------------------------------------------- | --------------------------- |
| **Read** | Take an existing workspace file, by file picker or by file ID. | `files` |
| **Get Content** | Extract a workspace file's text, by file picker or by file ID. | `contents` |
| **Fetch** | Download and parse a file from an external URL. | `files`, `combinedContent` |
| **Write** | Create a new workspace file from a name and text content. | `id`, `name`, `size`, `url` |
| **Append** | Add text to the end of an existing workspace file. | `id`, `name`, `size`, `url` |
Read hands the next block the **file itself**; Get Content hands it the **text inside**. Fetch brings in both for an external URL. Write and Append put a file out. A workflow uses only the operations its task needs, often just Read. The two sections below cover Read and Write; the other operations are variants noted alongside.
{/* VISUAL: File block config UI. Operation dropdown open showing Read / Get Content / Fetch / Write / Append */}
## Reading a file in [#reading-a-file-in]
In our example, the first File block is set to **Read**, with `report.pdf` chosen from the file picker. When it runs, it produces `files`: a list of **file objects**, one per file read. The first is ``.
When the next step needs the file's *text* rather than the file itself, use **Get Content** instead: it extracts the text and outputs `contents`, an array with one string per file, read as ``.
A **file object** is the standard shape Sim uses for every file. It carries the file's details:
```jsonc
{
"id": "wf_V1StGXR8z5jdHi6B…", // workspace file ID
"name": "report.pdf",
"url": "https://…", // where to access it
"size": 248120, // bytes
"type": "application/pdf"
}
```
You rarely type a reference by hand. Wherever a block parameter accepts a file or a value, the builder lists the available outputs and you pick the one you want. Read mode also takes a file ID directly in advanced mode, which is how you read a file produced earlier in the same run.
**Fetch** brings in files that live outside the workspace. Point it at a URL, and add request headers (such as `Authorization: Bearer …`) when the download needs authentication. It outputs `files` like Read does, plus `combinedContent`: the fetched files' text merged into one string.
{/* VISUAL: File block in Read mode, file picker open with report.pdf selected; callout on the files[] output */}
## Processing the file [#processing-the-file]
Once a file is read, a processing block reads that output by name. Two blocks do this, and they consume the file differently.
### Agent block [#agent-block]
An [Agent](/workflows/blocks/agent) block has a **Files** input. Reference the read file there, ``, and write the instruction in the prompt: "Summarize this document." The agent receives the file object, not just its text, so a **vision-capable model** can analyze images and scanned pages directly. Other models work from the file's text content.
In our example the Agent reads ``, summarizes it, and keeps the summary under its own name as ``.
{/* VISUAL: Agent block config. Files input bound to , prompt "Summarize this document" */}
### Function block [#function-block]
A [Function](/workflows/blocks/function) block runs code, and it usually works with file **text**. Read the file with **Get Content** and pass the extracted text, ``, and the code can parse, filter, or reshape it and return the result as its own output. A Function can also take the file object itself and read it in code with the `sim.files` helpers, like `await sim.files.readText(file)` — see [the Function block](/workflows/blocks/function) for those. Use a Function when the file is structured text (a CSV or JSON dump) and you want exact, deterministic processing instead of a model's interpretation.
The two blocks differ in what they take. An **Agent** takes the file object on its Files input, while a **Function** typically takes the file's text from Get Content's `contents`. Both store their result under their own name for the next block to read.
## Writing a file out [#writing-a-file-out]
Writing a file is optional, and many workflows skip it. The agent's summary could be returned in the response, posted to Slack, or emailed as-is without ever becoming a workspace file. Write a file when you specifically need a new one to keep, download, or hand to a later run.
The last block in our example is a File block set to **Write**. Give it a file name and the content to save:
* `fileName`: `summary.md`
* `content`: ``
Write creates a new workspace file and returns its `id`, `name`, `size`, and `url`. If a file with that name already exists, Write keeps both by adding a numeric suffix to the new one. The saved file lands in your workspace [files](/files), ready for the next run, a download, or another workflow.
{/* VISUAL: run log showing the File Write step with the returned file id, name, and url */}
**Append** adds to a file instead of replacing it. Target an existing workspace file by name and give it the content to add to the end. Use it to accumulate across runs, such as appending each run's observation to one `notes.md`.
## Composing the steps [#composing-the-steps]
Each block references the previous one by name, so you compose only the steps a task needs. A contract read by an Agent that returns a verdict stops at processing, and an uploaded image described by a vision model never touches Write, while a fetched CSV cleaned by a Function and saved as a new file uses all three. Reading a file in is common, and writing one out is only for when the result is itself a file.
For the file-object schema in full, base64 access, and how files move across API and chat triggers, see [Passing files](/files/passing-files).
---
# Files & documents (/chat/files)
Describe a document, presentation, image, or visualization and Sim creates it — streaming the content live into the resource panel as it writes. Attach any file to your message and Sim reads it, processes it, and saves it to your workspace.
## Uploading Files to the Workspace [#uploading-files-to-the-workspace]
Attach any file directly to your message in Chat — drag it into the input, paste it, or click the attachment icon. Sim reads the file as context and saves it to your workspace.
Use this to:
* Hand Sim a document and ask it to process, summarize, or extract data from it
* Upload a CSV and have it create a table from it
* Drop in a PDF and ask Sim to turn it into a knowledge base document
* Attach a design mockup and ask Sim to describe it or generate code from it
Uploaded files appear in the Files panel in the sidebar and are accessible to all workflows in the workspace. Sim can also fetch a file directly from a URL and save it for you: "Download the JSON at \[URL] and save it to the workspace."
## Creating Documents [#creating-documents]
Sim can write any text-based file — markdown, plain text, code files, CSV, JSON, or any other format:
* "Write a technical spec for the new auth system as a markdown file"
* "Create a CSV of our test accounts with columns for name, email, and plan tier"
* "Write a Python script that calls our workflow API and processes the response"
* "Draft a postmortem for the outage last Tuesday and save it as a markdown file"
* "Write a personalized outbound email for Acme Corp based on their recent funding announcement"
* "Draft a weekly ops digest summarizing workflow run counts, errors, and top failures for the past 7 days"
Files are saved to your workspace and accessible from the Files panel in the sidebar.
## Editing Existing Files [#editing-existing-files]
Open a file using `@filename` or the **+** menu, then describe the change:
* "Update the pricing section to reflect the new tiers"
* "Refactor this Python script to use async/await"
* "Add a section on error handling to this spec"
* "Rewrite the introduction of this report to be more concise"
## Presentations [#presentations]
Sim can generate `.pptx` files:
* "Create a pitch deck for Q3 review — 8 slides covering growth, retention, and roadmap"
* "Turn this research report into a 10-slide presentation"
* "Build a deck that walks through our API onboarding flow"
* "Build a battle card deck for our top 3 competitors — one slide each covering positioning, pricing, and how we win"
* "Create an account plan for Acme Corp — their priorities, our solution fit, and proposed next steps"
The file is saved to your workspace and can be downloaded.
## Images [#images]
Sim can generate images using AI, and can use an existing image as a reference to guide the output:
**Generating images:**
* "Generate a banner image for the new feature announcement — dark background, clean typography"
* "Create a diagram showing the data flow through our webhook pipeline"
* "Make a social card for the blog post with the title and author name"
**Using a reference image:**
* Attach an existing image to your message, then describe what you want: "Generate a new version of this banner with a blue color scheme instead of green"
* "Create a variation of this diagram with the boxes rearranged horizontally \[attach image]"
Generated images are saved as workspace files.
## Charts and Visualizations [#charts-and-visualizations]
Sim can generate charts and data visualizations from data you describe or reference:
* "Plot the workflow run counts from the metrics table as a bar chart grouped by week"
* "Create a line chart of token usage over the past 30 days from this data \[paste data]"
* "Generate a pie chart showing the distribution of lead sources from the leads table"
Visualizations are saved as files and rendered in the resource panel.
## Calculations & Data Processing [#calculations--data-processing]
For one-off calculations and data transformations, describe what you need and Sim runs it directly in the chat:
* "Parse this JSON and extract all records where status is 'failed'"
* "Calculate the p95 latency from these timing values: \[paste values]"
* "Convert these Unix timestamps to ISO 8601"
* "Deduplicate this list of emails, case-insensitive"
Results come back directly in the chat. Ask Sim to save the output as a file if you need it.
## File Viewer Modes [#file-viewer-modes]
When a file opens in the resource panel, you can switch between three views:
| Mode | What it shows |
| ----------- | -------------------------------- |
| **Editor** | Raw editable text |
| **Preview** | Rendered output (markdown, HTML) |
| **Split** | Editor and preview side by side |
---
# Chat (/chat)
Use Chat to build workflows, research a topic, generate files, query tables, schedule jobs, and act through connected integrations. Reference the workspace resources you want Sim to use.
## What You Can Do [#what-you-can-do]
| Area | What Sim can do |
| --------------------------------------------- | -------------------------------------------------------------------------- |
| **[Workflows](/chat/workflows)** | Build, edit, run, debug, deploy, and organize workflows |
| **[Research](/chat/research)** | Search the web, read pages, crawl sites, produce research reports |
| **[Files & Documents](/chat/files)** | Upload, create, edit, and generate documents, presentations, and images |
| **[Tables](/chat/tables)** | Create, query, update, and export workspace tables |
| **[Automation & Configuration](/chat/tasks)** | Schedule jobs, take immediate actions, connect integrations, manage tools |
| **[Knowledge Bases](/chat/knowledge)** | Create knowledge bases, add documents, and query content in plain language |
## How It Works [#how-it-works]
Sim can find workspace resources by name and inspect the details it needs. Reference a resource explicitly when you want to direct its attention:
* "Run the invoice workflow"
* "Add a row to the leads table"
* "Deploy the summarizer as a chat"
No configuration, no context-setting. Just describe what you want:
* "Build a lead enrichment workflow that scores inbound signups and writes the results to the leads table"
* "Research our top 5 competitors and save a battle card for each one"
* "Schedule a daily job that checks for new high-fit prospects and posts them to #outbound in Slack"
* "Create a workflow that takes a contract PDF, extracts the key terms, and emails a summary to legal"
For complex tasks, Sim delegates to specialized subagents automatically. You'll see them appear as collapsible sections in the chat while they work — building, researching, writing files, executing actions.
{/* TODO: Screenshot of Chat showing a subagent section expanded mid-task — e.g., the Build or Research subagent actively working, with its collapsible header and steps visible in the thread. */}
## Adding Context [#adding-context]
Bring any workspace object into the conversation via the **+** menu, `@`-mentions, or drag-and-drop from the sidebar. Sim also opens resources automatically when it creates or modifies them.
{/* TODO: Screenshot of the resource panel with multiple tabs open — a workflow tab, a table tab, and a file tab — showing different resource types side by side. */}
| What to add | How it appears |
| ------------------ | ------------------------------------------------- |
| **Workflow** | Interactive canvas in the resource panel |
| **Table** | Full table editor in the resource panel |
| **File** | File viewer with editor, split, and preview modes |
| **Knowledge Base** | Knowledge base management UI |
| **Folder** | Folder contents |
| **Past task** | A previous Chat conversation |
## Layout [#layout]
Chat has two panes. On the left: the chat thread, where your messages and Sim's responses appear. On the right: the resource panel, where workflows, tables, files, and knowledge bases open as tabs. The panel is resizable; tabs are draggable and closeable.
---
# Knowledge bases (/chat/knowledge)
Create a knowledge base, add documents to it, and query it in plain language — all through conversation. Knowledge bases you create in Chat are immediately available to Agent blocks in any workflow.
## Creating Knowledge Bases [#creating-knowledge-bases]
Describe the knowledge base and Sim creates it:
* "Create a knowledge base called 'Product Docs'"
* "Set up a knowledge base for our support team — call it 'Support KB'"
* "Create a competitive intelligence knowledge base"
* "Create a knowledge base from our sales playbook and attach it to the outbound agent workflow"
* "Set up a customer success knowledge base — I'll add our onboarding guides and past case studies to it"
## Adding Documents [#adding-documents]
Add documents by attaching files to your message, pasting text, or pointing Sim at a URL:
* "Add this PDF to the Product Docs knowledge base \[attach file]"
* "Add the following text to the Support KB as a new document: \[paste content]"
* "Fetch the page at \[URL] and add it to the competitive intelligence knowledge base"
* "Add these three uploaded case studies to the customer success knowledge base"
Sim processes and indexes each document automatically. Once indexed, the content is searchable by any Agent block that has the knowledge base attached.
{/* TODO: Screenshot of Sim confirming a document was added and indexed — showing the document name and its indexed status in the knowledge base. */}
## Querying Knowledge Bases [#querying-knowledge-bases]
Ask Sim a question and it searches the specified knowledge base to answer:
* "What does the Product Docs knowledge base say about our refund policy?"
* "Search the Support KB for anything related to SSO setup errors"
* "What are the key differences between our Pro and Enterprise plans, based on the product docs?"
* "Find everything in the competitive intelligence knowledge base about \[competitor]'s pricing"
## Connectors [#connectors]
For knowledge bases that should stay current automatically, connectors sync content from external services on a schedule — no manual uploads needed. New content is added, changed content is re-processed, and deleted content is removed on every run.
Connectors are configured through the knowledge base settings, not through Chat. Once connected, all synced content is immediately searchable by Sim and by any Agent block with the knowledge base attached.
Use a [connector](/knowledgebase/connectors) to sync sources such as Notion, Google Drive, Slack, GitHub, or Confluence.
Examples of what you can sync:
* **Notion** — sync a workspace, a database, or a specific page tree
* **Google Drive / Dropbox / OneDrive** — sync documents from cloud storage
* **GitHub** — sync a repository's markdown and code files
* **Slack** — sync channel history
* **Confluence / Jira** — sync your internal wiki or issue tracker
* **HubSpot / Salesforce** — sync CRM records into a searchable knowledge base
See [Connectors](/knowledgebase/connectors) for setup steps, sync frequency options, and managing connector status.
## Managing Knowledge Bases [#managing-knowledge-bases]
List, inspect, and clean up knowledge bases in plain language:
* "What knowledge bases are in this workspace?"
* "How many documents are in the Support KB?"
* "Remove the outdated pricing doc from the Product Docs knowledge base"
* "Delete the old-competitive-intel knowledge base"
## Using Knowledge Bases in Workflows [#using-knowledge-bases-in-workflows]
Knowledge bases created in Chat are immediately available to Agent blocks in any workflow. Attach a knowledge base to an Agent block and it will use semantic search to retrieve relevant content at runtime.
See [Knowledge Base](/knowledgebase) for full details on document processing settings, search configuration, and connector syncing.
---
# Sim Mailer (/chat/mailer)
Sim Mailer gives your workspace a dedicated email address. Forward or send emails to it and Sim will process them as tasks — reading the subject, body, and any attachments, then replying to the thread with the result.
## Getting Started [#getting-started]
1. Navigate to **Settings** → **Inbox**
2. Toggle the inbox on
3. Optionally choose a custom address prefix (e.g., `acme` → `acme@mothership.sim.ai`)
4. Copy your inbox address and start sending emails
If you skip the custom prefix, one is generated automatically.
Changing your address creates a new inbox. The old address stops working immediately.
## What You Can Send [#what-you-can-send]
Write your email like you would to a colleague. The subject and body become the task prompt.
**Attachments are fully supported.** Images, PDFs, and documents (up to 10 MB each) are read by Sim and displayed inline in the conversation; images show as previews.
| Good email | Why it works |
| -------------------------------------------------- | --------------------------------- |
| "Summarize the attached PDF and list action items" | Clear task with an attachment |
| "What's in this image?" with a photo attached | Sim reads and describes the image |
| "Draft a reply to this forwarded thread" | Uses the email body as context |
## Allowed Senders [#allowed-senders]
Only authorized senders can create tasks. Emails from anyone else are automatically rejected.
* **Workspace members** are allowed by default — no setup needed
* **External senders** can be added manually with an optional label for easy identification
External senders are email addresses that can create inbox tasks. They are not the same as external workspace members, who have workspace access in Sim without joining your organization.
Manage your allowed senders list in **Settings** → **Inbox** → **Allowed Senders**.
## Tracking Tasks [#tracking-tasks]
Every email becomes a task you can track in **Settings** → **Inbox**:
* **Search** by subject, sender, or body content
* **Filter** by status to find what you need
* **Click** any completed or failed task to jump to the full conversation
### Task Statuses [#task-statuses]
| Status | Meaning |
| -------------- | ---------------------------------------------------------------------------- |
| **Received** | Email accepted, queued for processing |
| **Processing** | Sim is actively working on it |
| **Completed** | Done — the result was sent as an email reply |
| **Failed** | Something went wrong during execution |
| **Rejected** | Email blocked (sender not allowed, automated sender, or rate limit exceeded) |
## Conversations [#conversations]
Each email task creates a conversation in your workspace. You can continue the conversation in Chat, and any follow-up emails in the same thread are linked to the same conversation.
---
# Research (/chat/research)
Ask Sim to research anything and it figures out the best approach — searching the web, reading specific pages, crawling sites, looking up technical docs. Just describe what you want to know.
## Asking Questions [#asking-questions]
Ask anything — about a company, a competitor, a market, a technical question, or a specific URL:
* "What did Salesforce, HubSpot, and Gong each ship in the past 30 days? Summarize the key product updates."
* "What's Acme Corp's tech stack, recent hires, and open engineering roles?"
* "Find everything published about \[competitor] in the past 90 days — press, product changes, job postings."
* "What are the current rate limits on the Anthropic API?"
* "Read \[URL] and tell me what changed in this release"
* "What does Stripe's API say about handling webhooks with idempotency keys?"
* "Who are the main players in AI-powered revenue operations, and how do they differentiate?"
Sim returns an answer directly in the chat. For anything that needs a longer written output, ask it to save the result as a file.
## Research Reports [#research-reports]
When you need a structured, saved document rather than a chat answer, ask Sim to write it up. Sim searches, reads, and cross-references multiple sources until it has enough to produce a full report. The output is saved as a file in your workspace and opened in the resource panel.
{/* TODO: Screenshot of a completed research report open in the resource panel as a file — showing a structured markdown document with sections, findings, and citations. */}
* "Research the top 10 AI SDR tools — pricing, features, positioning, and what customers say. Save as a competitive analysis."
* "Do a full market landscape for AI in healthcare diagnostics — major players, funding, use cases, and regulatory environment."
* "Research how our top 5 competitors handle multi-tenant auth — pricing, architecture, and any known vulnerabilities. Write it up as a report."
* "Find every public case study on AI agents in financial compliance from the past 2 years. Summarize the key outcomes and save as a markdown file."
* "Build a battle card for \[competitor] — their positioning, pricing, strengths, weaknesses, and how we win against them."
---
# Tables (/chat/tables)
Create a table from a description or a CSV, query it in plain language, add or update rows, and export the results — all through conversation. Tables open in the resource panel as soon as they're created or referenced.
## Creating Tables [#creating-tables]
Describe the schema and Sim creates the table:
* "Create a leads table with columns for name, email, company, status, and created date"
* "Create a table that matches the structure of this CSV \[attach file]"
* "Set up an errors table with: id (text), message (text), workflow (text), timestamp (date), resolved (boolean)"
* "Create a prospect table for outbound — company, domain, employee count, industry, ICP score, and last contacted date"
* "Set up an enrichment results table to store output from the lead enrichment workflow: email, company, title, LinkedIn URL, fit score"
## Querying Data [#querying-data]
Ask questions about table contents in plain language:
* "How many rows in the leads table have status 'qualified'?"
* "Show me all records from the past 7 days where score is above 0.8"
* "What are the top 5 most common error messages in the failures table?"
* "Are there any duplicate emails in the contacts table?"
* "How many prospects have an ICP score above 0.75 and haven't been contacted in the past 30 days?"
* "What's the conversion rate from 'contacted' to 'meeting booked' in the pipeline table this month?"
Sim translates the question into a structured query and returns the results.
## Adding and Updating Rows [#adding-and-updating-rows]
Add individual rows, bulk-update based on a condition, or delete records — all in plain language:
* "Add a row to the leads table: Acme Corp, [jane@acme.com](mailto:jane@acme.com), status pending"
* "Mark all rows in the queue table as processed where created\_at is before today"
* "Update the price column for all rows where tier is 'pro' to 49"
* "Delete all rows in the test\_events table"
## Exporting [#exporting]
Export a full table or a filtered subset as a CSV. The file is saved to your workspace and can be downloaded or referenced in other workflows:
* "Export the leads table to a CSV"
* "Export all rows where status is 'closed' and save as a file"
## Using Tables in Workflows [#using-tables-in-workflows]
Tables created in Chat are immediately available in workflows via the [Table tool](/integrations/table). Reference a table by name — no additional configuration needed.
---
# Automation & configuration (/chat/tasks)
Sim can act on your behalf right now — send a message, create an issue, call an API — or on a schedule, running a prompt automatically every hour, day, or week. It can also connect integrations, set environment variables, add MCP servers, and create custom tools.
## Scheduled Jobs [#scheduled-jobs]
A scheduled job is a saved Chat prompt that runs on a cron schedule. On each run, Sim reads the current workspace state and executes the job's prompt as if you had just sent it.
### Creating a Job [#creating-a-job]
Describe the recurring task and how often it should run:
* "Every morning at 8am, check the leads table for new entries and post a summary to #sales in Slack"
* "Every Monday at 9am, pull last week's workflow run counts and write a report to the workspace"
* "Run the data sync workflow every 6 hours"
* "On the first of every month, export the billing table to CSV and email it to [finance@example.com](mailto:finance@example.com)"
* "Every weekday at 7am, check for new funding announcements from companies in our ICP and post the top 5 to #market-intel in Slack"
* "Every Sunday night, run the lead enrichment workflow on all prospects added in the past week and update their scores in the table"
* "Daily at 6am, pull the previous day's workflow errors, summarize the top issues, and post to #eng-alerts"
Sim sets the cron expression and stores the job prompt. The first run happens at the next scheduled time.
### Viewing Job Logs [#viewing-job-logs]
* "Show me the last 5 runs of the weekly report job"
* "Did the sync job run successfully this morning?"
* "What did the Monday digest job do last week?"
Logs show run time, status (completed, failed), and a summary of what the agent did.
### Managing Jobs [#managing-jobs]
* "Pause the morning summary job"
* "Change the sync job to run every 3 hours instead of 6"
* "Delete the onboarding digest job"
* "What scheduled jobs are currently active?"
## Taking Direct Action [#taking-direct-action]
For requests that should happen right now — without building a workflow — just ask. Sim acts immediately using the credentials connected to your workspace.
{/* TODO: Screenshot of Chat showing the "Taking action" subagent label active during a direct action — e.g., posting to Slack or sending an email. Shows the subagent inline in the chat thread. */}
| Request | What happens |
| -------------------------------------------------------------------------- | ------------------------------------ |
| "Send a Slack message to #eng that the deploy finished" | Posts to Slack immediately |
| "Email the Q3 report to [jane@example.com](mailto:jane@example.com)" | Sends via connected Gmail or Outlook |
| "Create a GitHub issue: auth tokens not rotating on logout" | Opens an issue in the specified repo |
| "Add a contact to HubSpot: Acme Corp, [ceo@acme.com](mailto:ceo@acme.com)" | Creates the contact via HubSpot API |
| "Call the webhook at \[URL] with this JSON payload" | Makes the HTTP request |
If an integration isn't connected, Sim walks you through connecting it.
## Connecting Integrations [#connecting-integrations]
Sim can connect new OAuth integrations and API credentials on demand:
* "Connect my Google account"
* "Add the Slack workspace for our team"
* "Set up GitHub with my personal access token"
{/* TODO: Screenshot of Sim walking through connecting an integration — e.g., the Integration subagent active with an OAuth prompt or confirmation that a credential was connected. */}
Once connected, Sim can use the account for authorized actions. Configure a workflow to use the intended available credential.
Select the intended account when configuring each integration. Which credentials are available depends on their ownership, sharing settings, and workspace policy. See [credentials](/platform/credentials).
See [Credentials](/platform/credentials) for managing connected accounts.
## Environment Variables [#environment-variables]
Save API keys, connection strings, and configuration under **Secrets**, then reference them with `{{ENV_VAR}}`. Choose personal or workspace scope according to who should use the value. See [secrets](/workflows/variables#environment-variables).
* "Set the DATABASE\_URL environment variable to 'postgres\://...'"
* "Add an OPENAI\_API\_KEY environment variable"
* "Add a WEBHOOK\_SECRET variable for the inbound webhook workflow"
* "Update the SCORING\_API\_URL variable to point to the new endpoint"
* "What environment variables are currently set?"
{/* TODO: Screenshot of Sim confirming an environment variable was set — e.g., a response message showing the variable name was saved. */}
## MCP Servers [#mcp-servers]
MCP (Model Context Protocol) servers expose tools from external services that Agent blocks can call inside workflows. Connecting an MCP server makes all of its tools available in the workflow editor's tool picker — no custom integration code required.
Sim can add and manage MCP servers connected to your workspace:
* "Add the Stripe MCP server using my API key"
* "Remove the old analytics MCP server"
* "What MCP servers are connected to this workspace?"
* "Update the endpoint for the internal tools MCP server to \[URL]"
Once added, MCP tools appear in the workflow editor's tool picker and can be called from any Agent block.
{/* TODO: Screenshot of Sim confirming an MCP server was added or updated — showing the server name and its status. */}
## Custom Tools [#custom-tools]
[Custom tools](/agents/custom-tools) combine a JSON parameter schema with a JavaScript function body. Use one for an internal API call, calculation, or reusable transformation, then add it to an Agent block's tools.
Sim can build custom tools from a description:
* "Create a custom tool that calls our internal scoring API at \[URL] with a POST request and returns the score field"
* "Build a tool for our Zendesk instance that creates a ticket with a subject and body"
* "Create a tool that hits our internal enrichment API with a domain and returns company size, industry, and funding stage"
* "Add a tool that calls our CRM's REST API to look up a contact by email and return their account owner"
{/* TODO: Screenshot of Chat with the Custom Tool subagent active — showing it building a tool definition. */}
---
# Workflows (/chat/workflows)
Describe a workflow and Sim builds it. Reference an existing one by name and Sim edits it. No canvas navigation required — every change appears in the resource panel in real time.
## Creating Workflows [#creating-workflows]
Describe what the workflow should do — what triggers it, what it should do, which integrations it needs, and what it should return. Sim builds it and opens the canvas in the resource panel.
* "Build a workflow that takes a URL, scrapes the page, summarizes it with Claude, and sends the summary to a Slack channel"
* "Create a workflow triggered by a webhook that extracts invoice data from a PDF and writes it to the billing table"
* "Build an outbound workflow: take a company name and domain, enrich it with firmographic data, score the fit, and draft a personalized cold email"
* "Create a lead enrichment workflow that takes an email from a form submission, looks up the company, and writes the enriched record to the leads table"
* "Build a customer onboarding workflow: when a new user signs up, send a welcome email, create a HubSpot contact, and post a notification to #new-customers in Slack"
## Editing Workflows [#editing-workflows]
{/* TODO: Screenshot of Chat with the Edit subagent active and a change applied to an open workflow — e.g., a new block added or a configuration updated, visible on the canvas in the resource panel. */}
Open an existing workflow with `@workflow-name` or the **+** menu, then describe the change. Sim reads the current structure before modifying it — you don't need to explain what already exists.
* "Add a condition that routes to a different branch if the confidence score is below 0.7"
* "Replace the GPT-4o model with Claude Opus 4.6 on the summarizer block"
* "Add a Slack notification at the end that includes the output"
## Running Workflows [#running-workflows]
Ask Sim to run a workflow and it handles the execution:
* "Run the data sync workflow"
* "Run the invoice processor with this PDF \[attach file]"
* "Test the lead scoring workflow with these inputs: name=Acme, score=0.4"
Execution streams back to the chat. The workflow in the resource panel shows live block-by-block state.
## Reading Logs [#reading-logs]
Sim can retrieve and interpret execution logs for any workflow in the workspace:
* "Show me the last 10 runs of the pipeline workflow"
* "Why did the invoice workflow fail yesterday?"
* "What did the extractor block return in the most recent run?"
Logs include per-block execution state, outputs, errors, and timing.
## Debugging [#debugging]
When a workflow fails, tell Sim to debug it:
* "Debug the last failed run of the content pipeline"
* "The summarizer block is returning empty output — figure out why"
Sim reads the failure logs, identifies the cause, applies a fix, and can re-run to confirm.
{/* TODO: Screenshot of the Debug subagent section in Chat showing it reading logs and applying a fix. */}
## Deploying [#deploying]
Sim can deploy a workflow as any of the three deployment types:
| Deployment type | What it creates |
| --------------- | ----------------------------------------------------------------- |
| **API** | A REST endpoint at `https://sim.ai/api/v2/workflows/{id}/execute` |
| **Chat** | A hosted conversational interface with a shareable URL |
| **MCP tool** | An MCP server that exposes the workflow as a tool |
Ask: "Deploy the invoice workflow as an API and generate an API key."
Sim can also roll back: "Revert the billing workflow to the version from last Tuesday."
See [API Deployment](/workflows/deployment/api) and [Chat Deployment](/workflows/deployment/chat) for full details on each deployment type.
## Organizing Workflows [#organizing-workflows]
Sim can create and manage folders to keep your workspace organized.
**Folders:**
* "Create a folder called 'Data Pipelines'"
* "Move the invoice workflow into the billing folder"
* "Move the billing folder inside the finance folder"
* "Delete the old-experiments folder"
**Renaming and moving:**
* "Rename the 'test\_v2' workflow to 'lead-scorer'"
* "Move the summarizer workflow to the research folder"
{/* TODO: Screenshot showing Sim confirming a folder or workflow organization action — e.g., a message confirming "Moved 'invoice-processor' into 'billing' folder" with the resource panel showing the folder open. */}
## Workflow Variables [#workflow-variables]
Sim can set global variables on a workflow — values accessible across all blocks in that workflow at runtime:
* "Set the API\_ENDPOINT variable on the sync workflow to '[https://api.example.com/v2](https://api.example.com/v2)'"
* "Update the MAX\_RETRIES variable on the pipeline workflow to 5"
Variables set this way are available via `` syntax inside any block in the workflow.
## Deleting Workflows [#deleting-workflows]
* "Delete the old\_api\_prototype workflow"
* "Delete all workflows in the deprecated folder"
---
# Audit Logs (/cli/audit-logs)
`sim audit-logs` is also spelled `sim audit-log`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Get audit log [#get-audit-log]
```bash
sim audit-logs get [options]
```
Get Audit Log (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | --------------------------- |
| `auditLogId` | Yes | Audit-log entry identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--organization ` | No | Organization ID; defaults to your only organization, and is required when your account belongs to more than one (OAuth login or personal API key required). |
## List audit logs [#list-audit-logs]
```bash
sim audit-logs list [options]
```
List Audit Logs (OAuth login or personal API key required)
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--action ` | No | Filter by exact action name. |
| `--resource-type ` | No | Filter by resource type. Accepts a comma-separated set; members are trimmed and deduplicated, and member order affects neither the result nor the cursor. |
| `--resource-id ` | No | Filter by exact resource identifier. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--include-departed` | No | Include actions by users who have left the organization. |
| `--no-include-departed` | No | Send --include-departed as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--organization ` | No | Organization ID; defaults to your only organization, and is required when your account belongs to more than one (OAuth login or personal API key required). |
| `--actor-email ` | No | Filter by actor email address. |
| `--all-workspaces` | No | Do not filter to the configured workspace (OAuth login or personal API key required for account-wide access). |
---
# Authentication (/cli/authentication)
`sim login` signs you in through your browser. It prefers OAuth, which stores a
short-lived login that renews itself, and selects API-key pairing for remote
terminals or servers without OAuth support. In CI you supply an existing API
key through the environment instead.
## Signing in [#signing-in]
```bash
sim login
```
Choose a method explicitly when the credential type matters:
```bash
sim login --method oauth
sim login --method api-key
```
`--method oauth` requires a server with OAuth support and authentication enabled;
it never falls back to an API key. Explicit OAuth selection also overrides
SSH/headless detection; your browser still needs to reach the CLI's
local callback. `--method api-key` uses pairing-code approval to create a new
permanent API key. To supply an existing key, set `SIM_API_KEY` instead.
API-key pairing requires a server that supports `platform` API keys. Upgrade
older deployments that only issue `copilot` keys before starting login; those
keys cannot authenticate the platform CLI.
OAuth login opens your browser on Sim's sign-in page, then on a consent page that
names the Sim CLI and what it will be able to do. Approve, and the browser hands
control back to the terminal:
```
Signing in to https://www.sim.ai as profile default
https://www.sim.ai/api/auth/oauth2/authorize?client_id=sim-cli&…
Waiting for you to approve in the browser…
✓ Logged in. Login stored in /Users/you/.sim/credentials
Renews itself; revoke it any time in Settings → General → Authorized apps, or with: sim logout
No default workspace. Set one with: sim configure --set-workspace
```
This is the OAuth 2.0 authorization-code flow with PKCE and a loopback redirect,
aligned with current OAuth security guidance. The browser only ever carries a one-time code;
the tokens are exchanged over the terminal's own connection and written to
`~/.sim/credentials` with `0600` permissions. Access tokens last an hour and are
renewed automatically from a refresh token. The complete login has a fixed
30-day lifetime; after it expires, run `sim logout`, then sign in again.
Only approve a consent page you reached by running `sim login` yourself. A
consent page that appears unprompted, or one you were sent a link to, is not
your login.
| Option | What it does |
| ------------------------ | ---------------------------------------------------------------------------------------------------------- |
| `--method ` | `oauth` requires OAuth login; `api-key` creates a permanent key through pairing. Auto-selects when omitted |
| `--no-browser` | Print the approval URL without opening it; works with either method |
| `--read-only` | Ask only for permission to read, never to change anything |
| `--callback-port ` | Pin the loopback callback port, primarily for an SSH session that forwards the same fixed port |
| `-y, --yes` | Overwrite an existing API-key profile without prompting |
### Over SSH or in a container [#over-ssh-or-in-a-container]
OAuth login needs your browser to reach a listener on the machine running
`sim`. When it cannot — an SSH session, a dev container, a remote box — use the
API-key pairing flow. The CLI selects it automatically in an SSH session when
no method or callback port is specified:
```bash
sim login --method api-key --no-browser
```
The terminal prints a pairing code and a URL you can open on any device:
```
Signing in to https://www.sim.ai as profile default
Pairing code: K7M2-P9XT
Confirm this code matches what the browser shows before approving.
https://www.sim.ai/cli/auth?request=…&scope=platform
Waiting for approval…
✓ Logged in. Key stored in /Users/you/.sim/credentials
Personal key, defaulting to 2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67. Override per command with --workspace.
```
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.
The handoff issues a permanent personal API key rather than a renewing login,
so revoke it under **Settings → API keys** when you are done with that machine.
It also works when OAuth is unavailable or switched off, provided the server
supports platform API-key pairing. When `--method` is omitted, the CLI checks
OAuth availability and selects pairing if unavailable; that discovery does not
verify pairing compatibility. An explicit `--method oauth` fails in that case.
`--read-only` and `--callback-port` belong to OAuth login and have no
meaning here, so combining either with the handoff stops the login rather than
storing a credential you did not ask for. If your SSH session forwards a port
from the remote loopback interface to the browser's machine, use
`--method oauth --callback-port ` with that port. An ordinary container port publication
cannot reach a listener bound to the container's own loopback interface; use
`--method api-key` there.
### Picking a workspace [#picking-a-workspace]
A normal login can act across every workspace you belong to; `--read-only`
limits it to read operations. The profile's `workspace` setting only decides the default target.
Set it after signing in, or pass `--workspace` per command:
```bash
sim workspaces list
sim configure --set-workspace 2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67
sim workflows list --workspace 9b4c7e02-1d58-4f36-a0c9-6e2b85df413a
```
With the pairing-code handoff you choose the default workspace on the approval
page instead.
To target another workspace without a second login, add a workspace profile:
```bash
sim profile add acme --workspace 7e2d9c14-6b83-4a55-8f01-c4d3e9a76b28
sim --profile acme whoami
```
The new profile stores `auth_profile = default` and its own workspace. Omit
`--workspace` in an interactive terminal to choose from the workspaces your
login can access; scripts must provide the workspace ID explicitly. The picker
is capped at 1,000 entries and asks for an explicit ID above that.
## Checking who you are [#checking-who-you-are]
```bash
sim whoami # resolved settings, plus a live check that they work
sim whoami --no-verify # resolved settings only, no request
```
Prints the resolved endpoint, workspace, and output format, which source each
value came from, and whether the profile holds an OAuth login or an API key,
then reads the configured workspace to prove the credential is accepted and can
reach it.
It exits `0` when the check passes, `1` when the credentials are wrong, and `2`
when the check could not be made at all — no workspace to check against, or an
endpoint that did not answer. The split matters in CI: only `1` is fixed by
logging in again.
## Signing out [#signing-out]
```bash
sim logout # sign out of Sim and remove the stored login
sim logout --all # remove the profile entirely, including its settings
```
For an OAuth login, `sim logout` revokes that login's complete token family
before removing it from disk, including access tokens issued before earlier
rotations. Other machines that ran their own `sim login` remain signed in. To
cut off every independent login for the client, revoke the grant under
**Settings → General → Authorized apps**.
A workspace profile that shares authentication cannot remove the shared login.
Remove only that local profile with `sim logout --all --profile `, or log
out of the authentication profile named by the error message. Removing an
authentication profile entirely is refused until its workspace profiles are
removed, so it cannot leave dangling references.
For a login created with `--method api-key`, `sim logout` removes the API key from
disk but does **not** revoke it. Revoke keys under **Settings → API keys**.
## Authenticating CI [#authenticating-ci]
Set an API key and workspace in the environment; no saved login is required,
and the environment key overrides any stored login:
```bash
export SIM_API_KEY="sim_…"
export SIM_WORKSPACE="2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67"
sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --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.
`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 [#github-actions]
```yaml title=".github/workflows/nightly.yml"
jobs:
digest:
runs-on: ubuntu-latest
steps:
- uses: actions/setup-node@v4
with:
node-version: '20'
- run: npm install -g sim
- run: sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --output json
env:
SIM_API_KEY: ${{ secrets.SIM_API_KEY }}
SIM_WORKSPACE: ${{ vars.SIM_WORKSPACE }}
```
## Several accounts and workspaces [#several-accounts-and-workspaces]
Use separate logins for separate identities or deployments:
```bash
sim login --profile dev --endpoint http://localhost:3000
sim login --profile prod
sim workflows list --profile dev
sim workflows list --profile prod
```
Use workspace profiles when one login should target several workspaces:
```bash
sim profile add marketing --workspace c3a70e58-9f21-4d6b-b842-05e7f19c6a3d
sim profile add support --workspace e0d94b17-3c62-45af-9718-b6a2c8035f4e
sim workflows list --profile marketing
sim workflows list --profile support
```
See [Configuration](/cli/configuration) for how profiles are stored and resolved.
## Self-hosted and non-production deployments [#self-hosted-and-non-production-deployments]
Point the CLI at any deployment with `--endpoint`, then sign in against it:
```bash
sim login --profile local --endpoint http://localhost:3000
```
Save it to avoid repeating the flag:
```bash
sim configure --set-endpoint http://localhost:3000 --profile local
```
OAuth sign-in is available by default when server authentication is enabled.
`DISABLE_AUTH=true` disables OAuth. Servers without OAuth use the pairing-code
handoff when they support platform API keys. See
[Sign in with Sim](/platform/self-hosting/authentication#sign-in-with-sim) for
server configuration and upgrade requirements.
## Where the login is stored [#where-the-login-is-stored]
Logins 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]
access_token = sim_oat_…
refresh_token = sim_ort_…
token_expires_at = 1788547200000
oauth_issuer = https://www.sim.ai/api/auth
oauth_login_id = …
oauth_scope = offline_access api:read api:write
[ci-box]
api_key = sim_…
```
A profile holds one login. A stored API key can be replaced after confirmation
or with `--yes`; a live OAuth login must be revoked with `sim logout` before
signing in again. Several `sim` commands running at once share one renewal, so
a parallel shell loop cannot sign itself out.
Run `sim login` separately on each machine. Copying `~/.sim/credentials` copies
one single-use refresh-token family; simultaneous use from both copies is
treated as token replay and revokes that login. If a refresh response is lost
because the process or connection stops, the CLI does not retry the consumed
token: run `sim logout`, then `sim login` again. This fail-closed behavior keeps
a copied token from surviving an ambiguous refresh.
## Organization audit logs [#organization-audit-logs]
`sim audit-logs` requires a **personal** credential — an OAuth login, or the
personal API key `sim login --method api-key` issues. A workspace-scoped key cannot
read organization-level audit logs.
---
# Billing (/cli/billing)
Every command below also accepts the [global options](/cli/commands#global-options).
## Show billing status and current-period credit usage [#show-billing-status-and-current-period-credit-usage]
```bash
sim billing status [options]
```
Show billing status and current-period credit usage (credits and storage require an OAuth login or personal API key)
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------- |
| `--all-workspaces` | No | Do not filter to the configured workspace (OAuth login or personal API key required for account-wide access). |
## List credit usage events [#list-credit-usage-events]
```bash
sim billing logs [options]
```
List credit usage events (an OAuth login or personal API key reports only your events; a workspace API key reports every member's in aggregate, unattributed)
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--source ` | No | Filter by usage source; sim-chat combines Copilot and workspace chat. Accepted values: `workflow`, `wand`, `sim-chat`, `mcp_copilot`, `mothership_block`, `knowledge-base`, `voice-input`, `enrichment`, `voice-output`, `api-tool`. |
| `--period ` | No | Billing period. Accepted values: `1d`, `7d`, `30d`, `all`, `custom`. |
| `--start-date ` | No | Custom period start (ISO 8601). |
| `--end-date ` | No | Custom period end (ISO 8601). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--all-workspaces` | No | Do not filter to the configured workspace (OAuth login or personal API key required for account-wide access). |
---
# Blocks (/cli/blocks)
Every command below also accepts the [global options](/cli/commands#global-options).
## Get block [#get-block]
```bash
sim blocks get
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| `blockId` | Yes | Block type identifier. An unversioned base type resolves to the newest version, and the response echoes the resolved id. |
## List blocks [#list-blocks]
```bash
sim blocks list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the block id, name, and description. |
| `--category ` | No | Restrict to one toolbar category. Accepted values: `blocks`, `tools`, `triggers`. |
| `--capability ` | No | Restrict to blocks that can start a workflow — the `triggers` category, blocks declaring `triggerAllowed`, and blocks with trigger-mode fields. Accepted values: `trigger`. |
| `--source ` | No | Restrict to built-in blocks or this workspace's deployed custom blocks. Accepted values: `builtin`, `custom`. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `id`, `name`, `category`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
---
# Chat Deployments (/cli/chat-deployments)
Every command below also accepts the [global options](/cli/commands#global-options).
## List chat deployments [#list-chat-deployments]
```bash
sim chat-deployments list [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | --------------------------------------------------------------------------------------- |
| `--workflow-id ` | No | Restrict to deployments of one workflow. |
| `--is-active` | No | Restrict to active or inactive deployments. |
| `--no-is-active` | No | Send --is-active as false. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `identifier`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
---
# CLI Commands (/cli/commands)
Every `sim` command follows the same shape:
```bash
sim [sub-resource] [arguments] [options]
```
Some resource groups also accept a singular alias: `sim workflow get` and
`sim workflows get` are the same command. `knowledge` also answers to `kb`.
Each group’s reference lists its supported aliases.
## Global options [#global-options]
These apply to every command, and may be written before or after it.
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------- |
| `-P, --profile ` | Profile to use (env: SIM\_PROFILE). |
| `--endpoint ` | Sim deployment to talk to (env: SIM\_ENDPOINT). |
| `-w, --workspace ` | Workspace to target (env: SIM\_WORKSPACE). |
| `--output ` | Output format for this command. Accepted values: `table`, `json`, `yaml`, `text`. |
## Command groups [#command-groups]
| Group | Description |
| ------------------------------------------------------- | ------------------------------------------------------------------- |
| [`sim profiles`](/cli/profiles) | List profiles or add a workspace profile that shares a stored login |
| [`sim audit-logs`](/cli/audit-logs) | Manage audit logs |
| [`sim billing`](/cli/billing) | Manage billing |
| [`sim blocks`](/cli/blocks) | Manage blocks |
| [`sim chat-deployments`](/cli/chat-deployments) | Manage chat deployments |
| [`sim connector-types`](/cli/connector-types) | Manage connector types |
| [`sim credentials`](/cli/credentials) | Manage credentials |
| [`sim custom-tools`](/cli/custom-tools) | Manage custom tools |
| [`sim files`](/cli/files) | Manage files |
| [`sim knowledge`](/cli/knowledge) | Manage knowledge |
| [`sim logs`](/cli/logs) | Manage logs |
| [`sim mcp-servers`](/cli/mcp-servers) | Manage mcp servers |
| [`sim meta`](/cli/meta) | Manage meta |
| [`sim sandboxes`](/cli/sandboxes) | Manage sandboxes |
| [`sim secrets`](/cli/secrets) | Manage secrets |
| [`sim skills`](/cli/skills) | Manage skills |
| [`sim tables`](/cli/tables) | Manage tables |
| [`sim tools`](/cli/tools) | Manage tools |
| [`sim workflow-mcp-servers`](/cli/workflow-mcp-servers) | Manage workflow mcp servers |
| [`sim workflows`](/cli/workflows) | Manage workflows |
| [`sim workspaces`](/cli/workspaces) | Manage workspaces |
## Sign in through the browser and store the login for the profile [#sign-in-through-the-browser-and-store-the-login-for-the-profile]
```bash
sim login [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--method ` | No | Credential to obtain: oauth requires OAuth support; api-key creates a permanent key through pairing (auto-selects when omitted). Accepted values: `oauth`, `api-key`. |
| `--no-browser` | No | Print the approval URL without opening it (either login method). |
| `--read-only` | No | Ask only for permission to read, never to change anything. |
| `--callback-port ` | No | Pin the local port the browser returns to. |
| `-y, --yes` | No | Overwrite an existing API-key profile without prompting. |
## Sign out and remove the profile's stored login [#sign-out-and-remove-the-profiles-stored-login]
```bash
sim logout [options]
```
**Options**
| Option | Required | Description |
| ------- | -------- | ---------------------------------------------------- |
| `--all` | No | Remove the profile entirely, including its settings. |
## Show the resolved profile, where each setting came from, and whether it works [#show-the-resolved-profile-where-each-setting-came-from-and-whether-it-works]
```bash
sim whoami [options]
```
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------------------------- |
| `--no-verify` | No | Skip the API check and only print the resolved settings. |
## Set a profile's endpoint, default workspace, or output format [#set-a-profiles-endpoint-default-workspace-or-output-format]
```bash
sim configure [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------ |
| `--set-endpoint ` | No | Sim deployment to talk to. |
| `--set-workspace ` | No | Default workspace for workspace-scoped commands. |
| `--set-output ` | No | Default output format (table \| json \| yaml \| text). |
| `--unset ` | No | Remove settings (endpoint, workspace, output). |
## Ask Sim and print the reply [#ask-sim-and-print-the-reply]
```bash
sim chat [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | --------------- |
| `message` | Yes | What to ask Sim |
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------- |
| `-c, --conversation ` | No | Continue the conversation with this ID. |
---
# Configuration (/cli/configuration)
The CLI resolves an **endpoint**, **credential**, **workspace**, and **output
format**. The credential can be a stored OAuth login or an API key. Each resolves independently, so a saved default can still be overridden
for a single command.
## Profiles [#profiles]
A profile selects one set of defaults, in the style of the AWS CLI. It normally
uses its same-named stored identity, but a workspace profile can share another
profile's identity through `auth_profile`. Select one with `-P`, `--profile`, or
`SIM_PROFILE`:
```bash
sim workflows list --profile dev
SIM_PROFILE=dev sim workflows list
```
The profile is named `default` when you do not pick one.
```bash
sim profiles # list them; * marks the active one
```
Add a profile for another workspace without creating or copying an API key:
```bash
sim profile add acme --workspace 7e2d9c14-6b83-4a55-8f01-c4d3e9a76b28
```
## Setting defaults [#setting-defaults]
```bash
sim configure --set-endpoint http://localhost:3000 --profile dev
sim configure --set-workspace 5c81f3a6-0e27-4b94-8d15-a7f60c39b2e8 --profile dev
sim configure --set-output json
```
| Option | What it sets |
| ----------------------- | --------------------------------------------------------- |
| `--set-endpoint ` | The Sim deployment to talk to |
| `--set-workspace ` | Default workspace for workspace-scoped commands |
| `--set-output ` | Default output format: `table`, `json`, `yaml`, or `text` |
| `--unset ` | Remove settings — `endpoint`, `workspace`, or `output` |
Run `sim configure` with no flags to print the profile's stored settings.
API keys are not settable here. Use [`sim login`](/cli/authentication), or
`SIM_API_KEY` for CI.
## Where settings come from [#where-settings-come-from]
Each setting resolves independently, and the first match wins:
| Rank | Source |
| ---- | -------------------------------------------------------------------------------------------------- |
| 1 | Command-line flag — `--endpoint`, `--workspace`, `--output` |
| 2 | Environment — `SIM_ENDPOINT`, `SIM_API_KEY`, `SIM_WORKSPACE`, `SIM_OUTPUT` |
| 3 | `~/.sim/config` for the selected profile and `~/.sim/credentials` for its `auth_profile`, when set |
| 4 | Built-in default — `https://www.sim.ai` and `table` |
`sim whoami` prints the winning source for each setting:
```bash
sim whoami
```
## The files [#the-files]
Non-secret settings live in `~/.sim/config`. It is safe to commit to a dotfiles
repo:
```ini title="~/.sim/config"
[default]
endpoint = https://www.sim.ai
workspace = 2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67
output = table
[profile dev]
endpoint = http://localhost:3000
workspace = 5c81f3a6-0e27-4b94-8d15-a7f60c39b2e8
[profile acme]
auth_profile = default
workspace = 7e2d9c14-6b83-4a55-8f01-c4d3e9a76b28
```
Keys live in `~/.sim/credentials`, written `0600`:
```ini title="~/.sim/credentials"
[default]
api_key = sim_…
[dev]
api_key = sim_…
```
Section naming follows the AWS convention: `[profile dev]` in config, `[dev]` in
credentials. The `default` profile is `[default]` in both.
`auth_profile` references one direct profile and shares its endpoint and stored
login, whether OAuth or an API key. Workspace and output remain local.
References cannot be chained, and a shared profile cannot also set its own
endpoint or stored login.
## Environment variables [#environment-variables]
| Variable | Effect |
| ---------------------- | -------------------------------------------------------------------------------------------------------------- |
| `SIM_PROFILE` | Profile to use |
| `SIM_ENDPOINT` | Deployment to talk to |
| `SIM_API_KEY` | API key — skips `sim login` entirely |
| `SIM_WORKSPACE` | Workspace to target |
| `SIM_OUTPUT` | Output format |
| `SIM_CONFIG_DIR` | Relocate the config directory and update cache; file-specific overrides below still win |
| `SIM_CONFIG_FILE` | Relocate only the config file |
| `SIM_CREDENTIALS_FILE` | Relocate only the credentials file |
| `SIM_TIMEOUT_SECONDS` | Per-request timeout; `0` waits indefinitely. Defaults to `3600`, above every timeout the server itself applies |
| `SIM_DEBUG` | Trace each request's method, URL, status and duration to stderr |
| `SIM_NO_UPDATE_CHECK` | Turn off update checks |
## Update notices [#update-notices]
The CLI checks for a newer release at most once per day on eligible interactive
invocations. Notices go to stderr and show an upgrade command for the package
manager that installed Sim.
Checks are skipped in CI, when stderr is redirected, under `npm exec` or `npx`,
from a repository checkout, and for prerelease versions. Set
`SIM_NO_UPDATE_CHECK=1` to disable them.
The check uses `registry.npmjs.org` unless `npm_config_registry` names another
HTTP(S) registry. It sends no Sim API key, workspace, or command. Query-string
credentials in a configured registry URL are preserved; URLs containing
username/password userinfo are rejected. Empty registry values use npm, while
malformed non-empty values disable the check. Redirects are not followed.
The daily cache is `~/.sim/update-check.json`, or under `SIM_CONFIG_DIR`.
`SIM_CONFIG_FILE` and `SIM_CREDENTIALS_FILE` do not relocate it. If the cache
cannot be written, eligible invocations may check again. Concurrent commands
can also each check. Requests have a one-second deadline.
Node's `fetch` uses `HTTP(S)_PROXY` when opted in with `NODE_USE_ENV_PROXY=1`
(Node 22.21+ or 24.0+) or `--use-env-proxy` (Node 22.21+ or 24.5+).
For CI, set `SIM_API_KEY` and `SIM_WORKSPACE`; no saved login or config file is
required.
## Choosing a workspace [#choosing-a-workspace]
Workspace-scoped commands need a workspace:
```bash
sim tables list --workspace 9b4c7e02-1d58-4f36-a0c9-6e2b85df413a
sim configure --set-workspace 2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67
export SIM_WORKSPACE=2f6d0b1c-8a34-4d92-b7e5-31c8a0f45d67
```
For a reusable selection, create a workspace profile backed by the current
stored login:
```bash
sim workspaces list
sim profile add acme --workspace 7e2d9c14-6b83-4a55-8f01-c4d3e9a76b28
sim --profile acme tables list
```
When `--workspace` is omitted in a terminal, `profile add` presents an
interactive picker, capped at 1,000 entries. It refuses environment-only keys
and endpoint overrides because those values would disappear in another shell.
`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 [#repairing-a-bad-setting]
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
```
---
# Connector Types (/cli/connector-types)
Every command below also accepts the [global options](/cli/commands#global-options).
## List connector types [#list-connector-types]
```bash
sim connector-types list [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------ |
| `--search ` | No | Case-insensitive substring match against the connector name. |
---
# Credentials (/cli/credentials)
`sim credentials` is also spelled `sim credential`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Disconnect credential [#disconnect-credential]
```bash
sim credentials delete [options]
```
Disconnect Credential (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------- |
| `credentialId` | Yes | Credential to disconnect. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## List credential providers [#list-credential-providers]
```bash
sim credentials providers list [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the credential provider name. |
## List credentials [#list-credentials]
```bash
sim credentials list [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `--type ` | No | Restrict results to this credential type. Accepted values: `oauth`, `service_account`. |
| `--provider-id ` | No | Restrict results to credentials for this integration provider. |
| `--search ` | No | Case-insensitive substring match against the credential display name. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `displayName`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## Update credential [#update-credential]
```bash
sim credentials update [options]
```
Update Credential (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | --------------------- |
| `credentialId` | Yes | Credential to update. |
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `--display-name ` | No | New name shown for the credential in Sim. |
| `--description ` | No | New credential description. Send null to clear the stored one. (--description null sends the word, not JSON null). |
| `--service-account-json ` | No | Write-only Google service-account JSON key. |
| `--api-token ` | No | Write-only provider API token. |
| `--domain ` | No | Provider account domain. |
| `--atlassian-product ` | No | Atlassian product to verify; defaults to Jira on create and preserves the saved product on reconnect. Accepted values: `jira`, `confluence`. |
| `--signing-secret ` | No | Write-only webhook signing secret. |
| `--bot-token ` | No | Write-only bot token. |
| `--client-id ` | No | OAuth client identifier. |
| `--client-secret ` | No | Write-only OAuth client secret. |
| `--certificate-id ` | No | Provider certificate mapping identifier. |
| `--org-id ` | No | Provider organization ID. |
| `--data-center ` | No | Provider data center. |
| `--auth-method ` | No | Provider authentication method. |
| `--private-key ` | No | Write-only PEM private key. |
| `--username ` | No | Provider run-as username. |
| `--name ` | No | Alias for --display-name. |
## Create a service-account credential using its discovered provider schema [#create-a-service-account-credential-using-its-discovered-provider-schema]
```bash
sim credentials create [options]
```
Create a service-account credential using its discovered provider schema (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | --------------------------------------------------- |
| `providerId` | Yes | Service-account provider to create a credential for |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | --------------------------------------------------------------------- |
| `--name ` | Yes | Name shown for the credential in Sim. |
| `--credentials ` | Yes | Provider credentials as JSON (or @path / @- to read a file or stdin). |
| `--description ` | No | Optional credential description. |
| `--id ` | No | Client-generated credential ID when provider discovery requires it. |
## Create a short-lived link for connecting an OAuth provider [#create-a-short-lived-link-for-connecting-an-oauth-provider]
```bash
sim credentials connect [options]
```
Create a short-lived link for connecting an OAuth provider (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | ------------------------- |
| `providerId` | Yes | OAuth provider to connect |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ----------------------------------------- |
| `--name ` | Yes | Name shown for the new credential in Sim. |
## Create a short-lived link for reconnecting an OAuth credential [#create-a-short-lived-link-for-reconnecting-an-oauth-credential]
```bash
sim credentials reconnect
```
Create a short-lived link for reconnecting an OAuth credential (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ----------------------------------------- |
| `credentialId` | Yes | Existing OAuth credential to re-authorize |
---
# Custom Tools (/cli/custom-tools)
`sim custom-tools` is also spelled `sim custom-tool`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Create custom tool [#create-custom-tool]
```bash
sim custom-tools create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | Yes | Display title, unique within the workspace. |
| `--schema ` | Yes | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | Yes | Tool implementation executed in the sandboxed function runtime. |
## Delete custom tool [#delete-custom-tool]
```bash
sim custom-tools delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------------ |
| `customToolId` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Get custom tool [#get-custom-tool]
```bash
sim custom-tools get
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------------ |
| `customToolId` | Yes | Unique custom tool identifier. |
## List custom tools [#list-custom-tools]
```bash
sim custom-tools list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the tool title. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `title`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## Update custom tool [#update-custom-tool]
```bash
sim custom-tools update [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------------ |
| `customToolId` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | No | New display title for the tool. |
| `--schema ` | No | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | No | Replacement tool implementation. |
---
# Files (/cli/files)
`sim files` is also spelled `sim file`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Delete several files at once [#delete-several-files-at-once]
```bash
sim files batch-delete [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `-y, --yes` | Yes | Confirm this operation. |
## Create file [#create-file]
```bash
sim files create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | File name, including its extension. Path separators and dot segments are rejected. |
| `--content-type ` | No | MIME type. When omitted, it is inferred from the file extension. |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
| `--content ` | No | Initial file content. Omit or send an empty string for a zero-byte file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. Use an upload session for anything larger. |
| `--encoding ` | No | Encoding of the content field. Accepted values: `utf-8`, `base64`. |
## Create a file folder at a path [#create-a-file-folder-at-a-path]
```bash
sim files folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
## Delete folder [#delete-folder]
```bash
sim files folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | Yes | Confirm this operation. |
## List folders [#list-folders]
```bash
sim files folders list [options]
```
Also available as `sim files folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--scope ` | No | Which lifecycle set to list: `active` (default) returns live folders only; `archived` returns folders a recursive delete soft-deleted, which is how a caller finds a path to hand to the folder restore. Authorization is identical for both. Accepted values: `active`, `archived`. |
| `--recursive ` | No | Whether parentPath includes every descendant instead of direct children only. Accepted values: `true`, `1`, `yes`, `on`, `y`, `enabled`, `false`, `0`, `no`, `off`, `n`, `disabled`. |
| `--depth ` | No | Deepest level below parentPath to include when recursive is true. |
## Rename or move a file folder [#rename-or-move-a-file-folder]
```bash
sim files folders move
```
Also available as `sim files folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
| `destination` | Yes | Folder path as shown in the app; the leading / is optional |
## Restore an archived file folder [#restore-an-archived-file-folder]
```bash
sim files folders restore
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
## Delete file [#delete-file]
```bash
sim files delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Apply one exact or anchor-based edit to a text file [#apply-one-exact-or-anchor-based-edit-to-a-text-file]
```bash
sim files edit [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--edit ` | Yes | One edit object: \{"mode":"search\_replace","search":"old","content":"new","replaceAll":false}, \{"mode":"replace\_between","beforeAnchor":"start line","afterAnchor":"end line","content":"new"}, \{"mode":"insert\_after","anchor":"line","content":"new"}, or \{"mode":"delete\_between","startAnchor":"first line deleted","endAnchor":"ending line kept"}. Anchored modes also accept occurrence starting at 1 (JSON, or @path / @- to read a file or stdin). |
## Show file metadata and sharing status [#show-file-metadata-and-sharing-status]
```bash
sim files describe [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--scope ` | No | Which lifecycle set to read from: `active` (default) resolves live files only and returns `404` for a file a delete soft-deleted; `archived` also resolves soft-deleted files, so metadata stays readable before the file is restored. Authorization is identical for both. Accepted values: `active`, `archived`. |
## Show a file’s share settings [#show-a-files-share-settings]
```bash
sim files share get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
## Enable or disable sharing for a file [#enable-or-disable-sharing-for-a-file]
```bash
sim files share set [options]
```
Enable or disable sharing for a file (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--is-active ` | Yes | Whether the share should resolve. Disabling preserves the token and the whole access configuration, so re-enabling restores the share as it was; enabling rewrites the credentials the resulting mode does not use. Accepted values: `true`, `false`. |
| `--auth-type ` | No | How access to the share is gated. The stored mode is kept when omitted. Enabling `public` clears the stored password and empties `allowedEmails`; `password` empties `allowedEmails`; `email` and `sso` clear the stored password. Accepted values: `public`, `password`, `email`, `sso`. |
| `--password ` | No | Password for a password-gated share. Kept when omitted; enabling `password` with neither a supplied nor a stored password is a 400. |
| `--allowed-emails ` | No | Allowed addresses or `@domain` patterns for email and SSO shares. Kept when omitted; enabling `email` or `sso` with an empty resulting list is a 400. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
## List files [#list-files]
```bash
sim files list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
| `--recursive` | No | Include subfolders in the folder filter. Defaults to true when searching and false otherwise. Ignored without a folder filter. |
| `--no-recursive` | No | Send --recursive as false. |
| `--scope ` | No | Which lifecycle set to list: `active` (default) for live files, `archived` for files a delete soft-deleted. `folderPath` resolves against active folders only, so pairing it with `scope=archived` returns an empty page when the containing folder was archived too. Accepted values: `active`, `archived`. |
| `--search ` | No | Case-insensitive substring match against the file name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `size`, `uploadedAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## Move files into another folder [#move-files-into-another-folder]
```bash
sim files move [options]
```
Also available as `sim files mv`.
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--to ` | No | Destination folder path; omit for root. |
## Read a file’s text content [#read-a-files-text-content]
```bash
sim files read [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| --------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `--max-bytes ` | No | Optional ceiling on the source bytes fed to the parser, lowering but never raising the server limit. |
| `--offset ` | No | First line to return, 1-based. Absent starts at the first line. |
| `--limit ` | No | How many lines to return from `offset`. Absent reads to the end. |
## Rename a file [#rename-a-file]
```bash
sim files rename [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ---------------- | -------- | --------------------------------------- |
| `--name ` | Yes | New file name, including its extension. |
## Restore an archived file [#restore-an-archived-file]
```bash
sim files restore
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
## Search file content [#search-file-content]
```bash
sim files search [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--query ` | Yes | Regular expression, or exact text when `mode` is `exact`. |
| `--mode ` | No | How `query` is read. Accepted values: `exact`, `regex`. |
| `--max-results ` | No | Maximum matching lines to return. |
| `--folder ` | No | Folders to search, by path as shown in the app; omit to search the whole workspace (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--include-subfolders` | No | Whether each folder scope includes nested folders; on by default. |
| `--no-include-subfolders` | No | Send --include-subfolders as false. |
## Unzip an archive into a new folder beside it [#unzip-an-archive-into-a-new-folder-beside-it]
```bash
sim files unzip [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Replace a file’s contents [#replace-a-files-contents]
```bash
sim files set-content [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--content ` | Yes | Complete replacement content for the file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. |
| `--encoding ` | No | Content encoding. Accepted values: `utf-8`, `base64`. |
## Upload a file to the workspace [#upload-a-file-to-the-workspace]
```bash
sim files upload [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------- |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ------------------------------------------------------------- |
| `--folder ` | No | Folder path as shown in the app; defaults to the root folder. |
| `--name ` | No | Store it under a different name. |
## Get a file’s content [#get-a-files-content]
```bash
sim files get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------- |
| `fileId` | Yes | File whose content to read |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | --------------------------------------------- |
| `-o, --output-file ` | No | Write content to a file instead of stdout. |
| `--force` | No | Overwrite --output-file if it already exists. |
## List file resources and child folders together [#list-file-resources-and-child-folders-together]
```bash
sim files ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `0`. |
## Create a file directory at a path [#create-a-file-directory-at-a-path]
```bash
sim files mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
---
# Sim CLI (/cli)
`sim` is the command line for Sim. Sign in once, then run workflows, query tables,
move files, search knowledge bases, and read run logs from the terminal. Use
`--output json` for structured results that pipe into `jq`, cron jobs, and CI
pipelines. See [Output formats](/cli/output) for commands that emit raw content
or local configuration.
## Install [#install]
```bash
npm install -g sim
```
```bash
pnpm add -g sim
```
```bash
bun add -g sim
```
Requires Node.js 20 or newer. Verify with `sim --version`.
To run it without installing, use `npx sim `.
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 [#your-first-command]
### Sign in [#sign-in]
```bash
sim login
```
The CLI opens your browser for approval. Local sign-in prefers OAuth; remote
terminals use API-key pairing. After OAuth sign-in, choose a default workspace
with `sim configure --set-workspace `. For SSH and containers, use
`sim login --method api-key --no-browser` and approve the pairing code.
See [Authentication](/cli/authentication) for CI keys, multiple accounts, and
self-hosted deployments.
### Check what you are pointed at [#check-what-you-are-pointed-at]
```bash
sim whoami
```
This prints the resolved endpoint, workspace, and output format — and **where
each one came from**. It is the fastest way to explain a surprising result.
### List your workflows [#list-your-workflows]
```bash
sim workflows list
```
```
ID NAME FOLDER DEPLOYED RUNS LAST RUN
3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 Refund triage /Support yes 412 2026-08-15 14:02:11
b8c0d247-9e13-4a86-97f5-2ad4e1638c09 Weekly digest /Reporting no 18 2026-08-11 09:00:04
```
### Run one [#run-one]
```bash
sim workflows run 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 --input '{"ticketId":"T-4821"}'
```
This command runs the active deployment. Deploy from the editor or with
`sim workflows deploy `. To run the current saved workflow state instead,
use `sim workflows run --manual`.
## How commands are shaped [#how-commands-are-shaped]
Every command reads the same way:
```bash
sim [sub-resource] [arguments] [options]
```
```bash
sim workflows list
sim tables rows query tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --limit 50
sim knowledge documents upload 4c1b7f60-2d55-4a3e-9c18-70b6ea2f9d31 ./handbook.pdf
```
Some resource groups also accept a singular alias: `sim workflow get` and
`sim workflows get` are the same command. `knowledge` also answers to `kb`.
Each group’s reference lists its supported aliases.
Every command accepts `--help`, at any depth:
```bash
sim --help
sim tables --help
sim tables rows query --help
```
## What you can do [#what-you-can-do]
| Group | What it covers |
| --------------------------------------------------- | ------------------------------------------------------------------ |
| [`workflows`](/cli/workflows) | Run, deploy, roll back, import, export, and organize workflows |
| [`logs`](/cli/logs) | Read run diagnostics, including the full trace tree |
| [`tables`](/cli/tables) | Query, insert, update, and import rows; manage columns and views |
| [`files`](/cli/files) | Upload, download, share, and organize workspace files |
| [`knowledge`](/cli/knowledge) | Search knowledge bases and manage their documents and tags |
| [`skills`](/cli/skills) | Manage agent skills |
| [`sandboxes`](/cli/sandboxes) | Manage sandbox dependencies, managed CLIs, and system packages |
| [`mcp-servers`](/cli/mcp-servers) | Manage MCP server connections and their tools |
| [`custom-tools`](/cli/custom-tools) | Manage custom tool definitions |
| [`credentials`](/cli/credentials) | Connect, reconnect, and disconnect integration credentials |
| [`secrets`](/cli/secrets) | Set and remove workspace secrets |
| [`billing`](/cli/billing) | Check plan status and credit usage |
| [`audit-logs`](/cli/audit-logs) | Read organization audit logs |
| [`workspaces`](/cli/workspaces) | Inspect the active workspace and its members |
| [`blocks`](/cli/blocks) | Browse the block catalog and read one block's configuration fields |
| [`tools`](/cli/tools) | Browse and execute built-in tools |
| [`connector-types`](/cli/connector-types) | Browse knowledge-base connector types and their config fields |
| [`chat-deployments`](/cli/chat-deployments) | List the hosted chats a workspace serves |
| [`workflow-mcp-servers`](/cli/workflow-mcp-servers) | Publish workflows as MCP tools for outside agents |
| [`meta`](/cli/meta) | Check what this API supports and which limits apply |
The [command overview](/cli/commands) has the global options and the commands
that take no resource; the [complete reference](/cli/reference) documents every
subcommand, argument, and flag on one page. Both are generated from the CLI
itself.
## Where to go next [#where-to-go-next]
* [Authentication](/cli/authentication) — signing in, API keys for CI, and multiple accounts
* [Configuration](/cli/configuration) — profiles, config files, environment variables, and precedence
* [Output formats](/cli/output) — `table`, `json`, `yaml`, and `text`, and when to use each
* [Scripting](/cli/scripting) — piping, file inputs, exit codes, and automation recipes
* [Troubleshooting](/cli/troubleshooting) — what each error means, and how to resolve it
---
# Knowledge (/cli/knowledge)
`sim knowledge` is also spelled `sim kb`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Index files the workspace already stores [#index-files-the-workspace-already-stores]
```bash
sim knowledge from-workspace-files create [options]
```
Index files the workspace already stores (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `--file ` | Yes | Workspace file ID or key (repeatable) (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
## Declare the tag definitions a knowledge base needs [#declare-the-tag-definitions-a-knowledge-base-needs]
```bash
sim knowledge tags save [options]
```
Declare the tag definitions a knowledge base needs (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `--definitions ` | Yes | Tag definitions: \[\{"tagSlot":"tag1","displayName":"category","fieldType":"text"}] (JSON, or @path / @- to read a file or stdin). |
## Create tag [#create-tag]
```bash
sim knowledge tags create [options]
```
Create Tag (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--display-name ` | Yes | Name tag filters and document reads use for this tag. |
| `--field-type ` | No | Value type stored in the slot; it decides which slots are usable and which filter operators apply. Defaults to text, so a number, date, or boolean slot must name its type here. Slot capacity per type: text 7, number 5, date 2, boolean 3. Accepted values: `text`, `number`, `date`, `boolean`. |
| `--tag-slot ` | No | Slot to store the tag in. Omit to take the next free slot for the field type; a slot that does not belong to the field type, or one already in use, is rejected. Accepted values: `tag1`, `tag2`, `tag3`, `tag4`, `tag5`, `tag6`, `tag7`, `number1`, `number2`, `number3`, `number4`, `number5`, `date1`, `date2`, `boolean1`, `boolean2`, `boolean3`. |
## Delete tag [#delete-tag]
```bash
sim knowledge tags delete [options]
```
Delete Tag (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `tagId` | Yes | Unique tag definition identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Remove tag definitions no document still uses [#remove-tag-definitions-no-document-still-uses]
```bash
sim knowledge tags cleanup [options]
```
Remove tag definitions no document still uses (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--unused` | No | Whether to remove only the tag definitions no document in the knowledge base still carries a value for. Defaults to true. Pass --no-unused to delete every definition on the knowledge base, which also clears its slot on every document and chunk and is not recoverable. |
| `--no-unused` | No | Send --unused as false. |
| `-y, --yes` | Yes | Confirm this operation. |
## Show which tag slot a create would take for a field type [#show-which-tag-slot-a-create-would-take-for-a-field-type]
```bash
sim knowledge tags next-slot [options]
```
Show which tag slot a create would take for a field type (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--field-type ` | Yes | Value type stored in the slot; it decides which slots are usable and which filter operators apply. Slot capacity per type: text 7, number 5, date 2, boolean 3. Accepted values: `text`, `number`, `date`, `boolean`. |
## List tags [#list-tags]
```bash
sim knowledge tags list
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
## Show how many documents and chunks carry each tag [#show-how-many-documents-and-chunks-carry-each-tag]
```bash
sim knowledge tags usage
```
Show how many documents and chunks carry each tag (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
## Update tag [#update-tag]
```bash
sim knowledge tags update [options]
```
Update Tag (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `tagId` | Yes | Unique tag definition identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | --------------------------------------------------------------------------------- |
| `--display-name ` | No | New tag display name. |
| `--field-type ` | No | New value type for the tag. Accepted values: `text`, `number`, `date`, `boolean`. |
## Enable, disable, or delete many chunks at once [#enable-disable-or-delete-many-chunks-at-once]
```bash
sim knowledge chunks batch-update [options]
```
Enable, disable, or delete many chunks at once (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| --------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--operation ` | Yes | What to do with the selected chunks. Accepted values: `enable`, `disable`, `delete`. |
| `--chunk ` | Yes | Chunks to operate on, by identifier. An id naming no chunk in the document is reported in errors and does not fail the request. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `-y, --yes` | Yes | Confirm this operation. |
## Create chunk [#create-chunk]
```bash
sim knowledge chunks create [options]
```
Create Chunk (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | ------------------------------------------------------------------------------- |
| `--content ` | Yes | Text to embed. It is embedded on write, so the chunk is searchable immediately. |
| `--enabled` | No | Whether the new chunk participates in search. |
| `--no-enabled` | No | Send --enabled as false. |
## Delete chunk [#delete-chunk]
```bash
sim knowledge chunks delete [options]
```
Delete Chunk (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
| `chunkId` | Yes | Unique chunk identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Get chunk [#get-chunk]
```bash
sim knowledge chunks get
```
Get Chunk (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
| `chunkId` | Yes | Unique chunk identifier. |
## List chunks [#list-chunks]
```bash
sim knowledge chunks list [options]
```
List Chunks (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against chunk content. |
| `--enabled ` | No | Restrict to enabled or disabled chunks. `all` returns both. Accepted values: `true`, `false`, `all`. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `chunkIndex`, `tokenCount`, `enabled`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
## Update chunk [#update-chunk]
```bash
sim knowledge chunks update [options]
```
Update Chunk (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
| `chunkId` | Yes | Unique chunk identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | ------------------------------------------------------------------------------------------------ |
| `--content ` | No | Replacement text. Changing it re-embeds the chunk and re-derives its token and character counts. |
| `--enabled` | No | Whether the chunk participates in search. Disabling keeps it indexed. |
| `--no-enabled` | No | Send --enabled as false. |
## Enable or disable every matching document [#enable-or-disable-every-matching-document]
```bash
sim knowledge documents batch-update [options]
```
Enable or disable every matching document (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `--operation ` | Yes | Whether the selected documents become enabled or disabled for search. Accepted values: `enable`, `disable`. |
| `--document ` | No | Documents to update, by identifier. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--select-all` | No | Apply to every document in the knowledge base. |
| `--enabled-filter ` | No | With `selectAll`, restrict the update to documents in this state. Accepted values: `all`, `enabled`, `disabled`. |
## Delete document [#delete-document]
```bash
sim knowledge documents delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Get document [#get-document]
```bash
sim knowledge documents get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
## List documents [#list-documents]
```bash
sim knowledge documents list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--search ` | No | Case-insensitive substring match against the document filename. |
| `--enabled-filter ` | No | Filter by whether documents are enabled for search. Accepted values: `all`, `enabled`, `disabled`. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `filename` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `filename`, `fileSize`, `tokenCount`, `chunkCount`, `uploadedAt`, `processingStatus`, `enabled`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--tag-filters ` | No | A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{"tagName":"category","operator":"eq","value":"billing"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored. |
## Update document [#update-document]
```bash
sim knowledge documents update [options]
```
Update Document (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filename ` | No | New filename for the document. |
| `--enabled` | No | Whether the document participates in search. Disabling keeps it indexed. |
| `--no-enabled` | No | Send --enabled as false. |
| `--tag1 ` | No | New value for tag slot 1. |
| `--tag2 ` | No | New value for tag slot 2. |
| `--tag3 ` | No | New value for tag slot 3. |
| `--tag4 ` | No | New value for tag slot 4. |
| `--tag5 ` | No | New value for tag slot 5. |
| `--tag6 ` | No | New value for tag slot 6. |
| `--tag7 ` | No | New value for tag slot 7. |
| `--number1 ` | No | New value for number tag slot 1. |
| `--number2 ` | No | New value for number tag slot 2. |
| `--number3 ` | No | New value for number tag slot 3. |
| `--number4 ` | No | New value for number tag slot 4. |
| `--number5 ` | No | New value for number tag slot 5. |
| `--date1 ` | No | New value for date tag slot 1, formatted YYYY-MM-DD. |
| `--date2 ` | No | New value for date tag slot 2, formatted YYYY-MM-DD. |
| `--boolean1` | No | New value for boolean tag slot 1. |
| `--no-boolean1` | No | Send --boolean1 as false. |
| `--boolean2` | No | New value for boolean tag slot 2. |
| `--no-boolean2` | No | Send --boolean2 as false. |
| `--boolean3` | No | New value for boolean tag slot 3. |
| `--no-boolean3` | No | Send --boolean3 as false. |
| `--retry-processing` | No | Requeue a failed or stuck document for processing. Send it alone — no other field may accompany it — and it answers with a queue acknowledgement rather than the document. |
## Upload a document to a knowledge base [#upload-a-document-to-a-knowledge-base]
```bash
sim knowledge documents upload [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ----------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base to upload into |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------------------------------------ |
| `--name ` | No | Store it under a different name. |
| `--tag ` | No | Document tags, in tag1 through tag7 order. |
| `--recipe ` | No | Document processing recipe. Accepted values: `default`, `plain`, `markdown`, `code`. |
| `--lang ` | No | Document language tag: hyphen-separated letter and digit subtags, for example en or en-US. |
## Create knowledge base [#create-knowledge-base]
```bash
sim knowledge create [options]
```
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Human-readable knowledge base name. |
| `--description ` | No | Optional knowledge base description. |
| `--chunking-config ` | No | Chunking configuration; defaults are applied when omitted. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
## Create knowledge connector [#create-knowledge-connector]
```bash
sim knowledge connectors create [options]
```
Create Knowledge Connector (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| `--connector-type ` | Yes | Registered connector type. |
| `--credential-id ` | No | OAuth credential identifier for connectors that require OAuth. |
| `--api-key ` | No | Write-only API key for connectors that use API-key authentication. |
| `--source-config ` | Yes | Connector-specific source selection and filtering configuration. (JSON, or @path / @- to read a file or stdin). |
| `--sync-interval-minutes ` | No | Scheduled synchronization interval in minutes; zero disables scheduling. |
## Delete knowledge connector [#delete-knowledge-connector]
```bash
sim knowledge connectors delete [options]
```
Delete Knowledge Connector (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------- |
| `--delete-documents` | No | Also permanently delete documents produced by this connector. |
| `--no-delete-documents` | No | Send --delete-documents as false. |
| `-y, --yes` | Yes | Confirm this operation. |
## Get knowledge connector [#get-knowledge-connector]
```bash
sim knowledge connectors get
```
Get Knowledge Connector (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
## List knowledge connector documents [#list-knowledge-connector-documents]
```bash
sim knowledge connectors documents list [options]
```
List Knowledge Connector Documents (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | -------------------------------------------------------------- |
| `--include-excluded` | No | Include documents explicitly excluded by a user. |
| `--no-include-excluded` | No | Send --include-excluded as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
## Update knowledge connector documents [#update-knowledge-connector-documents]
```bash
sim knowledge connectors documents update [options]
```
Update Knowledge Connector Documents (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `--operation ` | Yes | Whether to restore or exclude the selected documents. Accepted values: `restore`, `exclude`. |
| `--document ` | Yes | Connector document identifiers to update. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
## List knowledge connectors [#list-knowledge-connectors]
```bash
sim knowledge connectors list [options]
```
List Knowledge Connectors (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `connectorType`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## Queue a knowledge connector synchronization [#queue-a-knowledge-connector-synchronization]
```bash
sim knowledge connectors sync [options]
```
Queue a knowledge connector synchronization (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ---------------- | -------- | -------------------------------------------------------- |
| `--rehydrate` | No | Re-fetch and re-index every existing connector document. |
| `--no-rehydrate` | No | Send --rehydrate as false. |
## Update knowledge connector [#update-knowledge-connector]
```bash
sim knowledge connectors update [options]
```
Update Knowledge Connector (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--source-config ` | No | Replacement source selection and filtering configuration. Updating a runnable connector queues synchronization; paused connectors remain paused. (JSON, or @path / @- to read a file or stdin). |
| `--sync-interval-minutes ` | No | New scheduled synchronization interval in minutes. |
| `--status ` | No | New connector state. Accepted values: `active`, `paused`. |
## Create a knowledge folder at a path [#create-a-knowledge-folder-at-a-path]
```bash
sim knowledge folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
## Delete folder [#delete-folder]
```bash
sim knowledge folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | Yes | Confirm this operation. |
## List knowledge folders [#list-knowledge-folders]
```bash
sim knowledge folders list [options]
```
Also available as `sim knowledge folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
## Rename or move a knowledge folder [#rename-or-move-a-knowledge-folder]
```bash
sim knowledge folders move
```
Also available as `sim knowledge folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
| `destination` | Yes | Folder path as shown in the app; the leading / is optional |
## Delete knowledge base [#delete-knowledge-base]
```bash
sim knowledge delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Get knowledge base [#get-knowledge-base]
```bash
sim knowledge get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
## List knowledge bases [#list-knowledge-bases]
```bash
sim knowledge list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | No | Lifecycle scope: active or archived knowledge bases. Use Restore Knowledge Base to recover archived entries. Folder paths resolve only active folders, so filtering by an archived folder returns no matches. Accepted values: `active`, `archived`. |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
| `--search ` | No | Case-insensitive substring match against the resource name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## Restore an archived knowledge base [#restore-an-archived-knowledge-base]
```bash
sim knowledge restore
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
## Search knowledge [#search-knowledge]
```bash
sim knowledge search [options]
```
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--kb ` | Yes | Knowledge base ID (repeatable) (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--query ` | No | Text to search for. |
| `--top-k ` | No | Maximum number of search results to return. Must be a whole number between 1 and 100. |
| `--tag-filters ` | No | Tag filters as \[\{"tagName":"...","operator":"...","value":"..."}] (JSON, or @path / @- to read a file or stdin). |
| `--search-mode ` | No | Search algorithm. Accepted values: `vector`, `hybrid`. |
| `--reranker-enabled` | No | Re-order retrieved chunks with a reranking model before truncating to `topK`. Ignored for a tag-only search, and billed as an additional search unit. Reranking is best-effort — a provider failure falls back to vector ordering, so check `rerankerStatus` on the response. |
| `--no-reranker-enabled` | No | Send --reranker-enabled as false. |
| `--reranker-model ` | No | Reranking model to use when `rerankerEnabled` is true. Defaults to `rerank-v4.0-fast`. Accepted values: `rerank-v4.0-pro`, `rerank-v4.0-fast`, `rerank-v3.5`. |
| `--reranker-input-count ` | No | How many candidate chunks to retrieve before reranking. Defaults to four times `topK`, capped at 100. A larger pool costs more retrieval work but gives the reranker more to choose from. |
## Update knowledge base [#update-knowledge-base]
```bash
sim knowledge update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `--name ` | No | New knowledge base name. |
| `--description ` | No | New knowledge base description. |
| `--chunking-config ` | No | New document chunking configuration. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
## Move a knowledge base to a folder [#move-a-knowledge-base-to-a-folder]
```bash
sim knowledge mv
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ---------------------------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `folder` | Yes | Folder path as shown in the app; the leading / is optional |
## Export a knowledge base as a .simkb.zip bundle [#export-a-knowledge-base-as-a-simkbzip-bundle]
```bash
sim knowledge export [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------ |
| `knowledgeBaseId` | Yes | Knowledge base to export |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `-o, --output-file ` | No | Write the bundle to this path instead of the name the server suggests; pass - to stream it to stdout. |
| `--force` | No | Overwrite --output-file if it already exists. |
| `--no-vectors` | No | Leave chunk vectors out of the bundle, so an import re-embeds every chunk. |
## List knowledge resources and child folders together [#list-knowledge-resources-and-child-folders-together]
```bash
sim knowledge ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `0`. |
## Create a knowledge directory at a path [#create-a-knowledge-directory-at-a-path]
```bash
sim knowledge mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
---
# Logs (/cli/logs)
`sim logs` is also spelled `sim log`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Show run diagnostics [#show-run-diagnostics]
```bash
sim logs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| --------- | -------- | ------------------------------------------------------------------------- |
| `--trace` | No | Show expanded trace spans with inputs, outputs, errors, timing, and cost. |
## Summarize run counts, failures and latency over a window [#summarize-run-counts-failures-and-latency-over-a-window]
```bash
sim logs stats [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | No | Comma-separated workflow identifiers to include. At most 200 entries. An empty entry is rejected. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--trigger ` | No | Comma-separated trigger types to include. An empty entry is rejected. The vocabulary is open, so an unrecognized member selects no runs; the literal `all` disables this filter. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--level ` | No | Severity level to include. Accepted values: `info`, `error`. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--segment-count ` | No | Number of time buckets, up to 500. Exactly this many are returned, each at least one minute wide. Short windows extend past the requested end and include empty trailing buckets. |
## List logs [#list-logs]
```bash
sim logs list [options]
```
**Options**
| Option | Required | Description |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | No | Comma-separated workflow identifiers to include. An empty entry is rejected. At most 200 entries. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--trigger ` | No | Comma-separated, lowercase trigger types or webhook provider IDs. Matching is exact and case-sensitive; unknown values select no runs. An empty entry is rejected. The sentinel `all` disables this filter, even when listed with other values. At most 100 entries. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--level ` | No | Severity level to include. Accepted values: `info`, `error`. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--min-duration-ms ` | No | Minimum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--max-duration-ms ` | No | Maximum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--min-cost ` | No | Minimum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--max-cost ` | No | Maximum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--model ` | No | AI model used during execution. |
| `--details ` | No | Response detail level; full is requested by default to name each run’s workflow. Accepted values: `basic`, `full`. |
| `--include-trace-spans` | No | Include trace spans in JSON or YAML output (implies full detail). |
| `--include-final-output` | No | Include final output in JSON or YAML output (implies full detail). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--status ` | No | Comma-separated execution statuses to include, from `pending` \| `running` \| `paused` \| `redacting` \| `completed` \| `failed` \| `cancelled`. An empty entry is rejected. ANDed with `level`, which reports severity rather than lifecycle. |
| `--workflow-name ` | No | Case-insensitive substring match against the run's workflow name. Runs whose workflow has been deleted match nothing, because the name is no longer joinable. |
| `--include-job-runs` | No | Include Chat and Sim-agent jobs alongside workflow runs. Jobs use `kind: "job"` and have no workflow or cost ledger. Workflow, folder, model, or status filters exclude jobs. This option is valid only when sorting by `startedAt`. |
| `--no-include-job-runs` | No | Send --include-job-runs as false. |
| `--run-id ` | No | Exact run identifier to match. |
| `--sort-by ` | No | Field used to sort the result. `durationMs` and `cost` are null until a run settles; those runs sort before recorded values in ascending order and after them in descending order. Only `startedAt` can order Chat and Sim-agent job runs, so any other value is rejected when job runs are included. Accepted values: `startedAt`, `durationMs`, `cost`, `status`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
## Watch runs as they arrive, printing each new run once [#watch-runs-as-they-arrive-printing-each-new-run-once]
```bash
sim logs follow [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------ |
| `--workflow ` | No | Only follow runs of this workflow (repeatable). |
| `--folder ` | No | Only follow runs of workflows in this folder (repeatable). |
| `--trigger ` | No | Only follow runs with this trigger type (repeatable). |
| `--level ` | No | Only follow runs at this severity. Accepted values: `info`, `error`. |
| `--details ` | No | Response detail level; full names each run’s workflow. Accepted values: `basic`, `full`. Defaults to `full`. |
| `-n, --lines ` | No | Recent runs to print before watching. Defaults to `10`. |
| `--interval ` | No | Seconds between polls. Defaults to `3`. |
---
# MCP Servers (/cli/mcp-servers)
`sim mcp-servers` is also spelled `sim mcp-server`.
Every command below also accepts the [global options](/cli/commands#global-options).
## Create MCP server [#create-mcp-server]
```bash
sim mcp-servers create [options]
```
**Options**
| Option | Required | Description |
| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Server display name. |
| `--description ` | No | Optional server description. |
| `--transport ` | No | Transport protocol. Defaults to `streamable-http` on creation. Accepted values: `streamable-http`. |
| `--url ` | Yes | Absolute HTTP or HTTPS endpoint URL without `{{ENV_VAR}}` references. It determines server identity and is immutable: delete and recreate the server to change endpoints. |
| `--auth-type ` | No | Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method. Accepted values: `none`, `headers`, `oauth`. |
| `--headers ` | No | Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat. (JSON, or @path / @- to read a file or stdin). |
| `--timeout ` | No | Per-request timeout in milliseconds. Defaults to 30000 on creation. |
| `--retries ` | No | Number of retries per request. Defaults to 3 on creation. |
| `--enabled` | No | Whether workflows can use the server's tools. Defaults to true on creation. |
| `--no-enabled` | No | Send --enabled as false. |
| `--oauth-client-id ` | No | Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization. |
| `--oauth-client-secret ` | No | Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication. (--oauth-client-secret null sends the word, not JSON null). |
## Delete MCP server [#delete-mcp-server]
```bash
sim mcp-servers delete [options]
```
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ----------------------------- |
| `mcpServerId` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
## Get MCP server [#get-mcp-server]
```bash
sim mcp-servers get
```
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ----------------------------- |
| `mcpServerId` | Yes | Unique MCP server identifier. |
## List MCP servers [#list-mcp-servers]
```bash
sim mcp-servers list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the server name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## List MCP server tools [#list-mcp-server-tools]
```bash
sim mcp-servers tools list [options]
```
List MCP Server Tools (OAuth login or personal API key required)
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ----------------------------- |
| `mcpServerId` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| -------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `--refresh` | No | Refresh tools using your credentials. Otherwise results may reuse another workspace member's recent discovery and omit newly added tools. |
| `--no-refresh` | No | Send --refresh as false. |
## Update MCP server [#update-mcp-server]
```bash
sim mcp-servers update [options]
```
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ----------------------------- |
| `mcpServerId` | Yes | Unique MCP server identifier. |
**Options**
| Option | Required | Description |
| ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | No | Server display name. |
| `--description ` | No | Optional server description. |
| `--transport ` | No | Transport protocol. Defaults to `streamable-http` on creation. Accepted values: `streamable-http`. |
| `--url ` | No | Immutable server URL. When provided, it must equal the current URL; use delete and create to change endpoints. |
| `--auth-type ` | No | Authentication method. When omitted, and no `headers` are sent, registration probes the endpoint once to classify it, falling back to `headers` when the probe fails or the server does not advertise OAuth. A server publishing RFC 9728 metadata is therefore stored as `oauth`, and headers configured afterwards will not authenticate — send this field explicitly to pin the method. Accepted values: `none`, `headers`, `oauth`. |
| `--headers ` | No | Write-only request headers sent to the server. Replaced wholesale rather than merged on update: sending this field drops every stored header it does not repeat. (JSON, or @path / @- to read a file or stdin). |
| `--timeout ` | No | Per-request timeout in milliseconds. Defaults to 30000 on creation. |
| `--retries ` | No | Number of retries per request. Defaults to 3 on creation. |
| `--enabled` | No | Whether workflows can use the server's tools. Defaults to true on creation. |
| `--no-enabled` | No | Send --enabled as false. |
| `--oauth-client-id ` | No | Pre-registered OAuth client identifier. Changing it on update revokes the stored OAuth grant and forces reauthorization. |
| `--oauth-client-secret ` | No | Write-only pre-registered OAuth client secret. Sending it on update as null or a new value revokes the stored OAuth grant and forces reauthorization, as does switching away from OAuth authentication. (--oauth-client-secret null sends the word, not JSON null). |
---
# Meta (/cli/meta)
Every command below also accepts the [global options](/cli/commands#global-options).
## Show what this API supports and which limits apply [#show-what-this-api-supports-and-which-limits-apply]
```bash
sim meta status
```
---
# Output formats (/cli/output)
Commands that return structured API data support four output formats.
| Format | For |
| ------- | ------------------------------------------------- |
| `table` | reading (default) |
| `json` | piping into `jq` |
| `yaml` | piping into anything that reads YAML |
| `text` | shell loops — tab-separated, no header, no colour |
Select one per command, save it to the profile, or set it in the environment:
```bash
sim tables get tbl_9f3c1a05d4b7426e8c2f0917ab35de64 --output json
sim configure --set-output json
SIM_OUTPUT=yaml sim logs list > logs.yaml
```
`--output` works before or after the command.
## What each format emits [#what-each-format-emits]
`json` and `yaml` emit the API's raw values, not the table's formatting — a
duration stays `1500`, not `"1.5s"`.
Paginated lists include the rows under `data` and the continuation cursor under
`nextCursor`. A `null` cursor means no pages remain:
```json
{ "data": [{ "runId": "9c4f0b7e-2d81-4a35-b6e9-70f1c8a2d543" }], "nextCursor": null }
```
Read list rows with `jq '.data[]'` and check for more pages with `jq '.nextCursor'`.
`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` 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
echo "$id $name"
done
```
An absent value is an em-dash in `table` and an empty field in `text`.
## Reading a run in detail [#reading-a-run-in-detail]
`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 9c4f0b7e-2d81-4a35-b6e9-70f1c8a2d543 --trace
```
`json` and `yaml` always carry the complete response, so `--trace` is a no-op
there:
```bash
sim logs get 9c4f0b7e-2d81-4a35-b6e9-70f1c8a2d543 --output json | jq '.traceSpans'
```
## Exceptions [#exceptions]
`sim profiles` and `sim configure` print local configuration for humans.
`sim files get` writes the file’s raw content to stdout or `--output-file`.
`sim chat` streams reply text in `table` and `text` modes. In `json` or `yaml`
mode it waits for the finished result and includes the conversation ID.
`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 3a9e21d8-5f47-4c0b-b2ea-91d7c6034ef8 > wf.json
sim workflows import --workflow @wf.json
```
---
# Profiles (/cli/profiles)
`sim profiles` is also spelled `sim profile`.
Every command below also accepts the [global options](/cli/commands#global-options).
## List configured profiles [#list-configured-profiles]
```bash
sim profiles list
```
## Add a workspace profile that shares the active stored login [#add-a-workspace-profile-that-shares-the-active-stored-login]
```bash
sim profiles add [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------ |
| `name` | Yes | Name for the new profile |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------- |
| `-w, --workspace ` | No | Existing workspace to use; omit for an interactive picker. |
---
# Complete reference (/cli/reference)
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.
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 [#global-options]
These apply to every command, and may be written before or after it.
| Option | Description |
| ---------------------- | --------------------------------------------------------------------------------- |
| `-P, --profile ` | Profile to use (env: SIM\_PROFILE). |
| `--endpoint ` | Sim deployment to talk to (env: SIM\_ENDPOINT). |
| `-w, --workspace ` | Workspace to target (env: SIM\_WORKSPACE). |
| `--output ` | Output format for this command. Accepted values: `table`, `json`, `yaml`, `text`. |
## sim login [#sim-login]
Sign in through the browser and store the login for the profile
```bash
sim login [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--method ` | No | Credential to obtain: oauth requires OAuth support; api-key creates a permanent key through pairing (auto-selects when omitted). Accepted values: `oauth`, `api-key`. |
| `--no-browser` | No | Print the approval URL without opening it (either login method). |
| `--read-only` | No | Ask only for permission to read, never to change anything. |
| `--callback-port ` | No | Pin the local port the browser returns to. |
| `-y, --yes` | No | Overwrite an existing API-key profile without prompting. |
## sim logout [#sim-logout]
Sign out and remove the profile's stored login
```bash
sim logout [options]
```
**Options**
| Option | Required | Description |
| ------- | -------- | ---------------------------------------------------- |
| `--all` | No | Remove the profile entirely, including its settings. |
## sim whoami [#sim-whoami]
Show the resolved profile, where each setting came from, and whether it works
```bash
sim whoami [options]
```
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------------------------- |
| `--no-verify` | No | Skip the API check and only print the resolved settings. |
## sim configure [#sim-configure]
Set a profile's endpoint, default workspace, or output format
```bash
sim configure [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------ |
| `--set-endpoint ` | No | Sim deployment to talk to. |
| `--set-workspace ` | No | Default workspace for workspace-scoped commands. |
| `--set-output ` | No | Default output format (table \| json \| yaml \| text). |
| `--unset ` | No | Remove settings (endpoint, workspace, output). |
## sim chat [#sim-chat]
Ask Sim and print the reply
```bash
sim chat [options]
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | --------------- |
| `message` | Yes | What to ask Sim |
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------- |
| `-c, --conversation ` | No | Continue the conversation with this ID. |
## sim profiles [#sim-profiles]
Also spelled `sim profile`.
### sim profiles list [#sim-profiles-list]
List configured profiles
```bash
sim profiles list
```
### sim profiles add [#sim-profiles-add]
Add a workspace profile that shares the active stored login
```bash
sim profiles add [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------ |
| `name` | Yes | Name for the new profile |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------- |
| `-w, --workspace ` | No | Existing workspace to use; omit for an interactive picker. |
## sim audit-logs [#sim-audit-logs]
Also spelled `sim audit-log`.
### sim audit-logs get [#sim-audit-logs-get]
Get Audit Log (OAuth login or personal API key required)
```bash
sim audit-logs get [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | --------------------------- |
| `auditLogId` | Yes | Audit-log entry identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--organization ` | No | Organization ID; defaults to your only organization, and is required when your account belongs to more than one (OAuth login or personal API key required). |
### sim audit-logs list [#sim-audit-logs-list]
List Audit Logs (OAuth login or personal API key required)
```bash
sim audit-logs list [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--action ` | No | Filter by exact action name. |
| `--resource-type ` | No | Filter by resource type. Accepts a comma-separated set; members are trimmed and deduplicated, and member order affects neither the result nor the cursor. |
| `--resource-id ` | No | Filter by exact resource identifier. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--include-departed` | No | Include actions by users who have left the organization. |
| `--no-include-departed` | No | Send --include-departed as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--organization ` | No | Organization ID; defaults to your only organization, and is required when your account belongs to more than one (OAuth login or personal API key required). |
| `--actor-email ` | No | Filter by actor email address. |
| `--all-workspaces` | No | Do not filter to the configured workspace (OAuth login or personal API key required for account-wide access). |
## sim billing [#sim-billing]
### sim billing status [#sim-billing-status]
Show billing status and current-period credit usage (credits and storage require an OAuth login or personal API key)
```bash
sim billing status [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------------------------------------------------------- |
| `--all-workspaces` | No | Do not filter to the configured workspace (OAuth login or personal API key required for account-wide access). |
### sim billing logs [#sim-billing-logs]
List credit usage events (an OAuth login or personal API key reports only your events; a workspace API key reports every member's in aggregate, unattributed)
```bash
sim billing logs [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--source ` | No | Filter by usage source; sim-chat combines Copilot and workspace chat. Accepted values: `workflow`, `wand`, `sim-chat`, `mcp_copilot`, `mothership_block`, `knowledge-base`, `voice-input`, `enrichment`, `voice-output`, `api-tool`. |
| `--period ` | No | Billing period. Accepted values: `1d`, `7d`, `30d`, `all`, `custom`. |
| `--start-date ` | No | Custom period start (ISO 8601). |
| `--end-date ` | No | Custom period end (ISO 8601). |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--all-workspaces` | No | Do not filter to the configured workspace (OAuth login or personal API key required for account-wide access). |
## sim blocks [#sim-blocks]
### sim blocks get [#sim-blocks-get]
Get Block
```bash
sim blocks get
```
**Arguments**
| Argument | Required | Description |
| --------- | -------- | ------------------------------------------------------------------------------------------------------------------------ |
| `blockId` | Yes | Block type identifier. An unversioned base type resolves to the newest version, and the response echoes the resolved id. |
### sim blocks list [#sim-blocks-list]
List Blocks
```bash
sim blocks list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the block id, name, and description. |
| `--category ` | No | Restrict to one toolbar category. Accepted values: `blocks`, `tools`, `triggers`. |
| `--capability ` | No | Restrict to blocks that can start a workflow — the `triggers` category, blocks declaring `triggerAllowed`, and blocks with trigger-mode fields. Accepted values: `trigger`. |
| `--source ` | No | Restrict to built-in blocks or this workspace's deployed custom blocks. Accepted values: `builtin`, `custom`. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `id`, `name`, `category`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## sim chat-deployments [#sim-chat-deployments]
### sim chat-deployments list [#sim-chat-deployments-list]
List Chat Deployments
```bash
sim chat-deployments list [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | --------------------------------------------------------------------------------------- |
| `--workflow-id ` | No | Restrict to deployments of one workflow. |
| `--is-active` | No | Restrict to active or inactive deployments. |
| `--no-is-active` | No | Send --is-active as false. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `identifier`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
## sim connector-types [#sim-connector-types]
### sim connector-types list [#sim-connector-types-list]
List Connector Types
```bash
sim connector-types list [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------ |
| `--search ` | No | Case-insensitive substring match against the connector name. |
## sim credentials [#sim-credentials]
Also spelled `sim credential`.
### sim credentials delete [#sim-credentials-delete]
Disconnect Credential (OAuth login or personal API key required)
```bash
sim credentials delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------- |
| `credentialId` | Yes | Credential to disconnect. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim credentials providers list [#sim-credentials-providers-list]
List Credential Providers
```bash
sim credentials providers list [options]
```
**Options**
| Option | Required | Description |
| ------------------ | -------- | ---------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the credential provider name. |
### sim credentials list [#sim-credentials-list]
List Credentials
```bash
sim credentials list [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------- |
| `--type ` | No | Restrict results to this credential type. Accepted values: `oauth`, `service_account`. |
| `--provider-id ` | No | Restrict results to credentials for this integration provider. |
| `--search ` | No | Case-insensitive substring match against the credential display name. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `displayName`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
### sim credentials update [#sim-credentials-update]
Update Credential (OAuth login or personal API key required)
```bash
sim credentials update [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | --------------------- |
| `credentialId` | Yes | Credential to update. |
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `--display-name ` | No | New name shown for the credential in Sim. |
| `--description ` | No | New credential description. Send null to clear the stored one. (--description null sends the word, not JSON null). |
| `--service-account-json ` | No | Write-only Google service-account JSON key. |
| `--api-token ` | No | Write-only provider API token. |
| `--domain ` | No | Provider account domain. |
| `--atlassian-product ` | No | Atlassian product to verify; defaults to Jira on create and preserves the saved product on reconnect. Accepted values: `jira`, `confluence`. |
| `--signing-secret ` | No | Write-only webhook signing secret. |
| `--bot-token ` | No | Write-only bot token. |
| `--client-id ` | No | OAuth client identifier. |
| `--client-secret ` | No | Write-only OAuth client secret. |
| `--certificate-id ` | No | Provider certificate mapping identifier. |
| `--org-id ` | No | Provider organization ID. |
| `--data-center ` | No | Provider data center. |
| `--auth-method ` | No | Provider authentication method. |
| `--private-key ` | No | Write-only PEM private key. |
| `--username ` | No | Provider run-as username. |
| `--name ` | No | Alias for --display-name. |
### sim credentials create [#sim-credentials-create]
Create a service-account credential using its discovered provider schema (OAuth login or personal API key required)
```bash
sim credentials create [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | --------------------------------------------------- |
| `providerId` | Yes | Service-account provider to create a credential for |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | --------------------------------------------------------------------- |
| `--name ` | Yes | Name shown for the credential in Sim. |
| `--credentials ` | Yes | Provider credentials as JSON (or @path / @- to read a file or stdin). |
| `--description ` | No | Optional credential description. |
| `--id ` | No | Client-generated credential ID when provider discovery requires it. |
### sim credentials connect [#sim-credentials-connect]
Create a short-lived link for connecting an OAuth provider (OAuth login or personal API key required)
```bash
sim credentials connect [options]
```
**Arguments**
| Argument | Required | Description |
| ------------ | -------- | ------------------------- |
| `providerId` | Yes | OAuth provider to connect |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ----------------------------------------- |
| `--name ` | Yes | Name shown for the new credential in Sim. |
### sim credentials reconnect [#sim-credentials-reconnect]
Create a short-lived link for reconnecting an OAuth credential (OAuth login or personal API key required)
```bash
sim credentials reconnect
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ----------------------------------------- |
| `credentialId` | Yes | Existing OAuth credential to re-authorize |
## sim custom-tools [#sim-custom-tools]
Also spelled `sim custom-tool`.
### sim custom-tools create [#sim-custom-tools-create]
Create Custom Tool
```bash
sim custom-tools create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | Yes | Display title, unique within the workspace. |
| `--schema ` | Yes | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | Yes | Tool implementation executed in the sandboxed function runtime. |
### sim custom-tools delete [#sim-custom-tools-delete]
Delete Custom Tool
```bash
sim custom-tools delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------------ |
| `customToolId` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim custom-tools get [#sim-custom-tools-get]
Get Custom Tool
```bash
sim custom-tools get
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------------ |
| `customToolId` | Yes | Unique custom tool identifier. |
### sim custom-tools list [#sim-custom-tools-list]
List Custom Tools
```bash
sim custom-tools list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against the tool title. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `title`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
### sim custom-tools update [#sim-custom-tools-update]
Update Custom Tool
```bash
sim custom-tools update [options]
```
**Arguments**
| Argument | Required | Description |
| -------------- | -------- | ------------------------------ |
| `customToolId` | Yes | Unique custom tool identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--title ` | No | New display title for the tool. |
| `--schema ` | No | OpenAI function schema: \{"type":"function","function":\{"name":"...","parameters":\{"type":"object","properties":\{}}}} (JSON, or @path / @- to read a file or stdin). |
| `--code ` | No | Replacement tool implementation. |
## sim files [#sim-files]
Also spelled `sim file`.
### sim files batch-delete [#sim-files-batch-delete]
Delete several files at once
```bash
sim files batch-delete [options]
```
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `-y, --yes` | Yes | Confirm this operation. |
### sim files create [#sim-files-create]
Create File
```bash
sim files create [options]
```
**Options**
| Option | Required | Description |
| ------------------------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | File name, including its extension. Path separators and dot segments are rejected. |
| `--content-type ` | No | MIME type. When omitted, it is inferred from the file extension. |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
| `--content ` | No | Initial file content. Omit or send an empty string for a zero-byte file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. Use an upload session for anything larger. |
| `--encoding ` | No | Encoding of the content field. Accepted values: `utf-8`, `base64`. |
### sim files folders create [#sim-files-folders-create]
Create a file folder at a path
```bash
sim files folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
### sim files folders delete [#sim-files-folders-delete]
Delete Folder
```bash
sim files folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | Yes | Confirm this operation. |
### sim files folders list [#sim-files-folders-list]
List folders
```bash
sim files folders list [options]
```
Also available as `sim files folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--scope ` | No | Which lifecycle set to list: `active` (default) returns live folders only; `archived` returns folders a recursive delete soft-deleted, which is how a caller finds a path to hand to the folder restore. Authorization is identical for both. Accepted values: `active`, `archived`. |
| `--recursive ` | No | Whether parentPath includes every descendant instead of direct children only. Accepted values: `true`, `1`, `yes`, `on`, `y`, `enabled`, `false`, `0`, `no`, `off`, `n`, `disabled`. |
| `--depth ` | No | Deepest level below parentPath to include when recursive is true. |
### sim files folders move [#sim-files-folders-move]
Rename or move a file folder
```bash
sim files folders move
```
Also available as `sim files folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
| `destination` | Yes | Folder path as shown in the app; the leading / is optional |
### sim files folders restore [#sim-files-folders-restore]
Restore an archived file folder
```bash
sim files folders restore
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
### sim files delete [#sim-files-delete]
Delete File
```bash
sim files delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim files edit [#sim-files-edit]
Apply one exact or anchor-based edit to a text file
```bash
sim files edit [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--edit ` | Yes | One edit object: \{"mode":"search\_replace","search":"old","content":"new","replaceAll":false}, \{"mode":"replace\_between","beforeAnchor":"start line","afterAnchor":"end line","content":"new"}, \{"mode":"insert\_after","anchor":"line","content":"new"}, or \{"mode":"delete\_between","startAnchor":"first line deleted","endAnchor":"ending line kept"}. Anchored modes also accept occurrence starting at 1 (JSON, or @path / @- to read a file or stdin). |
### sim files describe [#sim-files-describe]
Show file metadata and sharing status
```bash
sim files describe [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--scope ` | No | Which lifecycle set to read from: `active` (default) resolves live files only and returns `404` for a file a delete soft-deleted; `archived` also resolves soft-deleted files, so metadata stays readable before the file is restored. Authorization is identical for both. Accepted values: `active`, `archived`. |
### sim files share get [#sim-files-share-get]
Show a file’s share settings
```bash
sim files share get
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
### sim files share set [#sim-files-share-set]
Enable or disable sharing for a file (OAuth login or personal API key required)
```bash
sim files share set [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--is-active ` | Yes | Whether the share should resolve. Disabling preserves the token and the whole access configuration, so re-enabling restores the share as it was; enabling rewrites the credentials the resulting mode does not use. Accepted values: `true`, `false`. |
| `--auth-type ` | No | How access to the share is gated. The stored mode is kept when omitted. Enabling `public` clears the stored password and empties `allowedEmails`; `password` empties `allowedEmails`; `email` and `sso` clear the stored password. Accepted values: `public`, `password`, `email`, `sso`. |
| `--password ` | No | Password for a password-gated share. Kept when omitted; enabling `password` with neither a supplied nor a stored password is a 400. |
| `--allowed-emails ` | No | Allowed addresses or `@domain` patterns for email and SSO shares. Kept when omitted; enabling `email` or `sso` with an empty resulting list is a 400. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
### sim files list [#sim-files-list]
List Files
```bash
sim files list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
| `--recursive` | No | Include subfolders in the folder filter. Defaults to true when searching and false otherwise. Ignored without a folder filter. |
| `--no-recursive` | No | Send --recursive as false. |
| `--scope ` | No | Which lifecycle set to list: `active` (default) for live files, `archived` for files a delete soft-deleted. `folderPath` resolves against active folders only, so pairing it with `scope=archived` returns an empty page when the containing folder was archived too. Accepted values: `active`, `archived`. |
| `--search ` | No | Case-insensitive substring match against the file name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `size`, `uploadedAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
### sim files move [#sim-files-move]
Move files into another folder
```bash
sim files move [options]
```
Also available as `sim files mv`.
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- |
| `--file-ids ` | Yes | File identifiers to update. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--to ` | No | Destination folder path; omit for root. |
### sim files read [#sim-files-read]
Read a file’s text content
```bash
sim files read [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| --------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `--max-bytes ` | No | Optional ceiling on the source bytes fed to the parser, lowering but never raising the server limit. |
| `--offset ` | No | First line to return, 1-based. Absent starts at the first line. |
| `--limit ` | No | How many lines to return from `offset`. Absent reads to the end. |
### sim files rename [#sim-files-rename]
Rename a file
```bash
sim files rename [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ---------------- | -------- | --------------------------------------- |
| `--name ` | Yes | New file name, including its extension. |
### sim files restore [#sim-files-restore]
Restore an archived file
```bash
sim files restore
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
### sim files search [#sim-files-search]
Search File Content
```bash
sim files search [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--query ` | Yes | Regular expression, or exact text when `mode` is `exact`. |
| `--mode ` | No | How `query` is read. Accepted values: `exact`, `regex`. |
| `--max-results ` | No | Maximum matching lines to return. |
| `--folder ` | No | Folders to search, by path as shown in the app; omit to search the whole workspace (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--include-subfolders` | No | Whether each folder scope includes nested folders; on by default. |
| `--no-include-subfolders` | No | Send --include-subfolders as false. |
### sim files unzip [#sim-files-unzip]
Unzip an archive into a new folder beside it
```bash
sim files unzip [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim files set-content [#sim-files-set-content]
Replace a file’s contents
```bash
sim files set-content [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------- |
| `fileId` | Yes | File identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--content ` | Yes | Complete replacement content for the file. The 70,000,000-character bound guards the JSON envelope; the decoded bytes must be at most 50 MiB, and a longer base64 payload is rejected with `413`. |
| `--encoding ` | No | Content encoding. Accepted values: `utf-8`, `base64`. |
### sim files upload [#sim-files-upload]
Upload a file to the workspace
```bash
sim files upload [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------- |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ----------------- | -------- | ------------------------------------------------------------- |
| `--folder ` | No | Folder path as shown in the app; defaults to the root folder. |
| `--name ` | No | Store it under a different name. |
### sim files get [#sim-files-get]
Get a file’s content
```bash
sim files get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | -------------------------- |
| `fileId` | Yes | File whose content to read |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | --------------------------------------------- |
| `-o, --output-file ` | No | Write content to a file instead of stdout. |
| `--force` | No | Overwrite --output-file if it already exists. |
### sim files ls [#sim-files-ls]
List file resources and child folders together
```bash
sim files ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `0`. |
### sim files mkdir [#sim-files-mkdir]
Create a file directory at a path
```bash
sim files mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
## sim knowledge [#sim-knowledge]
Also spelled `sim kb`.
### sim knowledge from-workspace-files create [#sim-knowledge-from-workspace-files-create]
Index files the workspace already stores (OAuth login or personal API key required)
```bash
sim knowledge from-workspace-files create [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `--file ` | Yes | Workspace file ID or key (repeatable) (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
### sim knowledge tags save [#sim-knowledge-tags-save]
Declare the tag definitions a knowledge base needs (OAuth login or personal API key required)
```bash
sim knowledge tags save [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ----------------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `--definitions ` | Yes | Tag definitions: \[\{"tagSlot":"tag1","displayName":"category","fieldType":"text"}] (JSON, or @path / @- to read a file or stdin). |
### sim knowledge tags create [#sim-knowledge-tags-create]
Create Tag (OAuth login or personal API key required)
```bash
sim knowledge tags create [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `--display-name ` | Yes | Name tag filters and document reads use for this tag. |
| `--field-type ` | No | Value type stored in the slot; it decides which slots are usable and which filter operators apply. Defaults to text, so a number, date, or boolean slot must name its type here. Slot capacity per type: text 7, number 5, date 2, boolean 3. Accepted values: `text`, `number`, `date`, `boolean`. |
| `--tag-slot ` | No | Slot to store the tag in. Omit to take the next free slot for the field type; a slot that does not belong to the field type, or one already in use, is rejected. Accepted values: `tag1`, `tag2`, `tag3`, `tag4`, `tag5`, `tag6`, `tag7`, `number1`, `number2`, `number3`, `number4`, `number5`, `date1`, `date2`, `boolean1`, `boolean2`, `boolean3`. |
### sim knowledge tags delete [#sim-knowledge-tags-delete]
Delete Tag (OAuth login or personal API key required)
```bash
sim knowledge tags delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `tagId` | Yes | Unique tag definition identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge tags cleanup [#sim-knowledge-tags-cleanup]
Remove tag definitions no document still uses (OAuth login or personal API key required)
```bash
sim knowledge tags cleanup [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--unused` | No | Whether to remove only the tag definitions no document in the knowledge base still carries a value for. Defaults to true. Pass --no-unused to delete every definition on the knowledge base, which also clears its slot on every document and chunk and is not recoverable. |
| `--no-unused` | No | Send --unused as false. |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge tags next-slot [#sim-knowledge-tags-next-slot]
Show which tag slot a create would take for a field type (OAuth login or personal API key required)
```bash
sim knowledge tags next-slot [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--field-type ` | Yes | Value type stored in the slot; it decides which slots are usable and which filter operators apply. Slot capacity per type: text 7, number 5, date 2, boolean 3. Accepted values: `text`, `number`, `date`, `boolean`. |
### sim knowledge tags list [#sim-knowledge-tags-list]
List Tags
```bash
sim knowledge tags list
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
### sim knowledge tags usage [#sim-knowledge-tags-usage]
Show how many documents and chunks carry each tag (OAuth login or personal API key required)
```bash
sim knowledge tags usage
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
### sim knowledge tags update [#sim-knowledge-tags-update]
Update Tag (OAuth login or personal API key required)
```bash
sim knowledge tags update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `tagId` | Yes | Unique tag definition identifier. |
**Options**
| Option | Required | Description |
| ------------------------ | -------- | --------------------------------------------------------------------------------- |
| `--display-name ` | No | New tag display name. |
| `--field-type ` | No | New value type for the tag. Accepted values: `text`, `number`, `date`, `boolean`. |
### sim knowledge chunks batch-update [#sim-knowledge-chunks-batch-update]
Enable, disable, or delete many chunks at once (OAuth login or personal API key required)
```bash
sim knowledge chunks batch-update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| --------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--operation ` | Yes | What to do with the selected chunks. Accepted values: `enable`, `disable`, `delete`. |
| `--chunk ` | Yes | Chunks to operate on, by identifier. An id naming no chunk in the document is reported in errors and does not fail the request. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge chunks create [#sim-knowledge-chunks-create]
Create Chunk (OAuth login or personal API key required)
```bash
sim knowledge chunks create [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | ------------------------------------------------------------------------------- |
| `--content ` | Yes | Text to embed. It is embedded on write, so the chunk is searchable immediately. |
| `--enabled` | No | Whether the new chunk participates in search. |
| `--no-enabled` | No | Send --enabled as false. |
### sim knowledge chunks delete [#sim-knowledge-chunks-delete]
Delete Chunk (OAuth login or personal API key required)
```bash
sim knowledge chunks delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
| `chunkId` | Yes | Unique chunk identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge chunks get [#sim-knowledge-chunks-get]
Get Chunk (OAuth login or personal API key required)
```bash
sim knowledge chunks get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
| `chunkId` | Yes | Unique chunk identifier. |
### sim knowledge chunks list [#sim-knowledge-chunks-list]
List Chunks (OAuth login or personal API key required)
```bash
sim knowledge chunks list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------- |
| `--search ` | No | Case-insensitive substring match against chunk content. |
| `--enabled ` | No | Restrict to enabled or disabled chunks. `all` returns both. Accepted values: `true`, `false`, `all`. |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `chunkIndex`, `tokenCount`, `enabled`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
### sim knowledge chunks update [#sim-knowledge-chunks-update]
Update Chunk (OAuth login or personal API key required)
```bash
sim knowledge chunks update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
| `chunkId` | Yes | Unique chunk identifier. |
**Options**
| Option | Required | Description |
| ------------------- | -------- | ------------------------------------------------------------------------------------------------ |
| `--content ` | No | Replacement text. Changing it re-embeds the chunk and re-derives its token and character counts. |
| `--enabled` | No | Whether the chunk participates in search. Disabling keeps it indexed. |
| `--no-enabled` | No | Send --enabled as false. |
### sim knowledge documents batch-update [#sim-knowledge-documents-batch-update]
Enable or disable every matching document (OAuth login or personal API key required)
```bash
sim knowledge documents batch-update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| `--operation ` | Yes | Whether the selected documents become enabled or disabled for search. Accepted values: `enable`, `disable`. |
| `--document ` | No | Documents to update, by identifier. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--select-all` | No | Apply to every document in the knowledge base. |
| `--enabled-filter ` | No | With `selectAll`, restrict the update to documents in this state. Accepted values: `all`, `enabled`, `disabled`. |
### sim knowledge documents delete [#sim-knowledge-documents-delete]
Delete Document
```bash
sim knowledge documents delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge documents get [#sim-knowledge-documents-get]
Get Document
```bash
sim knowledge documents get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
### sim knowledge documents list [#sim-knowledge-documents-list]
List Documents
```bash
sim knowledge documents list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--search ` | No | Case-insensitive substring match against the document filename. |
| `--enabled-filter ` | No | Filter by whether documents are enabled for search. Accepted values: `all`, `enabled`, `disabled`. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `filename` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `filename`, `fileSize`, `tokenCount`, `chunkCount`, `uploadedAt`, `processingStatus`, `enabled`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
| `--tag-filters ` | No | A JSON-encoded array of at most 10 tag filters, using the same display-name shape as knowledge search: `[{"tagName":"category","operator":"eq","value":"billing"}]`. Every filter must hold, including two that name the same tag. A name that is not defined in this knowledge base is rejected, never ignored. |
### sim knowledge documents update [#sim-knowledge-documents-update]
Update Document (OAuth login or personal API key required)
```bash
sim knowledge documents update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `documentId` | Yes | Unique knowledge document identifier. |
**Options**
| Option | Required | Description |
| -------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--filename ` | No | New filename for the document. |
| `--enabled` | No | Whether the document participates in search. Disabling keeps it indexed. |
| `--no-enabled` | No | Send --enabled as false. |
| `--tag1 ` | No | New value for tag slot 1. |
| `--tag2 ` | No | New value for tag slot 2. |
| `--tag3 ` | No | New value for tag slot 3. |
| `--tag4 ` | No | New value for tag slot 4. |
| `--tag5 ` | No | New value for tag slot 5. |
| `--tag6 ` | No | New value for tag slot 6. |
| `--tag7 ` | No | New value for tag slot 7. |
| `--number1 ` | No | New value for number tag slot 1. |
| `--number2 ` | No | New value for number tag slot 2. |
| `--number3 ` | No | New value for number tag slot 3. |
| `--number4 ` | No | New value for number tag slot 4. |
| `--number5 ` | No | New value for number tag slot 5. |
| `--date1 ` | No | New value for date tag slot 1, formatted YYYY-MM-DD. |
| `--date2 ` | No | New value for date tag slot 2, formatted YYYY-MM-DD. |
| `--boolean1` | No | New value for boolean tag slot 1. |
| `--no-boolean1` | No | Send --boolean1 as false. |
| `--boolean2` | No | New value for boolean tag slot 2. |
| `--no-boolean2` | No | Send --boolean2 as false. |
| `--boolean3` | No | New value for boolean tag slot 3. |
| `--no-boolean3` | No | Send --boolean3 as false. |
| `--retry-processing` | No | Requeue a failed or stuck document for processing. Send it alone — no other field may accompany it — and it answers with a queue acknowledgement rather than the document. |
### sim knowledge documents upload [#sim-knowledge-documents-upload]
Upload a document to a knowledge base
```bash
sim knowledge documents upload [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ----------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base to upload into |
| `path` | Yes | Local file to upload |
**Options**
| Option | Required | Description |
| ------------------ | -------- | ------------------------------------------------------------------------------------------ |
| `--name ` | No | Store it under a different name. |
| `--tag ` | No | Document tags, in tag1 through tag7 order. |
| `--recipe ` | No | Document processing recipe. Accepted values: `default`, `plain`, `markdown`, `code`. |
| `--lang ` | No | Document language tag: hyphen-separated letter and digit subtags, for example en or en-US. |
### sim knowledge create [#sim-knowledge-create]
Create Knowledge Base
```bash
sim knowledge create [options]
```
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| `--name ` | Yes | Human-readable knowledge base name. |
| `--description ` | No | Optional knowledge base description. |
| `--chunking-config ` | No | Chunking configuration; defaults are applied when omitted. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
### sim knowledge connectors create [#sim-knowledge-connectors-create]
Create Knowledge Connector (OAuth login or personal API key required)
```bash
sim knowledge connectors create [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------- |
| `--connector-type ` | Yes | Registered connector type. |
| `--credential-id ` | No | OAuth credential identifier for connectors that require OAuth. |
| `--api-key ` | No | Write-only API key for connectors that use API-key authentication. |
| `--source-config ` | Yes | Connector-specific source selection and filtering configuration. (JSON, or @path / @- to read a file or stdin). |
| `--sync-interval-minutes ` | No | Scheduled synchronization interval in minutes; zero disables scheduling. |
### sim knowledge connectors delete [#sim-knowledge-connectors-delete]
Delete Knowledge Connector (OAuth login or personal API key required)
```bash
sim knowledge connectors delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------- |
| `--delete-documents` | No | Also permanently delete documents produced by this connector. |
| `--no-delete-documents` | No | Send --delete-documents as false. |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge connectors get [#sim-knowledge-connectors-get]
Get Knowledge Connector (OAuth login or personal API key required)
```bash
sim knowledge connectors get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
### sim knowledge connectors documents list [#sim-knowledge-connectors-documents-list]
List Knowledge Connector Documents (OAuth login or personal API key required)
```bash
sim knowledge connectors documents list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | -------------------------------------------------------------- |
| `--include-excluded` | No | Include documents explicitly excluded by a user. |
| `--no-include-excluded` | No | Send --include-excluded as false. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `100`. |
| `--cursor ` | No | Continue from nextCursor returned by a previous result. |
### sim knowledge connectors documents update [#sim-knowledge-connectors-documents-update]
Update Knowledge Connector Documents (OAuth login or personal API key required)
```bash
sim knowledge connectors documents update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------ |
| `--operation ` | Yes | Whether to restore or exclude the selected documents. Accepted values: `restore`, `exclude`. |
| `--document ` | Yes | Connector document identifiers to update. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
### sim knowledge connectors list [#sim-knowledge-connectors-list]
List Knowledge Connectors (OAuth login or personal API key required)
```bash
sim knowledge connectors list [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------ |
| `--sort-by ` | No | Field used to sort the result. Accepted values: `connectorType`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
### sim knowledge connectors sync [#sim-knowledge-connectors-sync]
Queue a knowledge connector synchronization (OAuth login or personal API key required)
```bash
sim knowledge connectors sync [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| ---------------- | -------- | -------------------------------------------------------- |
| `--rehydrate` | No | Re-fetch and re-index every existing connector document. |
| `--no-rehydrate` | No | Send --rehydrate as false. |
### sim knowledge connectors update [#sim-knowledge-connectors-update]
Update Knowledge Connector (OAuth login or personal API key required)
```bash
sim knowledge connectors update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------------- |
| `knowledgeBaseId` | Yes | Knowledge base that owns the connector. |
| `connectorId` | Yes | Connector selected for the operation. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--source-config ` | No | Replacement source selection and filtering configuration. Updating a runnable connector queues synchronization; paused connectors remain paused. (JSON, or @path / @- to read a file or stdin). |
| `--sync-interval-minutes ` | No | New scheduled synchronization interval in minutes. |
| `--status ` | No | New connector state. Accepted values: `active`, `paused`. |
### sim knowledge folders create [#sim-knowledge-folders-create]
Create a knowledge folder at a path
```bash
sim knowledge folders create
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
### sim knowledge folders delete [#sim-knowledge-folders-delete]
Delete Folder
```bash
sim knowledge folders delete [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
**Options**
| Option | Required | Description |
| ------------- | -------- | -------------------------------------- |
| `--recursive` | No | Delete the folder and its descendants. |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge folders list [#sim-knowledge-folders-list]
List knowledge folders
```bash
sim knowledge folders list [options]
```
Also available as `sim knowledge folders ls`.
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--parent ` | No | Direct parent folder path. |
| `--search ` | No | Case-insensitive substring match against the folder name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
### sim knowledge folders move [#sim-knowledge-folders-move]
Rename or move a knowledge folder
```bash
sim knowledge folders move
```
Also available as `sim knowledge folders mv`.
**Arguments**
| Argument | Required | Description |
| ------------- | -------- | ---------------------------------------------------------- |
| `path` | Yes | Folder path as shown in the app; the leading / is optional |
| `destination` | Yes | Folder path as shown in the app; the leading / is optional |
### sim knowledge delete [#sim-knowledge-delete]
Delete Knowledge Base
```bash
sim knowledge delete [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| ----------- | -------- | ----------------------- |
| `-y, --yes` | Yes | Confirm this operation. |
### sim knowledge get [#sim-knowledge-get]
Get Knowledge Base
```bash
sim knowledge get
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
### sim knowledge list [#sim-knowledge-list]
List Knowledge Bases
```bash
sim knowledge list [options]
```
**Options**
| Option | Required | Description |
| ---------------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--scope ` | No | Lifecycle scope: active or archived knowledge bases. Use Restore Knowledge Base to recover archived entries. Folder paths resolve only active folders, so filtering by an archived folder returns no matches. Accepted values: `active`, `archived`. |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
| `--search ` | No | Case-insensitive substring match against the resource name. |
| `--sort-by ` | No | Field used to sort the result. Sorting by `name` is case-sensitive and follows the storage collation, so do not rely on a case-insensitive order. Accepted values: `name`, `createdAt`, `updatedAt`. |
| `--sort-order ` | No | Sort direction. Accepted values: `asc`, `desc`. |
| `--limit ` | No | Maximum items to return (0 for everything). Defaults to `0`. |
### sim knowledge restore [#sim-knowledge-restore]
Restore an archived knowledge base
```bash
sim knowledge restore
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
### sim knowledge search [#sim-knowledge-search]
Search Knowledge
```bash
sim knowledge search [options]
```
**Options**
| Option | Required | Description |
| -------------------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--kb ` | Yes | Knowledge base ID (repeatable) (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--query ` | No | Text to search for. |
| `--top-k ` | No | Maximum number of search results to return. Must be a whole number between 1 and 100. |
| `--tag-filters ` | No | Tag filters as \[\{"tagName":"...","operator":"...","value":"..."}] (JSON, or @path / @- to read a file or stdin). |
| `--search-mode ` | No | Search algorithm. Accepted values: `vector`, `hybrid`. |
| `--reranker-enabled` | No | Re-order retrieved chunks with a reranking model before truncating to `topK`. Ignored for a tag-only search, and billed as an additional search unit. Reranking is best-effort — a provider failure falls back to vector ordering, so check `rerankerStatus` on the response. |
| `--no-reranker-enabled` | No | Send --reranker-enabled as false. |
| `--reranker-model ` | No | Reranking model to use when `rerankerEnabled` is true. Defaults to `rerank-v4.0-fast`. Accepted values: `rerank-v4.0-pro`, `rerank-v4.0-fast`, `rerank-v3.5`. |
| `--reranker-input-count ` | No | How many candidate chunks to retrieve before reranking. Defaults to four times `topK`, capped at 100. A larger pool costs more retrieval work but gives the reranker more to choose from. |
### sim knowledge update [#sim-knowledge-update]
Update Knowledge Base
```bash
sim knowledge update [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | --------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
**Options**
| Option | Required | Description |
| --------------------------------- | -------- | ----------------------------------------------------------------------------------- |
| `--name ` | No | New knowledge base name. |
| `--description ` | No | New knowledge base description. |
| `--chunking-config ` | No | New document chunking configuration. (JSON, or @path / @- to read a file or stdin). |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional. |
### sim knowledge mv [#sim-knowledge-mv]
Move a knowledge base to a folder
```bash
sim knowledge mv
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ---------------------------------------------------------- |
| `knowledgeBaseId` | Yes | Unique knowledge base identifier. |
| `folder` | Yes | Folder path as shown in the app; the leading / is optional |
### sim knowledge export [#sim-knowledge-export]
Export a knowledge base as a .simkb.zip bundle
```bash
sim knowledge export [options]
```
**Arguments**
| Argument | Required | Description |
| ----------------- | -------- | ------------------------ |
| `knowledgeBaseId` | Yes | Knowledge base to export |
**Options**
| Option | Required | Description |
| -------------------------- | -------- | ----------------------------------------------------------------------------------------------------- |
| `-o, --output-file ` | No | Write the bundle to this path instead of the name the server suggests; pass - to stream it to stdout. |
| `--force` | No | Overwrite --output-file if it already exists. |
| `--no-vectors` | No | Leave chunk vectors out of the bundle, so an import re-embeds every chunk. |
### sim knowledge ls [#sim-knowledge-ls]
List knowledge resources and child folders together
```bash
sim knowledge ls [path] [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | No | Folder path to list; defaults to the root folder |
**Options**
| Option | Required | Description |
| ----------------- | -------- | --------------------------------------------------------------------- |
| `--search ` | No | Filter folders and resources by name. |
| `--limit ` | No | Maximum combined items to return (0 for everything). Defaults to `0`. |
### sim knowledge mkdir [#sim-knowledge-mkdir]
Create a knowledge directory at a path
```bash
sim knowledge mkdir
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------------------------ |
| `path` | Yes | Folder path to create; the leading / is optional |
## sim logs [#sim-logs]
Also spelled `sim log`.
### sim logs get [#sim-logs-get]
Show run diagnostics
```bash
sim logs get [options]
```
**Arguments**
| Argument | Required | Description |
| -------- | -------- | ------------------------------- |
| `runId` | Yes | Unique workflow run identifier. |
**Options**
| Option | Required | Description |
| --------- | -------- | ------------------------------------------------------------------------- |
| `--trace` | No | Show expanded trace spans with inputs, outputs, errors, timing, and cost. |
### sim logs stats [#sim-logs-stats]
Summarize run counts, failures and latency over a window
```bash
sim logs stats [options]
```
**Options**
| Option | Required | Description |
| ------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | No | Comma-separated workflow identifiers to include. At most 200 entries. An empty entry is rejected. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--folder ` | No | Folder path as shown in the app; the leading / is optional (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--trigger ` | No | Comma-separated trigger types to include. An empty entry is rejected. The vocabulary is open, so an unrecognized member selects no runs; the literal `all` disables this filter. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--level ` | No | Severity level to include. Accepted values: `info`, `error`. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--segment-count ` | No | Number of time buckets, up to 500. Exactly this many are returned, each at least one minute wide. Short windows extend past the requested end and include empty trailing buckets. |
### sim logs list [#sim-logs-list]
List Logs
```bash
sim logs list [options]
```
**Options**
| Option | Required | Description |
| --------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `--workflow ` | No | Comma-separated workflow identifiers to include. An empty entry is rejected. At most 200 entries. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--trigger ` | No | Comma-separated, lowercase trigger types or webhook provider IDs. Matching is exact and case-sensitive; unknown values select no runs. An empty entry is rejected. The sentinel `all` disables this filter, even when listed with other values. At most 100 entries. (space-separated, or @path / @- with one value per line; @@value for a literal leading @). |
| `--level ` | No | Severity level to include. Accepted values: `info`, `error`. |
| `--start-date ` | No | Only include runs started at or after this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--end-date ` | No | Only include runs started at or before this UTC ISO 8601 timestamp, e.g. `2026-08-06T00:00:00Z`. A date without a time, or a timestamp carrying a UTC offset instead of `Z`, is rejected, as is year `0000`, which names no storable instant. |
| `--min-duration-ms ` | No | Minimum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--max-duration-ms ` | No | Maximum total execution duration in milliseconds. Whole milliseconds from 0 to 2147483647; the stored duration is a 32-bit integer, so a fractional or out-of-range bound is rejected. |
| `--min-cost ` | No | Minimum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--max-cost ` | No | Maximum execution cost in USD, from 0 to 1000000. A run is never charged a negative amount, so a negative bound is rejected rather than treated as a filter that matches every run. |
| `--model ` | No | AI model used during execution. |
| `--details ` | No | Response detail level; full is requested by default to name each run’s workflow. Accepted values: `basic`, `full`. |
| `--include-trace-spans` | No | Include trace spans in JSON or YAML output (implies full detail). |
| `--include-final-output` | No | Include final output in JSON or YAML output (implies full detail). |
| `--limit