Skip to content
vibstrVibstr home
Open Vibstr

External automation

The premise: your own Claude Code (or your CI/CD, or your custom script, or your future @vibstr/mcp-server install) drives Vibstr programmatically. Seven api_key-authenticated endpoints. BYO Anthropic key. We never mark up AI compute. You pay Anthropic, not us.

If Claude Code integration was the one curl in CLAUDE.md that auto-reports builds, this page is the other six curls that let your agent create plans, file items, list state, and post comments without a logged-in browser tab.

How it works

  1. Your project has an api_key in Vibstr (Settings → PROJECT → Connect Claude Code — the pane name is from the original Claude Code use case but the key works for any caller). Treat it like a password.
  2. Your code POSTs to one of seven endpoints with api_key in the request body.
  3. Vibstr validates the key, applies per-project rate limits, audit-logs the mutation, and executes.
  4. No user JWT needed. The api_key is the auth.

The api_key is project-scoped. A leak means an attacker can write to that one project — not your account, not your other projects, not your billing. Rotate from the same Settings pane that minted it.

Per-project rate limit at the time of writing: 60 calls per hour, sliding window. Tracked in vibelog_external_api_calls. Endpoints that invoke Anthropic (currently just vibstr-plan-create when derive_items: true) also charge against the project owner's daily AI cap unless the owner has BYO key set.

All endpoints return JSON. Errors come back as { error: { status, code, message, details? } }. Successful responses are flat objects (no envelope) so the happy path destructures in one line.

The 7 endpoints

Base URL: https://abtludluoynmwdfyvrse.supabase.co/functions/v1

1. vibstr-plan-create

Create a plan. Optionally derive items in the same call (one AI credit, returns the items along with the plan).

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-plan-create \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "title": "1.13.x AI first-responder sidebar",
    "body": "## Goal\nTurn AI into a per-item thinking partner...\n\n## Tasks\n- [ ] {type: change, area: drawer} Add item_context param\n- [ ] {type: change, area: drawer} Render sidebar shell",
    "status": "active",
    "target_build_id": null,
    "derive_items": true
  }'

Response:

{
  "plan": {
    "id": 14,
    "title": "1.13.x AI first-responder sidebar",
    "status": "active",
    "created_at": "2026-05-12T03:18:22.000Z"
  },
  "items": [
    { "id": 283, "item_number": 283, "type": "change", "area": "drawer", "description": "Add item_context param" },
    { "id": 284, "item_number": 284, "type": "change", "area": "drawer", "description": "Render sidebar shell" }
  ],
  "used_byo": false,
  "remaining": 27
}

Set derive_items: false (or omit) to just create the plan shell with no AI cost. The target_build_id accepts any build id in this project; pass null to leave it unlinked.

2. vibstr-item-create

Create a single item with the full field set. No AI cost.

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-create \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "type": "bug",
    "area": "auth",
    "description": "Sign-in form re-submits on every keystroke after first failure",
    "labels": ["regression", "priority"],
    "reported_build": "v1.12.2",
    "priority": true,
    "plan_id": null
  }'

Response:

{
  "item": { "id": 297, "item_number": 297, "status": "open", "type": "bug", "area": "auth" }
}

Fields supported: type, area, description, labels, reported_build, priority, assignee_id, due_at, estimate_value, estimate_unit, parent_item_id, plan_id. Type must be one of the project's categories. Area must be one of the project's areas (or null). Labels must reference names in the project's labels dictionary.

3. vibstr-item-bulk-create

Create up to 100 items in one shot. Partial-success reporting — failures don't roll back successes.

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-bulk-create \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "items": [
      { "type": "bug", "area": "auth", "description": "..." },
      { "type": "change", "area": "drawer", "description": "..." },
      { "type": "bug", "area": "?invalid?", "description": "..." }
    ]
  }'

Response:

{
  "successes": [
    { "id": 298, "item_number": 298 },
    { "id": 299, "item_number": 299 }
  ],
  "failures": [
    { "index": 2, "reason": "area '?invalid?' not in project areas" }
  ]
}

This is the workhorse for "I derived items from a spec, file them all now." Pair with vibstr-plan-create when you want them linked to a plan in one workflow, but separating create-plan from bulk-create-items lets you derive items locally with your own AI key first, then file them after editing.

4. vibstr-items-list

Read items with the full filter set + pagination.

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-items-list \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "filters": {
      "status": "open",
      "priority": true,
      "labels": ["regression"],
      "plan_id": 14
    },
    "sort": "created_at_desc",
    "limit": 50,
    "offset": 0
  }'

Response:

{
  "items": [ /* up to 50 items */ ],
  "total": 23,
  "has_more": false
}

Filter fields: status, type, area, priority, assignee_id, labels (array — items matching ANY of the listed labels), plan_id, build_id, reported_build, parent_item_id, is_template, due_before, due_after. Sort options: created_at_desc (default), created_at_asc, updated_at_desc, due_at_asc, item_number_asc.

5. vibstr-plans-list

Read plans with derived-item counts joined.

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-plans-list \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "include_archived": false,
    "limit": 20
  }'

Response:

{
  "plans": [
    {
      "id": 14,
      "title": "1.13.x AI first-responder sidebar",
      "status": "active",
      "derived_count": 8,
      "derived_done_count": 5,
      "target_build_id": 247,
      "updated_at": "2026-05-12T03:18:22.000Z"
    }
  ]
}

6. vibstr-build-create

Log a build + close items via the #NN parser. This is the same machinery the Claude Code integration calls, exposed for callers who want to log builds from outside a Claude Code run (CI/CD, custom scripts, the future @vibstr/mcp-server).

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-build-create \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "version": "1.12.3",
    "commit_hash": "a1b2c3d",
    "commit_message": "Phase 8 catchup — closes #279 #280 #281 #282 #287\n\nFive themes...",
    "prompt": "(optional original prompt)",
    "output": "(optional run summary)"
  }'

Response:

{
  "build": { "id": 247, "build_number": 245, "build_version": "1.12.3" },
  "closed_items": [279, 280, 281, 282, 287],
  "ai_matches": 0,
  "commit_matches": 5
}

The #NN parser is deterministic, charges zero AI credits, and runs first. If you want the AI semantic-match pass to run on top, pass output with enough text for the AI to chew on — same model and prompt as the Claude Code auto-ingest path. Pass output: null to skip the AI pass entirely.

7. vibstr-item-comment-create

Post a comment on an item. The substrate for Phase 10's Slack bridge ("a teammate's Slack reply syncs back as a Vibstr comment") and any future bot integration.

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-comment-create \
  -H "Content-Type: application/json" \
  -d '{
    "api_key": "YOUR_PROJECT_API_KEY",
    "item_number": 297,
    "body": "Reproduced on Safari 17.4 — keystroke handler re-binds the form action each render."
  }'

Response:

{
  "comment": { "id": 1842, "item_id": 297, "created_at": "2026-05-12T03:24:11.000Z" }
}

The author of the comment is recorded as the project owner. Future versions will accept an optional as_user_id for properly attributed bot bridges.

The full loop, walked through

A real example: derive items from spec.md via your Claude Code, file them via bulk-create, write code, commit with closes #NN, log a build that auto-closes them. End-to-end.

Step 1. Your Claude Code reads spec.md and proposes 8 items. You review them in the agent's reply. You approve.

Step 2. Agent files them in Vibstr:

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-bulk-create \
  -H "Content-Type: application/json" \
  -d @items.json

Response gives you item_number 312-319. Agent shows you the new items in Vibstr.

Step 3. Agent (optionally) creates a plan to wrap them:

curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-plan-create \
  -H "Content-Type: application/json" \
  -d '{ "api_key": "...", "title": "Sprint 14", "body": "...", "derive_items": false }'

Then a follow-up update to link items to the plan (out of scope for 1.12.3; for now, the in-app Plans UI is the link surface).

Step 4. Implement. Make commits:

git commit -m "Add user-pref persistence — closes #312 #313

Wires the localStorage round-trip and the cross-tab broadcast."

Step 5. Push. Your CLAUDE.md already has the auto-ingest curl wired, so the build reports itself. The #NN parser closes items 312 and 313. No further action needed.

Step 6. Repeat steps 4-5 until the plan's progress chip hits 8 / 8 done.

The plan, the items, the commits, the closing builds, and the changelog all live in the same context. You filed zero items by hand; you closed zero items by hand; you wrote zero status comments.

CLAUDE.md snippet

Paste this into YOUR project's CLAUDE.md so your Claude Code learns the integration:

## Vibstr external automation

This project tracks work in Vibstr at `https://vibstr.app`. The project's `api_key` is in your local env as `VIBSTR_API_KEY` (or substitute directly below).

When the user asks to file items, create a plan, or check what's open:

1. **Read state first** before proposing changes. Call `vibstr-items-list` with `{ status: 'open' }` to see what already exists; don't file duplicates.

2. **File items via bulk-create** for anything >1 item:
   ```bash
   curl -X POST https://abtludluoynmwdfyvrse.supabase.co/functions/v1/vibstr-item-bulk-create \
     -H "Content-Type: application/json" \
     -d '{"api_key": "$VIBSTR_API_KEY", "items": [...]}'
   ```

3. **Vibstr Plan Prompt** (use when asked to "create a Vibstr plan for X"):
   - Produce markdown with sections: Goal, Context, Tasks, Target build, Acceptance gate, Out of scope
   - Tasks must be `- [ ] {type: <type>, area: <area>} <description>`
   - `<type>` must be one of this project's categories (the user can tell you which)
   - `<area>` must be one of this project's areas (the user can tell you which)
   - Target build follows semver (e.g. `v1.13.0`)
   - Acceptance-gate items are smoke tests verifiable by hand
   - POST to `vibstr-plan-create` with `derive_items: true` to file the plan AND the items in one call

4. **Builds auto-report** via the curl already in CLAUDE.md after every commit + push. Commit messages should reference `closes #NN` for items the commit ships — the `#NN` parser closes them deterministically.

5. **All endpoints documented**: https://vibstr.app/how-we-ship/external-automation/

Tweak the wording to match your team's voice. The point is to teach your agent the four moves it actually has: read, file, plan, and let builds close themselves.

Path B: @vibstr/mcp-server (coming)

An out-of-band npm package. Install Vibstr as an MCP server in Claude Desktop, Cursor, Zed, or any MCP-capable client. No curl plumbing required — the seven Path A endpoints surface as MCP tools the model can call directly.

Ships in a separate repo on a separate timeline. The Path A endpoints documented here are the underlying transport; the MCP server is the friendly wrapper. Use either, or both — the api_key auth is the same.

Pricing context

We never mark up AI compute. You pay Anthropic, not us. The trial includes a $1 USD platform-AI budget (~100 typical Haiku calls) for the per-item AI sidebar; AI Assist requires a BYO Anthropic key from day 1. After the 14-day trial, all AI features require a BYO key regardless of tier (the Pro $2.99/seat tier covers workflow features — unlimited active projects + team members + Slack + Path A — not AI compute). For external automation — where your agent is calling the API on its own clock — set your Anthropic key under Settings → Account → AI provider. From then on, every AI-charging endpoint uses your key directly, bypasses the trial cap, and bills Anthropic, not Vibstr.

This is the boundary by design: pay us for the workflow; pay Anthropic for the compute. The best practices page has the full reasoning, including why the labels-as-stages position keeps the surface small enough to stay programmable.

The seven endpoints above are the surface. Everything else is composition.