r3: Skill for Claude Code

.claude/skills/api-surface/SKILL.md

api-surface is a skill for Claude Code from hyperlogue/r3. It costs 110 tokens per session (6,982 once invoked), scanned A, original, MIT.

A design guide describing r3's HTTP/JSON API and command-line interface. An API is the set of routes and commands that other programs use to interact with it.

In plain words
What is it for?
Use it when adding or changing routes, review operations, Git browsing, file rendering, command-line usage, or shared request and response types.
Why use it?
It keeps the browser, command-line tool, and AI agent aligned when data formats or behavior change.

Skill for Claude Code

Written for Claude Code: installed under .claude/. Also seen: mentions subagents; mentions Claude Code; mentions Codex.

This is hyperlogue/r3's own configuration. It tells Claude Code how to work on r3 itself, so it is not a mod to install elsewhere. Copy it as a starting point and replace the rules that are about this project. Everything r3 configures →

Reuse

Borrowing it

Nothing to install: this file belongs to hyperlogue/r3. Take a copy, put it at the same path in your own repository, and replace the rules that are about this project with yours.

Copy the file
curl -O https://raw.githubusercontent.com/hyperlogue/r3/main/.claude/skills/api-surface/SKILL.md
Clone the repo
git clone --depth 1 https://github.com/hyperlogue/r3

Made for: Claude Code.

Wrote this? Show the measurements

A badge with what this costs and how it scanned, read live from this page, so it follows the numbers instead of freezing them. Markdown for a README, HTML for a documentation site or a project page.

agentmods badge for api-surface

README.md
[![agentmods](https://agentmods.dev/badge/skills/hyperlogue/r3/api-surface/github.svg)](https://agentmods.dev/skills/hyperlogue/r3/api-surface)
Your own site
<a href="https://agentmods.dev/skills/hyperlogue/r3/api-surface"><img src="https://agentmods.dev/badge/skills/hyperlogue/r3/api-surface/github.svg" alt="Measured on agentmods" height="20"></a>

Or the 80×15 button, for a site that already has a row of RSS and ATOM ones. Only the verdict fits; the numbers stay here.

agentmods 80×15 button for api-surface

Your own site · 80×15
<a href="https://agentmods.dev/skills/hyperlogue/r3/api-surface"><img src="https://agentmods.dev/badge/skills/hyperlogue/r3/api-surface.svg" alt="Reviewed on agentmods" width="80" height="20"></a>
Per session 110 Skills are progressive disclosure: only the name and description are preloaded; the body loads when the skill is used.
When invoked 6,982 The whole file, excluding the scripts and references it only reads on demand.
Security scan A 0 findings. A grade says what 26 rules found in the file — not that it is safe. Third-party audits
  • NVIDIA SkillSpector warn 7 Sept 2026
SkillSpector: 4 findings, up to high

These are SkillSpector’s own severities. On a checked sample its high-severity flags on skills were ~96% false positives — a documented command, a public API, a “never do X” rule — so we show them as a caution to read, not a verdict. Why →

  • high Tool Misuse · line 80
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
  • high Tool Misuse · line 130
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
  • high Tool Misuse · line 136
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
  • high Tool Misuse · line 168
    Tool parameters are crafted to achieve unintended or unsafe behavior. Parameter abuse can bypass intended safety checks (e.g. shell=True, --force, dangerous glob patterns).
    Fix: Validate all tool parameters against an allowlist. Reject dangerous parameter values (shell=True, --force, -rf /) and use safe defaults.
How audits are shown
Origin original No closer match found in the catalogue.
Token cost

What it costs to keep this loaded

Counted locally with the o200k_base tokenizer, which is exact for GPT models; Claude uses its own tokenizer and its counts differ. Treat this as one consistent yardstick across the catalogue rather than a bill. Prices are per million input tokens.

ModelPer sessionOnce invoked
Fable 5.1 $0.00110 $0.06982
Opus 5.5 $0.00044 $0.02793
Sonnet 5.5 $0.00022 $0.01396
Haiku 4.5 $0.00011 $0.00698

Measured today against content hash 0e72d37aed28, method: parsed. Prices are Anthropic first-party input rates as of 2026-10-07, from the pricing page.

Security

Grade A, and why

api-surface scanned grade A with 0 findings against 26 rules in 11 categories — prompt injection, anti-refusal, data exfiltration, privilege escalation, supply chain, agent snooping, system-prompt leakage, SSRF and excessive agency — measured today.

A static scan of the body, not an audit. Every finding is printed with the line that produced it so you can judge whether it matters here. A mod is markdown that instructs an agent; that is exactly why what it instructs is worth reading.

Nothing flagged

None of the 26 patterns this scan looks for appear in this file: no shell pipes, no recursive deletes, no credential paths, no hidden text, no instruction-override or anti-refusal phrasing, no agent-config snooping. That is not a guarantee, it is the absence of the things that are checkable.

.claude/skills/api-surface/SKILL.md · 445 lines

How it starts

The opening of the file, as written. The whole thing — 445 lines — stays where its author put it; the contents beside it link to each section on GitHub.

r3's API + CLI surface

This file is the design source of truth for r3's route catalog and CLI usage — update it here when the surface changes. The wire shapes live in shared/artifacts.ts (re-exported by shared/types.ts); this is the map over them.

The HTTP/JSON API is the product, not a detail of the React client — there are three clients (browser, CLI, agent). When you change behavior, change shared/artifacts.ts and keep server + CLI + web in sync.

The conversation hierarchy is Discussion → Thread → Comment. Discussion is the artifact-wide grouping; Threads own targets, claims, and resolution; Comments are authored messages, including archive messages directly in the discussion.

HTTP API

Artifact API

server/artifact-api.ts assembles the API against injected artifact storage. server/artifact-daemon.ts opens and migrates storage before accepting requests. The CLI, browser, and demo all use this protocol; legacy routes are removed.

  • GET /api/library-summary?window=daily|weekly returns ArtifactUsage: current backend-wide inventory, published versions, conversation counts, deduplicated content bytes, default-TTL GC eligibility, and activity buckets. Windows are fixed at 14 calendar days or four Monday-start weeks, including the current partial period, in the explicitly returned server timezone. Activity counts survive content deletion; completeSince marks partial pre-upgrade coverage. Reads have no delivery effect.
  • POST /api/gc accepts ArtifactGcRequest: optional ttlDays (integer 1..36500), dryRun (default false), and optional confirmed candidates (id, archivedAt). Default TTL is persisted archiveTtlDays, or 30 elapsed days. Only archived artifacts at or before the cutoff qualify. A supplied candidate list restricts deletion to that preview and skips changed archive timestamps, restored artifacts, and missing members. Results include candidates, reclaimable content bytes, deleted/skipped IDs, per-artifact failures and any post-commit blob cleanup error. Cleanup uses whole-artifact cascades, preview revocation, deletion invalidations, and publication-coordinated blob collection. Both routes require normal API auth and origin guards and return no-store. GC is manual, never a startup timer.
  • GET/POST /api/sessions lists/registers explicit agent identities; labels are mutable display names and never identity or delivery addresses. Label changes invalidate each referencing artifact, refresh its complete label map, and update both selected and fallback subscription labels. Unchanged labels emit no event; GET/POST /api/projects and PATCH/DELETE /api/projects/:id manage optional grouping. PATCH accepts EditArtifactProjectBody (name, remoteUrl, optional expectedRemoteUrl). Remote backfill can require the current field to be null; concurrent changes conflict. Removing a group preserves its artifacts and deletes its automatic remote mapping.
  • GET/POST /api/artifacts, GET/PATCH/DELETE /api/artifacts/:id list, create, inspect, edit metadata, or delete the whole artifact. Creation accepts a sanitized remoteUrl hint for server-configured project inference; explicit projectId, including null, wins. List filters are state, kind, project, and meta.<key>. No repo header or local path is involved. Artifact detail includes a process-scoped syncCursor; ?since=<cursor> returns a bounded delta or a full snapshot on a gap. ?view=summary reads only its Artifact projection. See incremental reads. Artifact detail includes agentLabels, current display labels keyed by the sessions referenced in its creator, versions, threads, comments, claims, and lifecycle events. Unnamed entries are null; unrelated sessions are omitted. The browser uses these labels without fetching the global session list. Artifact reads include computed unhandledCount: open threads whose latest message is from an agent. Reading, delivery, and claims do not clear it. storage.totalBytes and storage.latestVersionBytes report deduplicated published content and the latest publication's full footprint, excluding database/filesystem overhead. See storage accounting. latestVersion is null before publication, otherwise a list projection of the latest committed sequence, label, summary, and publication time; never nextSeq - 1. Artifact metadata has no overview/summary field. Publication summaries remain immutable version metadata; edit --summary is unsupported.
  • GET /api/search?q=... returns ArtifactSearchResponse from shared/artifact-search.ts (re-exported by shared/artifacts.ts). Filters: state=active|archived, kind=files|html|diff, project=<id>, attention=true|false, history=latest|all, type=all|content|conversation, limit=1..100 (default 50), and offset=0..100000. Queries contain 1–16 Unicode word prefixes, at most 256 characters, combined with AND; punctuation is a separator and FTS syntax is never executed. Latest scope limits publications; conversation matches retain each message’s recorded context. Results contain plain-text snippets, native targets, thread/comment IDs, per-type counts, and nextOffset. skippedFiles reports excluded binary, invalid UTF-8, or >4 MiB text files in the selected scope. HTML searches static entrypoint text without executing scripts or searching companion source. Same authentication/origin guards as artifact reads; no comment acknowledgment, claim, subscription, or delivery effect. CLI: r3 search "words" with corresponding flags, --attention, and --json.
  • GET/POST /api/artifacts/:id/versions lists retained versions or publishes a complete version with expectedSeq, publicationKey, explicit actor, and optional boolean listen (default true). A new commit replaces the fallback using a connected worker destination, or clears it when absent/disabled. Replays cannot reclaim the fallback. The response adds a complete backend-owned url, listenerRegistered, and optional worker listener subscription. CLI text and JSON output preserve that stable URL unchanged, without a browser sign-in ticket. There is no per-version delete. GET .../versions/:seq reads version metadata.
  • GET .../versions/:seq/files|source|resource|diff|diff-context|patch reads membership, highlighted source, original bytes, rendered sparse diff, retained context, or original patch. source and resource take ?path=; diff-context takes ?path=&start=&end= in new-side coordinates. Highlighted reads accept ?theme=. Resource GET/HEAD supports ranges and validators; app-origin HTML is always an attachment. Missing bytes never fall back to a different version or the filesystem. Executable rendering belongs to preview.
  • GET/PUT /api/artifacts/:id/viewed persists opaque read-progress keys with { key, viewed }. Theme and login-token endpoints retain their response shapes.
  • GET/POST /api/artifacts/:id/threads, GET/PATCH/DELETE /api/threads/:id, POST /api/threads/:id/comments and GET/PATCH /api/comments/:id use native immutable original targets and derived comment references. Historical placements remain readable; new placement authoring is removed. A Thread contains one ordered Comment list, including its opening Comment. The common comment read/edit endpoint also accepts artifact-level archive Comments; these are text-only and editable after restore. r3 comment show reads any Comment without acknowledging it; r3 comment edit edits its body and supported images. Every message mutation names an actor; deletion takes { actor }. Only human actors change thread status. Files also accept native media targets with locator: { time, box } and a required mediaSnapshot (full-frame PNG/JPEG upload). Reads add the immutable locator.frame descriptor; bytes use the attachment route. Snapshot evidence is separate from editable message attachments. CLI thread add/comment accept --frame <path> with a media --target; media targets accept --view media. Comment fetch manifests include target frames, including follow-up originals. Rendered locators accept an optional plain-text label for named HTML fix links; matching still uses the selector and native evidence. See r3 guide html for the comment example and the schema document for storage semantics. artifact_summary and version_summary are historical read-only targets; new threads and comment fix targets reject description anchors.
  • GET /api/threads/:id/source returns ArtifactSourceRange for the original source/diff line target: artifact, version, path, side (null for source), inclusive start/end, and complete text with LF separators. Rendered, general, and whole-file targets return 400; missing threads return 404. The normal authentication and origin guards apply. This read never acknowledges comments, claims a thread, or establishes a subscription. Source/diff quotes may be nonblank exact excerpts within the complete captured range; range existence, version/file/side, diff gaps, and input limits remain validated. Browser excerpts are capped at four lines and 2,048 UTF-16 code units; existing saved quotes are unchanged.
  • POST/DELETE /api/claims { sessionId, threadIds } claims/releases as the named registered agent. Claims change presence, not owner delivery.
  • GET .../:id/comments/pending[?threads=<ids>] returns an ArtifactCommentSnapshot: formatted text, itemCount, and an acknowledgment containing the selection and required expectedFingerprint. It is read-only and uncached; archived artifacts return 409. POST .../:id/comments/acknowledge takes that ArtifactCommentAcknowledgment after successful consumption and returns { acknowledgedCount }. Missing/invalid fingerprints return 400; stale revisions, changed selection, or archive return 409 without marking content delivered. An unfiltered snapshot also includes pending artifact-level Comments after restore. The fingerprint binds artifact, selection, and persisted conversation revision, including edit/revert and prior acknowledgment. GET .../:id/comments/history[?threads=<ids>] returns ArtifactCommentRead (text, itemCount) without acknowledgment data: open history by default, or the specified threads including resolved ones. History remains readable after archive. The browser copies only the CLI command and makes no comment-read or acknowledgment request. The former /prompt routes and CLI alias are removed.
  • POST .../:id/submit returns { notification }; sent confirms a local harness delivery acknowledgment or a generic watch woken for pending comments. An absent selected subscription (or a watch with no pending work) returns none. Local Codex or Antigravity acceptance returns queued; failure returns failed and HTTP 502. Neither acknowledges comments. POST .../:id/lifecycle takes ArtifactLifecycleBody, returning the persisted event (including its optional artifact-level comment), replay flag, and notification result. Archive input is comment: { body }; blank bodies normalize to no Comment. Delivery failure is HTTP 502; the committed archive remains authoritative. Replays do not notify twice.
  • POST /api/artifacts/archive takes ArtifactBulkArchiveBody: explicit actor, 1–100 unique items: [{ id, operationKey }], and optional shared comment: { body }. Validate the whole envelope before writes; malformed requests fail as a whole. A valid batch returns HTTP 200 and ArtifactBulkArchiveResponse.results in input order. Each item independently uses the lifecycle transaction: archived includes eventId, replayed, and notification; skipped has reason already_archived; failed includes HTTP-equivalent status and error. Missing artifacts fail with 404; conflicting operation keys fail with 409. Other artifacts still proceed. Matching operation keys replay before the already-archived check, including after restore, without another transition or notification. Fresh keys skip existing archives without changing timestamps. Notification failure remains an archived result with notification.state: failed, not a batch HTTP 502. Claims, subscriptions, Comments, and invalidations follow the single-artifact lifecycle rules. Requests retain the ordinary 2 MiB streamed body limit, auth/origin guards, and no-store responses. The home page chunks larger selections and keeps each item's retry key.
  • GET .../:id/watchers reads subscriptions and POST .../:id/watch { actor, timeoutMs? } establishes an explicit subscription for a bounded long poll. DELETE .../:id/listen { actor } removes that actor's subscriptions. Persistent listen and delivery acknowledgments use the shared worker protocol below. The former per-artifact POST listen stream and /api/connections/:id/acknowledgments are removed. Backend HTTP receives no harness socket, executable path, or harness credential.
  • GET /api/events[?artifact=<id>] is an authenticated fetch stream of ArtifactStreamEvent invalidations. ready means refetch current state; heartbeat keeps the connection alive. Neither implies message delivery.

Read the full file on GitHub · 445 lines

Changes

What this file has done since we first saw it

Hashed on every crawl. A supply-chain change to an agent config is a question of when, not whether, so the history is kept rather than the latest state alone.

  1. today Changed · +17 lines 0e72d37aed28
  2. 4d ago Changed · +5 lines 50ea867ef420
  3. 8d ago Changed · +3 lines 6e2eeaa9cc04
  4. 9d ago Changed · +15 lines c1c5d61b0fc6
  5. 11d ago Changed · +37 lines e171e1a56bf9
  6. 13d ago Changed · +6 lines 134fa588feae
  7. 14d ago Changed 5ca0ddbdc66c
  8. 15d ago Changed · +20 lines 9049edcf5c43
  9. 16d ago Changed · +15 lines fb2632289336
  10. 18d ago First seen · 327 lines · 110 tokens per session scan A 3e0299754987

Subscribe to this mod's changes

api-surface is a skill published in the GitHub repository hyperlogue/r3 (45 stars, last pushed today), licensed MIT. It adds 110 tokens to every session and 6,982 once invoked, about $0.0004 per session on Opus 5.5. A static security scan graded it A with 0 findings. No closer match exists in the catalogue, so it is treated as the original; first seen 2026-08-30.

Related

Other skills, from other repositories

ring:migrating-to-lib-observability

Migrating a Lerian Go app off lib-commons observability imports (deprecated shims or removed APIs) to lib-observability via a fixed mapping table, then bumps go.mod and validates the build; ring:backend-go applies the edits. Covers log/zap/runtime/assert, opentelemetry/tracing, HTTP middleware, context helpers, and…

LerianStudio/ring · 104 tokens

ring:using-lib-streaming

Using lib-streaming, Lerian's producer-only event publication library (Kafka/SQS/RabbitMQ/EventBridge), in two modes. Sweep Mode detects DIY publishers (franz-go, sarama, amqp091, watermill, raw AWS SDK) and re-rolled manifests/breakers. Reference Mode catalogs the Builder/Emitter/Catalog facade. Companion to…

LerianStudio/ring · 99 tokens

ring:using-lib-systemplane

Using lib-systemplane, the hot-reload runtime-config plane (Postgres LISTEN/NOTIFY or MongoDB change streams), in two modes. Sweep Mode detects DIY config reload (SIGHUP, fsnotify, viper, pgx LISTEN), manual tenant-scoping, hand-built admin CRUD, and v4 residue. Reference Mode catalogs client lifecycle and…

LerianStudio/ring · 106 tokens

ring:using-lib-observability

Using lib-observability v1.1.0, Lerian's OpenTelemetry foundation (lib-commons, lib-systemplane, lib-streaming depend on it), in two modes. Sweep Mode detects DIY zap/slog logging, raw OTel metrics, hand-rolled redaction, and hard-coded attribute strings. Reference Mode catalogs the log, metrics, zap, redaction, and…

LerianStudio/ring · 102 tokens

ring:using-outbox

Using the transactional-outbox pattern across lib-streaming (writer) and lib-commons/v5/commons/outbox (repository + relay), in two modes. Sweep Mode detects DIY outbox tables, hand-rolled relay loops, send-and-pray emits, missing WithOutboxTx wrapping, and broker calls inside DB transactions. Reference Mode catalogs…

LerianStudio/ring · 98 tokens

ring:using-tracing

Using lib-observability/tracing for OTEL provider lifecycle, trace-context propagation across HTTP/gRPC/queues, span error/event recording, and PII redaction, in two modes. Sweep Mode detects raw OTEL setup, hand-rolled header propagation, manual span-attribute assembly, and DIY redaction. Reference Mode catalogs…

LerianStudio/ring · 94 tokens