Following system theme

#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

  • bash 4 or later
  • curl
  • jq
  • Optional: openssl — the auto-minted idempotency key falls back to sha256sum or shasum when openssl is 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 clone and .zip methods): SKILL.md lives at skills/scribo/SKILL.md in the repo, not at the repo root. Always place the inner skills/scribo directory at the destination so SKILL.md lands at …/scribo/SKILL.md. Cloning the repo root straight into …/skills/scribo would 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:

  1. Download scribo-skill.zip from the latest GitHub release.
  2. Upload it:
    • Claude.ai / Claude Desktop / Cowork — open Settings → Customize → Skills and click Upload skill.
    • ChatGPTNew skill → Upload from your computer (see Skills in ChatGPT); ChatGPT scans the upload before it goes live.
  3. 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):

  1. 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 to sender.contact_email), prints status: "verification_required" with a challenge_id, and exits with code 10.
  2. The assistant asks you for the 6-digit code; you paste it from the email.
  3. It redeems the code with skills/scribo/scripts/redeem_verification.sh <challenge_id> <code>, which returns a short-lived verification_token. A wrong, expired, or revoked code returns verification_invalid and exits 11.
  4. It re-runs the create with the token, supplied via the SCRIBO_VERIFICATION_TOKEN env var (preferred — keeps it out of the process list and shell history) or the --verification-token flag. The script sends it as the X-Email-Verification-Token header.

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:

  1. 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.
  2. Resolves the tax category code with the user (it never infers). The reference at /docs/tax-codes is loaded if the user is unsure.
  3. Builds the JSON payload and pipes it into skills/scribo/scripts/create_invoice.sh.
  4. 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 a verification_token, and re-runs the create with the token. See Email verification above.
  5. Hands back the result — the durable download_url (re-fetchable any time), the resolved format, and, for XRechnung, the preview_url plus the manual-upload submission hint. Scribo also emails the invoice notification (summary + download link) to the sender.
  6. 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) include retry_after_seconds / reset_at; for tenant_soft_blocked, wait until details.auto_lift_at before retrying. The reference at /docs/troubleshooting covers 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-codes for 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/mcp for 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.