skills/devin/SKILL.md
Dispatch coding tasks to Devin (Cognition's autonomous software engineer) via its v3 API, and embed Devin sessions in a TanStack Start + Cloudflare Workers app backend. Covers Bearer cog_ auth on the org-scoped v3 paths (/v3/organizations/{org_id}/sessions), create-session params (prompt, repos, max_acu_limit, structured_output_schema), the status lifecycle + polling for the PR result, sending messages to a live session, ACU cost control, and the dispatch-and-get-a-PR vs embed-in-app workflows. Use when the user wants to dispatch a task to Devin, run Devin from CLI/CI, get a PR from a prompt, embed an in-app coding agent, or mentions devin.ai / a cog_ key / an org- id.
npx skillsauth add RonanCodes/ronan-skills devinInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Drive Devin (Cognition's autonomous AI software engineer) over its API: hand a session a natural-language prompt (+ repos, attachments, a structured-output schema), poll until it finishes, and read back the PR. Two shapes: dispatch-and-get-a-PR (CLI/CI), and embed-in-app (your backend creates + steers sessions on behalf of users).
Target the v3 org-scoped API. A cog_ key and an org-... id are v3 artefacts. The /v1/sessions shape most blog posts show still works but is deprecated and gets no new features. v3 paths put the org id in the path: /v3/organizations/{org_id}/....
/ro:devin install # env check + a fetch helper
/ro:devin dispatch # create a session from a prompt (CLI / one-shot)
/ro:devin poll # poll a session to terminal + read the PR
/ro:devin embed # create + steer sessions from an app backend (Worker)
/ro:devin ops # API-ops cheat-sheet (curl)
~/.claude/.env (megathon block): DEVIN_API_KEY (cog_..., 90-day service admin), DEVIN_ORG_ID (org-...).max_acu_limit.https://api.devin.aiAuthorization: Bearer $DEVIN_API_KEY + Content-Type: application/jsonhttps://api.devin.ai/v3/organizations/{org_id}/... (the cog_ key is org/enterprise-scoped; enterprise scope can also hit org paths).401 bad key, 403 insufficient role, 404 bad path (e.g. missing {org_id}), 429 rate-limited (specific limits unpublished, back off).| Purpose | Method + path (v3) |
| --- | --- |
| Create session | POST /v3/organizations/{org_id}/sessions |
| Get session | GET /v3/organizations/{org_id}/sessions/{devin_id} |
| List sessions | GET /v3/organizations/{org_id}/sessions (cursor paginated) |
| Message a session | POST /v3/organizations/{org_id}/sessions/{devin_id}/messages |
| Terminate | DELETE /v3/organizations/{org_id}/sessions/{devin_id} |
| Enterprise consumption | GET /v3/enterprise/consumption/daily?time_after=...&time_before=... |
| Enterprise audit / members | GET /v3/enterprise/audit-logs, /v3/enterprise/members/users |
No official SDK is confirmed (docs show only curl + raw Python
requests). Treat anydevin-sdk/@cognition/devin-corepackage as unverified, build against REST. Plainfetchfrom a Worker works.
# ~/.claude/.env already has DEVIN_API_KEY + DEVIN_ORG_ID
echo "$DEVIN_API_KEY" | grep -q '^cog_' && echo "v3 key OK"
curl -X POST "https://api.devin.ai/v3/organizations/$DEVIN_ORG_ID/sessions" \
-H "Authorization: Bearer $DEVIN_API_KEY" -H "Content-Type: application/json" \
-d '{
"prompt": "Fix the login bug in issue #42 and open a PR",
"repos": ["<repo-id>"],
"max_acu_limit": 10,
"title": "Auth login fix"
}'
Response (200) includes session_id, url (app.devin.ai/sessions/...), status: "new", pull_requests[], structured_output, acus_consumed. Persist session_id.
Key create-session body params: prompt (required), repos[], max_acu_limit (budget circuit-breaker, set it), structured_output_schema (JSON Schema Draft 7, ≤64KB, self-contained, no external $ref), structured_output_required (force a final structured result), attachment_urls[], bypass_approval (skip safe-mode approvals, for unattended CI), tags[], title, secret_ids[] / session_secrets[] (private deps), knowledge_ids[], playbook_id, devin_mode (normal|fast|lite|ultra), create_as_user_id (attribute to an end user; needs ImpersonateOrgSessions).
status: new → claimed → running → exit (also error, suspended, resuming). Terminal = exit / error / suspended. status_detail adds nuance (working, waiting_for_user, waiting_for_approval, finished; and for suspended: out_of_credits, usage_limit_exceeded, etc., which look like "stopped" but mean "blocked on quota").
SID="devin-..."
while :; do
s=$(curl -s "https://api.devin.ai/v3/organizations/$DEVIN_ORG_ID/sessions/$SID" \
-H "Authorization: Bearer $DEVIN_API_KEY")
st=$(echo "$s" | jq -r .status)
echo "status=$st acus=$(echo "$s" | jq -r .acus_consumed)"
case "$st" in exit|error|suspended) break;; esac
sleep 10
done
echo "$s" | jq '{pr: .pull_requests, out: .structured_output}'
Read the result from the get-session response: pull_requests[].pr_url (+ pr_state), structured_output (if you passed a schema), acus_consumed (cost so far).
Hold two truths:
status == "exit"is the stop signal;status_detail == "finished"is an in-running"task done, awaiting more input" signal for interactive sessions. For fire-and-forget, break onexit.
cog_ key (never client-side). Create the session from your server (a Worker is fine), store session_id against your domain object (ticket/job/PR).create_as_user_id to attribute the session to the end user (shows in their list, counts to their usage).POST .../messages ({ "message": "..." }); reflect status + status_detail (waiting_for_user, waiting_for_approval) in your UI.session_id, reconcile via a poll loop, Worker Cron, a Durable Object alarm, or a queue.// src/lib/devin.ts — Workers-safe
const BASE = 'https://api.devin.ai/v3/organizations'
export async function createDevinSession(env: Env, prompt: string, repos: string[]) {
const res = await fetch(`${BASE}/${env.DEVIN_ORG_ID}/sessions`, {
method: 'POST',
headers: { Authorization: `Bearer ${env.DEVIN_API_KEY}`, 'Content-Type': 'application/json' },
body: JSON.stringify({ prompt, repos, max_acu_limit: 10 }),
})
if (!res.ok) throw new Error(`Devin create failed: ${res.status} ${await res.text()}`)
return res.json() as Promise<{ session_id: string; url: string; status: string }>
}
Two layers: (1) org-level: Devin's Git integration + the repo must be connected in org settings; (2) per-session: pass repos[] to scope, or name the repo/PR URL in the prompt. Private deps via secret_ids[] (pre-stored) or inline session_secrets[]. Attachments must be referenced in the prompt as a literal ATTACHMENT:"{url}" line (all caps, own line) or Devin ignores them.
max_acu_limit. Devin bills only while actively working.suspended sub-reasons (quota/billing), they aren't "done".cog_ key ⇒ v3 org-scoped paths with {org_id} in the path. Targeting v1, or dropping {org_id}, → 404. v3 idempotency flag is unverified; if you need exact-once create, dedupe yourself (store task → session_id).Devin is a third-party sibling to the local factory (/ro:ralph, /ro:planner-worker) and the remote Factory app: another way to dispatch a coding task and get a PR. Use it when you want Cognition's agent specifically; otherwise the factory loops run on the Max plan with no per-ACU cost.
DEVIN_API_KEY=cog_... # v3 service key, server only
DEVIN_ORG_ID=org-... # goes IN the path
Server-side only; never expose the cog_ key. Cap every session with max_acu_limit. Use bypass_approval only for deliberately-unattended CI. Review every PR Devin opens before merge (human-in-the-loop, same as the factory).
/ro:ralph, /ro:planner-worker, /ro:night-shifttesting
--- name: linear-pipeline description: The Fable orchestrator for a single dispatched Linear ticket. Holds almost no context itself; it receives `--issue <ID> --detached`, decides the stage sequence, and fans out a sub-agent per stage, passing forward only each stage's artifact (never re-derived, never inlined into its own context). Step zero, before any planning or stage routing, is a boundary triage against `canon/security-boundary.md` (#199): a match tags Ronan Connolly and stops the run, no
development
--- name: in-your-face description: Capture a chat-only answer into a durable artifact (markdown + HTML, PDF when cheap) and launch it automatically so the user cannot miss it. Use when user says "in your face", "don't let me lose this", "save that answer", "make that durable", or right after answering a substantive side question (a recipe, comparison, how-to, or generated prompt) that would otherwise die with the context. category: workflow argument-hint: [--no-open] [--vault <short>] [hint of
tools
One-shot headless OpenAI Codex CLI calls for background/admin AI tasks — summaries, classification, extraction, admin glue. The default engine for anything that runs AI constantly in the background (daemon-driven, per-event), because it bills the flat ChatGPT subscription instead of Claude usage or per-token API spend, and it keeps working while Claude is rate-limited. NEVER for coding — coding stays Claude. Use when a skill or daemon needs a cheap always-on AI call, when the user says "use codex", "ask codex", "codex as backup", or when building a background summarizer/classifier into a listener or loop. Reads auth from ~/.codex/auth.json (ChatGPT account, no API key).
research
Turn a warranty rejection, repair quote, or RMA email into a cited decision brief — legal read (NL/EU consumer law), is the part user-serviceable, live part and new-unit prices, repair-vs-DIY-vs-new economics, before-you-send-it checklist, deadlines. Use when the user pastes or screenshots a repair quote, warranty rejection, "not covered" email, onderzoekskosten fee, or asks "should I repair or replace this".