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.
curl -O https://raw.githubusercontent.com/hyperlogue/r3/main/.claude/skills/api-surface/SKILL.mdgit clone --depth 1 https://github.com/hyperlogue/r3Wrote 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.
[](https://agentmods.dev/skills/hyperlogue/r3/api-surface)<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.
<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>- NVIDIA SkillSpector warn
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.
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.
| Model | Per session | Once 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 |
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.
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|weeklyreturnsArtifactUsage: 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;completeSincemarks partial pre-upgrade coverage. Reads have no delivery effect.POST /api/gcacceptsArtifactGcRequest: optionalttlDays(integer 1..36500),dryRun(default false), and optional confirmedcandidates(id,archivedAt). Default TTL is persistedarchiveTtlDays, 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 returnno-store. GC is manual, never a startup timer.GET/POST /api/sessionslists/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/projectsandPATCH/DELETE /api/projects/:idmanage optional grouping. PATCH acceptsEditArtifactProjectBody(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/:idlist, create, inspect, edit metadata, or delete the whole artifact. Creation accepts a sanitizedremoteUrlhint for server-configured project inference; explicitprojectId, including null, wins. List filters arestate,kind,project, andmeta.<key>. No repo header or local path is involved. Artifact detail includes a process-scopedsyncCursor;?since=<cursor>returns a bounded delta or a full snapshot on a gap.?view=summaryreads only its Artifact projection. See incremental reads. Artifact detail includesagentLabels, 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 computedunhandledCount: open threads whose latest message is from an agent. Reading, delivery, and claims do not clear it.storage.totalBytesandstorage.latestVersionBytesreport deduplicated published content and the latest publication's full footprint, excluding database/filesystem overhead. See storage accounting.latestVersionis null before publication, otherwise a list projection of the latest committed sequence, label, summary, and publication time; nevernextSeq - 1. Artifact metadata has no overview/summary field. Publication summaries remain immutable version metadata;edit --summaryis unsupported.GET /api/search?q=...returnsArtifactSearchResponsefromshared/artifact-search.ts(re-exported byshared/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), andoffset=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, andnextOffset.skippedFilesreports 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/versionslists retained versions or publishes a complete version withexpectedSeq,publicationKey, explicitactor, and optional booleanlisten(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-ownedurl,listenerRegistered, and optional workerlistenersubscription. CLI text and JSON output preserve that stable URL unchanged, without a browser sign-in ticket. There is no per-version delete.GET .../versions/:seqreads version metadata.GET .../versions/:seq/files|source|resource|diff|diff-context|patchreads membership, highlighted source, original bytes, rendered sparse diff, retained context, or original patch.sourceandresourcetake?path=;diff-contexttakes?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/viewedpersists 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/commentsandGET/PATCH /api/comments/:iduse 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 showreads any Comment without acknowledging it;r3 comment editedits its body and supported images. Every message mutation names anactor; deletion takes{ actor }. Only human actors change thread status. Files also accept nativemediatargets withlocator: { time, box }and a requiredmediaSnapshot(full-frame PNG/JPEG upload). Reads add the immutablelocator.framedescriptor; 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-textlabelfor named HTML fix links; matching still uses the selector and native evidence. Seer3 guide htmlfor the comment example and the schema document for storage semantics.artifact_summaryandversion_summaryare historical read-only targets; new threads and comment fix targets reject description anchors.GET /api/threads/:id/sourcereturnsArtifactSourceRangefor the original source/diff line target: artifact, version, path, side (nullfor 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 anArtifactCommentSnapshot: formattedtext,itemCount, and anacknowledgmentcontaining the selection and requiredexpectedFingerprint. It is read-only and uncached; archived artifacts return 409.POST .../:id/comments/acknowledgetakes thatArtifactCommentAcknowledgmentafter 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>]returnsArtifactCommentRead(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/promptroutes and CLI alias are removed.POST .../:id/submitreturns{ notification };sentconfirms a local harness delivery acknowledgment or a generic watch woken for pending comments. An absent selected subscription (or a watch with no pending work) returnsnone. Local Codex or Antigravity acceptance returnsqueued; failure returnsfailedand HTTP 502. Neither acknowledges comments.POST .../:id/lifecycletakesArtifactLifecycleBody, returning the persisted event (including its optional artifact-levelcomment), replay flag, and notification result. Archive input iscomment: { 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/archivetakesArtifactBulkArchiveBody: explicitactor, 1–100 uniqueitems: [{ id, operationKey }], and optional sharedcomment: { body }. Validate the whole envelope before writes; malformed requests fail as a whole. A valid batch returns HTTP 200 andArtifactBulkArchiveResponse.resultsin input order. Each item independently uses the lifecycle transaction:archivedincludeseventId,replayed, andnotification;skippedhas reasonalready_archived;failedincludes HTTP-equivalentstatusanderror. 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 anarchivedresult withnotification.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/watchersreads subscriptions andPOST .../: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/acknowledgmentsare removed. Backend HTTP receives no harness socket, executable path, or harness credential.GET /api/events[?artifact=<id>]is an authenticated fetch stream ofArtifactStreamEventinvalidations.readymeans refetch current state;heartbeatkeeps the connection alive. Neither implies message delivery.
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.
- today Changed · +17 lines 0e72d37aed28
- 4d ago Changed · +5 lines 50ea867ef420
- 8d ago Changed · +3 lines 6e2eeaa9cc04
- 9d ago Changed · +15 lines c1c5d61b0fc6
- 11d ago Changed · +37 lines e171e1a56bf9
- 13d ago Changed · +6 lines 134fa588feae
- 14d ago Changed 5ca0ddbdc66c
- 15d ago Changed · +20 lines 9049edcf5c43
- 16d ago Changed · +15 lines fb2632289336
- 18d ago First seen · 327 lines · 110 tokens per session scan A 3e0299754987
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.
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…
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…
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…
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…
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…
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…