Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "sim",
"displayName": "Sim",
"version": "0.1.0",
"description": "Build, run, deploy, and operate Sim workflows, tables, and knowledge bases.",
"description": "Build, run, deploy, and sync Sim workflows; operate tables and knowledge bases.",
"author": {
"name": "Sim",
"url": "https://sim.ai"
Expand Down
4 changes: 2 additions & 2 deletions .codex-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "sim",
"version": "0.1.0",
"description": "Build, run, deploy, and operate Sim workflows, tables, and knowledge bases.",
"description": "Build, run, deploy, and sync Sim workflows; operate tables and knowledge bases.",
"author": {
"name": "Sim",
"url": "https://sim.ai"
Expand All @@ -14,7 +14,7 @@
"interface": {
"displayName": "Sim",
"shortDescription": "Build and operate Sim workflows",
"longDescription": "Use the Sim CLI to build, test, deploy, and debug workflows, plus manage tables and knowledge bases.",
"longDescription": "Use the Sim CLI to build, test, deploy, and debug workflows, import and sync workspaces, and manage tables and knowledge bases.",
"developerName": "Sim",
"category": "Productivity",
"capabilities": ["Read", "Write"],
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,4 @@ jobs:
test -f "$PACKAGE_DIR/package/.codex-plugin/plugin.json"
test -f "$PACKAGE_DIR/package/.claude-plugin/plugin.json"
test -f "$PACKAGE_DIR/package/skills/build-workflow/SKILL.md"
test -f "$PACKAGE_DIR/package/skills/sync-workspaces/SKILL.md"
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ Native plugin installs expose the skills under the `sim` namespace:
- `sim:build-workflow`
- `sim:run-workflow`
- `sim:deploy-workflow`
- `sim:sync-workspaces`
- `sim:table`
- `sim:knowledge-base`

Expand All @@ -83,7 +84,11 @@ Direct installs through `bunx sim-skills` install the selected skills without th
- `build-workflow` — discover blocks and author a draft graph with atomic workflow operations.
- `run-workflow` — test saved state, exercise triggers, resume from a block, and diagnose runs.
- `deploy-workflow` — publish and manage workflows as APIs, chats, or MCP tools.
- `sync-workspaces` — import portable workflows with bindings, fork workspaces, and preview, apply, and reconcile push/pull sync.
- `table` — design typed tables, load and query rows, import data, and run workflow groups.
- `knowledge-base` — ingest and index documents, configure connectors and tags, and verify retrieval.

The skills assume the `sim` CLI is installed and authenticated. They never store or print API keys.

Workspace sync guidance requires a CLI and server exposing the v2 import-preview and fork sync
commands. The skill checks command availability before changing resources.
1 change: 1 addition & 0 deletions scripts/validate-skills.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const expectedSkillNames = [
"knowledge-base",
"run-tool",
"run-workflow",
"sync-workspaces",
"table",
] as const;
const expectedPackageFiles = [
Expand Down
4 changes: 4 additions & 0 deletions skills/build-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ A request that is one action against one connected service needs no graph at all
directly with `sim tools execute` (see the `run-tool` skill). Build a workflow when the task needs
more than one call, branching, or a schedule.

For an existing workflow JSON import or environment promotion, use the `sync-workspaces` skill.
It preserves registered reference identities through preview and destination binding before graph IDs
are regenerated; do not recreate that flow with a sequence of graph edits.

## Establish context

- Use the profile the user named. If none was named, inspect configured profiles and current context;
Expand Down
38 changes: 16 additions & 22 deletions skills/deploy-workflow/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,28 +56,22 @@ Do not choose a surface from convenience. Ask when the intended caller does not

## Promoting across workspaces with fork sync

When a workflow moves between workspaces via a fork push, the sync has its own semantics; do not
reason about it as a copy.

- The push creates resources that are missing in the target and rebinds selector-bound references
to them. Do not pre-create tables in the target as a promotion prerequisite - pre-creating
defeats the mapping and leaves references pointing at the source.
- A table the push creates arrives holding the source's rows. Re-seed environment-specific values,
feature flags and configuration especially, immediately after the push, before anything reads
them. Where possible design flag rows so the source's value is also the safe value in every
target.
- Deployment state travels. A workflow deployed in the source is live in the target as soon as the
sync completes, and a schedule trigger starts firing there on its own - there is no separate
deploy step in the target. Before syncing anything scheduled or triggered, state plainly what
will start running where and when.
- Bind every resource through its selector and leave the manual id fields empty. The push remaps
selectors but carries a hardcoded manual id verbatim, silently pointing the promoted workflow at
the source workspace's resource - and a cross-workspace read succeeds, so no error surfaces.
- The push does not preserve a block's basic/advanced mode: some blocks arrive rebound and working,
others arrive carrying the source's manual id and broken, with nothing surfacing which is which.
"Works in the source workspace" is therefore never the completion condition. Verify each target
environment after promotion - run its workflows or audit its bindings - rather than inferring
health from the source.
Use the `sync-workspaces` skill for portable imports, workspace forks, and push/pull promotion.
That flow owns mapping discovery, preview fingerprints, stable request IDs, and operation polling.

- Sync transfers deployed source versions along a direct fork edge. Push sends current → other;
pull receives other → current, regardless of which workspace is the child.
- Select resource copies explicitly or map to existing authorized destination resources. Creating a
destination table is valid when mapping to it; sync does not automatically copy every missing
resource. Selected table copies include rows, so review environment-specific configuration.
- Import and fork create drafts. Sync deploys eligible admitted snapshots after background work;
inspect operation and deployment readiness before declaring the target live. Schedules and
webhooks can begin receiving traffic when their deployment activates.
- Registered selector references are remapped using canonical field modes. Manual values remain
literal; verify their intended destination instead of assuming they were rebound or that access
across workspaces is permitted.
- Review trigger URL changes and required configuration. A committed operation can still need
configuration or have failed follow-up work; an HTTP success alone does not establish readiness.

## Verify and report

Expand Down
182 changes: 182 additions & 0 deletions skills/sync-workspaces/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
---
name: sync-workspaces
description: Import portable Sim workflow JSON with destination bindings, create workspace forks, or push and pull deployed workflows along a fork edge through the sim CLI. Use for environment promotion, mapping and selector discovery, preview/apply retries, and operation readiness; not for authoring a new graph or ordinary deployment.
---

# Import and Sync Sim Workflows

Use a reviewed preview, explicit destination bindings, and a durable request ID. Verify the returned
operation; sync also requires target deployment readiness. Imports and forks complete as drafts.

## Establish scope

- Use the user's profile, API origin, and explicit workspace. Inspect context before selecting an
environment; never silently change accounts. Do not print or store authentication secrets.
- Check `sim workflows import-preview --help` or `sim workspaces push-preview --help` first. These
commands require a CLI and server with the v2 sync feature. If unavailable, report the missing
capability and required upgrade; do not substitute private browser endpoints.
- Fork creation requires source admin. Sync and mapping changes require admin on both workspaces.
Fork administration accepts personal API keys or OAuth, not workspace keys. Imports retain their
existing workflow-write permissions; credential binding still requires an eligible acting user.
- Inspect `workspaces fork-availability` before forking. Enterprise/self-hosting and workspace
creation policies still apply. OAuth scopes and permission groups can further restrict access.
- Use `--output json`. Single-resource CLI results are unwrapped objects; paged results contain
`data` and `nextCursor`. Raw v2 HTTP single-resource responses wrap the object in `data`.

## Choose the operation

| Intent | Commands | Result |
| --- | --- | --- |
| Import workflow JSON into an authorized destination | `workflows export`, `import-preview`, `import` | New undeployed draft with regenerated graph IDs |
| Create a child environment | `workspaces fork-preview`, `fork` | Child workspace with eligible deployed source workflows copied as drafts |
| Send current workspace changes to its direct fork neighbor | `workspaces push-preview`, `push` | Replace eligible target workflows from deployed source versions |
| Receive changes from a direct fork neighbor | `workspaces pull-preview`, `pull` | Same sync with the other workspace as source |

Push always means current → other; pull means other → current, on either side of the parent/child
edge. Inspect `workspaces lineage` and `children`; do not infer direction from the word child.
Arbitrary workspace transfers and draft sync are outside this flow.

## Portable import

Export with reference metadata and preview in the destination:

```sh
sim --profile source --workspace "$SOURCE_WORKSPACE" --output json \
workflows export "$WORKFLOW_ID" --include-references > workflow.json
sim --profile destination --workspace "$DESTINATION_WORKSPACE" --output json \
workflows import-preview --workflow @workflow.json > preview.json
```

Default export remains sanitized without reference metadata. `--include-references` records
registered non-secret source IDs and every block/field occurrence alongside the sanitized graph.
Treat imported IDs and provenance as untrusted labels, not authorization to read a source workspace.

Read `unresolvedBindings`, `unresolvedConfiguration`, and target-discovery instructions. Discover
destination credentials, tables, files, sandboxes, and other resources through their existing CLI
commands. Candidate matches are suggestions; verify provider, resource type, and parent resource.
Missing OAuth connections can require human provider authorization; report that requirement rather
than inventing a connection or substituting a different user's credential.

Import resource mappings use `kind`, `sourceId`, and `targetId`:

```json
[
{ "kind": "credential", "sourceId": "source-connection", "targetId": "destination-connection" },
{ "kind": "sandbox", "sourceId": "source-sandbox", "targetId": "destination-sandbox" }
]
```

For older exports, `--bindings` addresses a specific registered source occurrence. For example:

```json
[
{ "kind": "sandbox", "blockId": "source-function", "subBlockKey": "sandboxId", "targetId": "destination-sandbox" }
]
```

`valuePath` defaults to `[]` and `encoding` to `scalar`. Use preview/manifest occurrence paths for
nested or multi-value fields; do not guess them. Conflicting mappings and bindings are rejected.
Import dependent values use `{blockId, subBlockKey, value}`, such as
`{"blockId":"source-agent","subBlockKey":"tools[0].folder","value":"destination-label"}`.
Keep the original source IDs and tool indexes until apply returns `idMap`.

Save the exact input files and a client-generated stable request ID before applying:

```sh
sim --profile destination --workspace "$DESTINATION_WORKSPACE" --output json \
workflows import-preview --workflow @workflow.json \
--mappings @mappings.json --dependent-values @values.json > preview.json
sim --profile destination --workspace "$DESTINATION_WORKSPACE" --output json \
workflows import --workflow @workflow.json \
--mappings @mappings.json --dependent-values @values.json \
--preview-fingerprint "$(jq -r .previewFingerprint preview.json)" \
--request-id "$REQUEST_ID" --wait
```

Include the same name, folder, bindings, and other choices on both requests. JSON flags accept
`@file` and `@-` for stdin; only one input can consume stdin. Mapped import creates nothing while
required bindings remain unresolved. It commits the draft, graph, variables, inline custom tools,
and receipt together. Mappings are local to this request; importing does not create a workflow
correspondence on a fork edge. Plain imports without mapping options
retain legacy behavior; use preview/apply for automation that needs binding guarantees.

## Fork and sync choices

Inspect `workspaces fork-resources`, then preview with explicit copy selections. A fork's
`--copy` selects source resources; sync uses `--copy-resources`. Consult command help for each
shape: fork file selections are workspace file IDs, while sync file selections are storage keys.
Copying is opt-in. Selected table copies include rows and selected knowledge bases include content;
account for environment-specific configuration before enabling the destination.

Existing destination resources can be mapped instead of copied. Sync mapping entries use
`{resourceType, sourceId, targetId}`; they differ from import's `kind` entries. In particular,
portable `credential` corresponds to sync `oauth_credential` or `service_account_credential`.
Verify the actual credential type through resource discovery. A mapping inspection row also has
`id`; project it before reuse with `jq '.data | map({resourceType,sourceId,targetId})'`. Follow all
pages first. Newly referenced resources may have no persisted mapping row yet.

Previews evaluate inline mappings without saving them. Accepted inline sync mappings persist on
the canonical edge in the same transaction as sync; a refusal before commit saves neither.
Dependent sync values use `{sourceWorkflowId, sourceBlockId, subBlockKey, value}`. Never use fresh
target IDs from preview as override identities. Omitted overrides reuse saved sync choices; values
that exist only in a target draft are not saved choices. A supplied `dependentValues` array replaces
the saved choices for affected workflows; `[]` clears them. Start from every preview configuration
field and its `currentValue`, edit the intended selections, and submit the complete set of choices
to retain, rather than only the changed fields.

For every dependent field, use its returned selector key, context, and `discoveryWorkspaceId`:

```sh
sim --profile destination --workspace "$DISCOVERY_WORKSPACE" --output json \
selectors list --selector-key gmail.labels \
--context '{"oauthCredential":"destination-connection"}'
```

The discovery workspace is the source when the parent resource will be copied, and the destination
when using an existing mapping. Use a profile authorized for that workspace. Follow `nextCursor`,
inspect truncation metadata, and use `selectors get --help` to verify a particular option. A clipped
list does not prove an option is absent. Resolve dependent chains in order, re-previewing with the
new choices. Use exactly the returned context for MCP tool discovery as well.

```sh
sim --profile destination --workspace "$DESTINATION_WORKSPACE" --output json \
workspaces pull-preview --other-workspace-id "$SOURCE_WORKSPACE" \
--mappings @sync-mappings.json --dependent-values @sync-values.json > sync-preview.json
sim --profile destination --workspace "$DESTINATION_WORKSPACE" --output json \
workspaces pull --other-workspace-id "$SOURCE_WORKSPACE" \
--mappings @sync-mappings.json --dependent-values @sync-values.json \
--preview-fingerprint "$(jq -r .previewFingerprint sync-preview.json)" \
--request-id "$SYNC_REQUEST_ID" --yes --wait
```

Use `--yes` within the user's authorized destructive sync scope. Review replacements, exclusions,
resource selections, required configuration, and trigger URL changes before apply. If preview offers
trigger adoption choices, use its stable source workflow/block identities and offered paths; never
invent a path. Sync `ready` indicates commit readiness, not a live deployment. Scheduled or webhook
workflows can begin receiving traffic once admitted deployments activate.

## Completion and recovery

- Save `operationId`, `requestId`, and the receipt's `workspaceId`. Import receipts belong to the
destination; fork and push/pull receipts belong to the workspace on which the command was invoked.
Poll that scope even when the created child or sync target is a different workspace.
- `applied: true` means the transaction committed, including when later copy/deployment work fails.
Use `workspaces operations get <operationId>` or `wait <operationId> --wait-timeout 300` to refresh
readiness. Operation lists are stored snapshots; filter with `--request-id` to recover a lost ID.
- Require terminal readiness and inspect issues/trigger URL changes before declaring the environment
ready. Completed-with-warnings exits 0 but still needs review. Required configuration exits 3,
failed completion exits 1, and wait timeout exits 4. Timeout diagnostics retain reconciliation IDs.
- After an uncertain response, retry identical inputs with the original request ID, or poll the
existing operation. Never retry an uncertain mutation with a fresh ID. Same ID with changed input
returns 409. Authorize access again before reconciliation; a stored receipt is not an auth bypass.
- A stale preview with no committed operation needs a fresh preview and a new request ID for the
revised inputs. Resolve structured 409 issues; do not loop blindly or remove safety flags.
- Sync transfers deployed source versions. Merely undeploying a source does not archive its target;
deleting a mapped source can. Respect explicit sync exclusions.
- Rollback restores the latest target sync from prior deployed versions. It does not recover
arbitrary prior drafts or remove every copied resource. Use rollback/unlink/exclusion controls
only for the requested recovery scope and verify their result.

For a new imported draft, use the `run-workflow` skill to test it and `deploy-workflow` only when
publication is requested. Never copy secret values, signed URLs, arbitrary headers, or opaque
credential payloads between environments to make a binding pass.
Loading