#Scribo Skill for Claude, ChatGPT & Codex
The Scribo skill lets any Claude-, ChatGPT-, or Codex-powered assistant generate EN 16931-compliant e-invoices through the public Scribo API. It ships as plain bash + curl + jq helper scripts — no MCP server, no npm install, no Node.js.
One SKILL.md package — skills/scribo/SKILL.md in github.com/causa-prima-ai/scribo-skill — three install methods. Pick the row that matches how you run Claude, ChatGPT, or Codex:
| Install method | Surfaces it covers | Command |
|---|---|---|
/plugin install (Claude Code marketplace — live) |
Claude Code (CLI) | /plugin marketplace add causa-prima-ai/scribo-skill then /plugin install scribo-skill@scribo-skill (or /plugin install scribo-skill) |
git clone (layout-correct clone-then-copy) |
Claude Code (manual, project or user-global), OpenAI Codex CLI, Cowork repo-baked | git clone https://github.com/causa-prima-ai/scribo-skill /tmp/scribo-skill then cp -r /tmp/scribo-skill/skills/scribo <dest>/scribo — where <dest> is .claude/skills (project / Cowork), ~/.claude/skills (user-global), or ~/.codex/skills (Codex CLI) |
.zip upload (latest GitHub release) |
Claude.ai chat, Claude Desktop, Cowork, ChatGPT | Download scribo-skill.zip from the latest release, then Settings → Customize → Skills → Upload skill (Claude) or New skill → Upload from your computer (ChatGPT) |
#Requirements
bash4 or latercurljq- Optional:
openssl— the auto-minted idempotency key falls back tosha256sumorshasumwhenopensslis missing.
#Install
Three install methods cover every surface. Pick the one that matches how you run your assistant — the matrix above maps methods to surfaces.
Layout note (for the
git cloneand.zipmethods):SKILL.mdlives atskills/scribo/SKILL.mdin the repo, not at the repo root. Always place the innerskills/scribodirectory at the destination soSKILL.mdlands at…/scribo/SKILL.md. Cloning the repo root straight into…/skills/scribowould bury it at…/scribo/skills/scribo/SKILL.md, where it is never discovered.
#Method 1 — /plugin install (Claude Code)
The repo ships as a single-plugin Claude Code marketplace, so this is the fastest path on the CLI:
/plugin marketplace add causa-prima-ai/scribo-skill
/plugin install scribo-skill@scribo-skill
# or, when the name is unambiguous across your installed marketplaces:
/plugin install scribo-skill
The skill activates as /scribo-skill:scribo and triggers automatically when you ask Claude to draft or generate an invoice. Installed helper scripts live under ~/.claude/plugins/scribo-skill/skills/scribo/scripts/.
#Method 2 — git clone (Claude Code manual, Codex CLI, Cowork repo-baked)
Use this for OpenAI Codex CLI (which doesn't read the Claude plugin format), a manual Claude Code install, or to bake the skill into a repo for a whole Cowork team. Clone once, then copy the inner skills/scribo to the destination for your surface:
git clone https://github.com/causa-prima-ai/scribo-skill /tmp/scribo-skill
# OpenAI Codex CLI
cp -r /tmp/scribo-skill/skills/scribo ~/.codex/skills/scribo
# Claude Code — project (also the Cowork repo-baked path)
cp -r /tmp/scribo-skill/skills/scribo .claude/skills/scribo
# Claude Code — user-global
cp -r /tmp/scribo-skill/skills/scribo ~/.claude/skills/scribo
Claude Code and Codex CLI auto-discover any directory under their skills folder whose SKILL.md has frontmatter; restart your session afterward. For a team-wide Cowork install, commit the copied .claude/skills/scribo directory so every session that opens the repo picks it up.
#Method 3 — .zip upload (Claude.ai chat, Claude Desktop, Cowork, ChatGPT)
One upload on the account covers Claude.ai web chat, Claude Desktop, and Cowork sessions across any repo — and ChatGPT supports the same skill .zip:
- Download
scribo-skill.zipfrom the latest GitHub release. - Upload it:
- Claude.ai / Claude Desktop / Cowork — open Settings → Customize → Skills and click Upload skill.
- ChatGPT — New skill → Upload from your computer (see Skills in ChatGPT); ChatGPT scans the upload before it goes live.
- The skill is enabled for new chats / sessions on that account.
The release zip is a single top-level scribo/ folder (scribo/SKILL.md at its root) — exactly the shape both Claude's and ChatGPT's skill uploaders expect.
#Verify
# Method 1 (/plugin install) — installed plugin path
~/.claude/plugins/scribo-skill/skills/scribo/scripts/list_jurisdictions.sh | jq '.[].jurisdiction'
# Method 2 (git clone) — the path you copied to, e.g.
~/.codex/skills/scribo/scripts/list_jurisdictions.sh | jq '.[].jurisdiction'
# Method 3 (.zip upload) — verify in chat
# Ask: "list the jurisdictions Scribo supports"
Expect a JSON array of supported country codes (or an in-chat list of the same).
#What's in the skill
.claude-plugin/
marketplace.json # marketplace entry (one plugin: scribo-skill)
plugin.json # plugin manifest (name, version, description, …)
scripts/
release-zip.sh # builds the distributable skill zip (CI)
skills/scribo/
SKILL.md # prompt fragment Claude/Codex loads on invoice intent
scripts/
_common.sh # shared bash helpers (auto-mint idempotency key)
create_invoice.sh # POST /api/v1/invoices (takes --verification-token)
request_verification.sh # POST /api/v1/scribo/email-verifications
redeem_verification.sh # POST /api/v1/scribo/email-verifications/:id/redeem
get_invoice.sh # GET /api/v1/invoices/:id
download_invoice.sh # GET /api/v1/invoices/:id/download
list_jurisdictions.sh # GET /api/v1/jurisdictions
references/
jurisdictions.md # format priority chain
tax-codes.md # EN 16931 S/Z/E/AE/K/G/O picker guidance
troubleshooting.md # verification, rate limits, Turnstile, idempotency, validator errors
tests/ # mock-server.py + smoke.sh (CI only; excluded from the release zip)
#Email verification (first invoice per sender)
Before Scribo generates the first invoice for a sender email, it proves the caller owns that address (Scribo-03). The assistant orchestrates this — there's no separate signup, and the verification email is expected (it comes from verify@scribo.causaprima.ai, not a phishing attempt):
- The assistant builds the payload and runs
skills/scribo/scripts/create_invoice.sh. With no verification token the script does not create the invoice — it requests a challenge (Scribo emails a 6-digit code tosender.contact_email), printsstatus: "verification_required"with achallenge_id, and exits with code10. - The assistant asks you for the 6-digit code; you paste it from the email.
- It redeems the code with
skills/scribo/scripts/redeem_verification.sh <challenge_id> <code>, which returns a short-livedverification_token. A wrong, expired, or revoked code returnsverification_invalidand exits11. - It re-runs the create with the token, supplied via the
SCRIBO_VERIFICATION_TOKENenv var (preferred — keeps it out of the process list and shell history) or the--verification-tokenflag. The script sends it as theX-Email-Verification-Tokenheader.
The code expires in 15 minutes; one redeemed token covers ~30 minutes of invoices for the same sender, so you aren't re-prompted on every invoice. Verification sends are rate-limited (1 per 30 s and 5 per hour per email).
The headless skill is exempt from CAPTCHA — Turnstile gates only the web chat's first LLM call at
scribo.causaprima.ai.
#How the agent uses it
When the user says "draft me an invoice" or anything matching the trigger phrases in SKILL.md, the assistant:
- Collects seven required fields in a brief conversational pass — sender business name, sender address, sender tax/VAT ID (plus sender contact email), recipient name, recipient address, recipient email (accounts-payable / billing), line items + currency. Optional extras: jurisdiction override, idempotency key.
- Resolves the tax category code with the user (it never infers). The reference at
/docs/tax-codesis loaded if the user is unsure. - Builds the JSON payload and pipes it into
skills/scribo/scripts/create_invoice.sh. - Verifies email ownership on the first invoice for a new sender — the tokenless create returns
verification_required(exit 10); the assistant collects the 6-digit code, redeems it for averification_token, and re-runs the create with the token. See Email verification above. - Hands back the result — the durable
download_url(re-fetchable any time), the resolvedformat, and, for XRechnung, thepreview_urlplus the manual-uploadsubmissionhint. Scribo also emails the invoice notification (summary + download link) to the sender. - Surfaces structured errors — on a 4xx/5xx the assistant reads
error.code,error.message, and retry metadata from the response envelope. Temporary cases (rate_limited,tenant_invoice_quota_exceeded,tenant_soft_blocked) includeretry_after_seconds/reset_at; fortenant_soft_blocked, wait untildetails.auto_lift_atbefore retrying. The reference at/docs/troubleshootingcovers verification errors, rate limits, soft blocks, idempotency mismatch, and validator failures.
#Helper scripts
#skills/scribo/scripts/create_invoice.sh — POST /api/v1/invoices
Reads a JSON payload on stdin (or via --from FILE). Auto-mints Idempotency-Key from a SHA-256 of the payload so accidental retries don't double-bill.
Pass the email verification token via the SCRIBO_VERIFICATION_TOKEN env var (preferred — keeps it out of the process list and shell history) or the --verification-token <token> flag; it is sent as the X-Email-Verification-Token header. Without a token the script requests a verification challenge and prints status: "verification_required" (exit 10) instead of creating the invoice — see Email verification above.
SCRIBO_VERIFICATION_TOKEN=<token> cat <<'JSON' | skills/scribo/scripts/create_invoice.sh
{
"sender": {
"legal_name": "Example GmbH",
"country_code": "DE",
"address_line1": "Example Allee 1",
"postcode": "10115",
"city": "Berlin",
"tax_id": "DE123456788",
"contact_email": "billing@example.com"
},
"recipient": {
"legal_name": "Acme GmbH",
"country_code": "DE",
"address_line1": "Hauptstrasse 1",
"postcode": "10117",
"city": "Berlin",
"tax_id": "DE987654321",
"contact_email": "ap@acme.example"
},
"line_items": [
{
"description": "Consulting, 3 days",
"quantity": "3",
"unit_code": "DAY",
"unit_price": "1200.00",
"tax_rate": "19",
"tax_category_code": "S"
}
],
"currency": "EUR"
}
JSON
Returns the InvoiceRecord envelope — see /docs/api#post-apiv1invoices-generate-an-invoice.
Exit codes: 0 ok, 10 verification required, 64 invalid input / other 4xx, 65 validator failed, 70 server error, 75 rate-limited. (Skill-script convention — the npm CLI signals the same verification-required state with 75 EX_TEMPFAIL under --no-prompt, since it follows sysexits.)
#skills/scribo/scripts/request_verification.sh EMAIL — POST /api/v1/scribo/email-verifications
Requests an email-ownership challenge; Scribo emails a magic link and a 6-digit code to EMAIL. Returns { challenge_id, expires_at, next_request_allowed_at }. You normally don't call this directly — create_invoice.sh requests the challenge for you when no token is present.
#skills/scribo/scripts/redeem_verification.sh CHALLENGE_ID CODE — POST /api/v1/scribo/email-verifications/:id/redeem
Exchanges the 6-digit code the user copied from the email for a verification_token (reusable ~30 min). All failures (wrong, expired, or revoked code) return a uniform verification_invalid and exit 11. Other exit codes: 64 bad usage, 70 server error, 75 rate-limited.
#skills/scribo/scripts/get_invoice.sh INVOICE_ID — GET /api/v1/invoices/:id
Fetch metadata + a fresh signed download URL.
#skills/scribo/scripts/download_invoice.sh INVOICE_ID [-o FILE] — GET /api/v1/invoices/:id/download
Streams the bytes to -o FILE (default invoice-<id>.pdf).
#skills/scribo/scripts/list_jurisdictions.sh — GET /api/v1/jurisdictions
Returns the per-jurisdiction format matrix.
#Configuration
| Env var | Default | Purpose |
|---|---|---|
SCRIBO_BASE_URL |
https://scribo.causaprima.ai |
Override for staging or an alternate Scribo deployment. |
SCRIBO_API_KEY |
(unset) | Forward-compat partner key; not required at v1. |
SCRIBO_VERIFICATION_TOKEN |
(unset) | Email-ownership token from redeem_verification.sh; sent as the X-Email-Verification-Token header. Reusable ~30 min. |
SCRIBO_LOCALE |
(unset → English) | BCP-47 tag (e.g. de-DE) — language of the verification, confirmation-page, and invoice-ready emails. Export before create_invoice.sh / request_verification.sh. |
#SKILL.md frontmatter
The agent finds this skill via standard SKILL.md frontmatter — same shape that Anthropic's skills repository and OpenAI's Codex CLI both consume (Claude Code's marketplace also reads the plugin manifest at .claude-plugin/plugin.json):
---
name: scribo
description: Generate EN 16931-compliant e-invoices (XRechnung, ZUGFeRD) or a clean US plain PDF via the public Scribo HTTP API. Factur-X, Peppol BIS UBL, and Spanish Facturae are Phase 2 — coming soon. No signup; the sender's email is the login.
allowed-tools:
- Read
- Bash
---
#When NOT to use the skill
- Reading existing invoices — OCR / extracting structured data from a PDF is a different tool.
- Tax advice — Scribo never infers the tax category code; the user picks one per EN 16931. See
/docs/tax-codesfor guidance only. - Delivery to the recipient — the skill returns a durable download URL; the user delivers the invoice themselves.
#See also
- MCP server — hosted at
scribo.causaprima.ai/mcpfor Claude Desktop, Cursor, Cline, ChatGPT App, OpenAI Codex CLI, and other MCP clients. - CLI — npm CLI with the same flag surface.
- API — the underlying HTTP contract.
- Jurisdictions — format priority chain.
- Tax category codes — EN 16931 S/Z/E/AE/K/G/O picker.
- Troubleshooting — error envelope and recovery.
#License
© Causa Prima Germany GmbH. All rights reserved. The skill is
distributed for use against the public Scribo API; the scribo-skill
repository is
proprietary (UNLICENSED). The other Scribo client surfaces (CLI, MCP
server) are likewise proprietary.