3 min read
Getting Started in 5 Minutes
StateAnchor is git-native API contract enforcement. You commit a stateanchor.yaml spec to Git. On every push, StateAnchor parses it, builds a canonical IR, diffs against the previous state, evaluates breaking changes, and regenerates SDKs and MCP servers. This guide gets your first sync running.
StateAnchor is in self-serve beta. Sign up at stateanchor.devand you’re in immediately — no waitlist, no invite code. Beta access is granted automatically on first signup via the Clerk user.created webhook.
Prerequisites
| Requirement | Details |
|---|---|
| GitHub repo | Public or private. Must have push access. |
| stateanchor.yaml | Spec file in repo root (or custom path) |
| GitHub Actions | Enabled on the repo |
| StateAnchor account | Sign up at stateanchor.dev — beta access is granted automatically on signup. No invite code needed. |
How the first sync works
When you push a commit that includes stateanchor.yaml, the GitHub Action fires. It requests an OIDC token from GitHub, exchanges it with StateAnchor for a short-lived action token, sends your spec for validation, then calls the gate-check endpoint. If the gate proceeds, artifacts are generated.
New projects start in observe mode -- the gate evaluates every push and classifies changes (ERR / WARN / INFO), but it never blocks your CI. You receive advisory PR comments and the full gate verdict in the dashboard. Enforcement starts when you explicitly set mode: enforce in your workflow.
OOD cold-start period:For the first ~20 syncs, StateAnchor’s out-of-distribution detector is still building its baseline for your spec’s structure. During this period, unusual spec shapes may be flagged for human review rather than flowing through the automated gate. This is intentional — the detector needs a baseline before it can reliably classify novelty. After ~20 syncs the cold-start period ends and the gate runs fully autonomously.
See all 33 gate kinds (ERR / WARN / INFO) for the complete reference of what the gate classifies.
Step 1: Add the GitHub Action
Create .github/workflows/stateanchor-sync.yml in your repository:
name: StateAnchor Sync
on:
push:
branches: [main]
pull_request:
branches: [main]
permissions:
id-token: write
contents: read
jobs:
stateanchor-sync:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: stateanchor-hq/sync-action@v1
with:
mode: observe
config-path: stateanchor.yamlThe id-token: write permission is required for OIDC authentication. Without it, the Action falls back to local validation only.
The default mode is observe— advisory only, never blocks CI. Change to mode: enforceonce you’ve reviewed a few gate verdicts and are confident the spec reflects your contract intent.
Step 2: Create stateanchor.yaml
Add this file to your repo root, or try the YAML generator to scaffold it from a plain-English description.
service: payments-api
version: "1.0.0"
server:
base_url: https://api.acme.com/v1
endpoints:
- name: createCharge
method: POST
path: /charges
description: Create a new charge
auth: bearer
- name: getCharge
method: GET
path: /charges/{id}
description: Get charge by ID
auth: bearer
- name: listCharges
method: GET
path: /charges
description: List all charges
auth: bearer
outputs:
languages:
- typescript
- python
mcp: trueStep 3: Push and verify
Commit both files and push to main.
git add .github/workflows/stateanchor-sync.yml stateanchor.yaml
git commit -m "feat: add StateAnchor sync"
git push origin mainCheck the Actions tab in GitHub. You should see the StateAnchor Sync workflow running. The summary will show validation result and gate decision.
| Field | Expected value |
|---|---|
| Validation | PASS |
| Gate action | proceed |
| Gate score | 0 |
| Mode | sync |
Step 4: View artifacts
After the sync completes, open your project in StateAnchor. The latest sync run shows generated artifacts: TypeScript SDK, Python SDK, and MCP server. Each artifact is versioned and tied to the exact commit SHA.
The dashboard — 3-panel console
On desktop (viewport ≥ 900px), the StateAnchor dashboard renders as a 3-panel console:
- Left sidebar— your project list with a status dot per project (green for healthy, amber for drift detected, red for gate errors). Clicking a project selects it.
- Middle panel— the sync timeline for the selected project. Each row shows the lane badge (ERR / WARN / INFO / PASS), the commit SHA, the trigger type, a brief change summary, the duration, and a relative timestamp. Clicking a row selects the run.
- Right panel— detail for the selected sync run. Shows the lane badge, commit, headline, the first triggering change path, a 2×2 stat grid (trigger / duration / policy / artifacts), the breaking·degradations·additive change summary, and a “View full report” button that opens the full run view at
/project/{id}?run={runId}.
A stats bar pinned below the three panels shows total syncs, last-7-days sync count, gate blocks, and artifacts generated.
Mobile (< 900px) collapses the three panels to the flat-list layout: stats grid at top, repo list with gate badges, and recent gate activity. All interactions work on mobile; the 3-panel view is a desktop-only affordance.
Troubleshooting
Action shows SOFT-PASS instead of PASS
SOFT-PASS is the Action result when remote validation or the gate check could not complete and the configured outage policy is fail-open. The Action runs local YAML schema validation only and emits soft-pass instead of the usual pass. Common causes:
- OIDC token unavailable— usually a fork PR or a workflow missing
id-token: writepermission. - Remote timeout— StateAnchor API unreachable within
timeout-ms(default 15 000 ms).
SOFT-PASS is not a gate decision — the categorical lane cannot be determined because the remote evaluation never ran. Treat it as “proceed with caution”: your spec parsed, but the breaking- change diff did not run. Review the sync manually before deploying.
Gate returned block
Breaking change detected. Check diff_summary in the action output.
No sync run created
Repo may not be connected in the StateAnchor dashboard.
YAML parse error
Check indentation. Use 2-space indent, no tabs.
Token exchange failed
Check that api-base-url is correct and the repo is connected.