5 min read
Local development
You do not need to push to GitHub to test a spec change. This page covers how to validate, preview gate decisions, and generate artifacts locally before committing.
Validate your spec locally
The fastest way to check if your stateanchor.yaml is valid is to parse it before pushing. StateAnchor's validation rules are deterministic -- the same spec that passes locally will pass in CI.
Using the API
If you have an API key, you can call the validation endpoint directly:
curl -X POST https://stateanchor.dev/api/action/validate \
-H "Authorization: Bearer <your-action-token>" \
-H "Content-Type: application/json" \
-d '{
"config_content": "'"$(cat stateanchor.yaml)"'",
"repo": "your-org/your-repo",
"ref": "refs/heads/main",
"commit_sha": "local-dev"
}'A 200 response with "valid": true means the spec is structurally correct. A 422 with errors array tells you exactly what to fix.
Manual validation checklist
If you prefer to validate without an API call, check these rules. They are the same rules Stage A enforces:
serviceis a non-empty string, max 100 charsversionis a quoted string, max 20 charsserver.base_urlstarts withhttps://- At least one endpoint exists
- Every endpoint has
name,method, andpath methodis one of: GET, POST, PUT, PATCH, DELETEpathstarts with/- Endpoint names are unique
- At least one output is configured under
outputs - File size is under 128 KB
- No YAML anchors or aliases
Preview what the gate would do
The gate decision depends on the diff between your current spec and the previously synced IR. To preview without triggering a real sync:
- Make your spec change in
stateanchor.yaml. - Think about what changed: did you remove an endpoint? That is an ERR lane item -- the gate will block. Did you add an optional field? That is INFO -- the gate will pass. Did you add a required parameter? That is WARN -- the gate will block if your
warn_count_thresholdis 1 (the default). - Refer to the gate engine reference for the full lane classification table.
The gate is deterministic. If you know the previous IR and the current spec, you can predict the gate decision without calling the API.
Generate SDKs locally
SDK generation currently runs server-side as part of the sync pipeline. There is no local generation CLI yet. To generate locally:
- Push your spec change to a branch (not main).
- Trigger a manual sync from the dashboard -- the gate evaluates and artifacts generate without affecting your main branch's state.
- Download the generated artifacts from the project detail page.
A local generation CLI (stateanchor generate --local) is on the roadmap. Until then, branch-based syncs are the recommended workflow for previewing generated output.
Test the GitHub Action locally with act
act lets you run GitHub Actions workflows on your local machine. To test the StateAnchor action:
# Install act
brew install act # macOS
# or: curl -s https://raw.githubusercontent.com/nektos/act/master/install.sh | bash
# Create a .env file with your action token
echo "STATEANCHOR_TOKEN=sa_live_..." > .secrets
# Run the action
act push --secret-file .secretsNote: The OIDC token exchange (/api/action/oidc/exchange) requires a real GitHub OIDC JWT that act cannot generate. For local testing, use a pre-created API key instead of the OIDC flow.
Environment variables for local testing
| Variable | Required | Description |
|---|---|---|
STATEANCHOR_TOKEN | For API calls | API key from Settings → API Keys |
GITHUB_TOKEN | For act | Personal access token for repo access during local Action runs |
Common local setup issues
| Issue | Cause | Fix |
|---|---|---|
| YAML parse error on valid-looking file | Unquoted version number (version: 1.0 parsed as float) | Always quote: version: "1.0.0" |
| Validation passes locally but webhook sync fails | Local file has different line endings or encoding than the GitHub-hosted version | Ensure UTF-8 encoding with LF line endings |
422 invalid_config with no details | The config_content field was not the raw YAML string | Send the file contents as a string, not as a parsed object |
| act fails with OIDC error | act cannot mint GitHub OIDC tokens | Use a pre-created API key instead of the OIDC flow for local testing |
| Gate blocks a change you expected to pass | Your local spec differs from the last synced IR. The diff catches more than you expected. | Check the sync run detail for the full list of findings. You may have uncommitted changes from previous edits. |