Install
$ agentstack add skill-ngerakines-atproto-skills-atproto-repository ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
AT Protocol Repository
An AT Protocol repository is a single account's entire record store, addressed by its DID. Every record lives at a key in a Merkle Search Tree; the tree's root CID is sealed by a signed commit; the commit plus every block it transitively references are the repository. On the wire, it travels as a CAR v1 file.
This skill routes to per-language guides for Rust, TypeScript, and Go, sitting on top of a language-neutral spec in shared/.
Defaults
- DRISL — canonical DAG-CBOR: bytewise map keys, shortest-form integers, no indefinite-length framing, CIDs as tag 42 + identity multibase.
- CAR v1 —
varint ‖ header-cbor ‖ (varint ‖ 36-byte-CID ‖ bytes)*. Roots list declares the commit CID. - MST — SHA-256 key height with fanout 4 (count pairs of leading zero bits). Node shape
{l?, e:[{p,k,v,t?}]}. Keys are/, max 1024 bytes. - Commit —
{did, version:3, data, rev, prev, sig}.previsnullfor genesis (though see §divergence). Signing bytes = DAG-CBOR of the commit minussig. - Signature — raw
r ‖ sECDSA (k-256 or p-256), low-S normalized. Verified against the#atprotoMultikey in the signer's DID document.
Full normative rules: shared/drisl.md, shared/car-v1.md, shared/mst.md, shared/commit-and-signing.md, shared/data-model.md. Fixtures: shared/test-vectors.md. Cross-language differences: shared/divergence-matrix.md.
Language detection
Before generating or reviewing any repo code, determine the target language from project files or the file being edited:
Cargo.toml,*.rs, any mention ofatproto-repo/atproto-dasl/atproto-record→ Rust — read fromrust/.package.json,tsconfig.json,*.ts,*.tsx, imports of@atproto/repo/@atproto/lex-cbor/@atproto/crypto→ TypeScript — read fromtypescript/. Also*.js/*.jsxwhen there is no.tspresent.go.mod,*.go, imports ofgithub.com/bluesky-social/indigo/atproto/repo→ Go — read fromgo/.
Prefer the file being edited over the repo root when they disagree: a .go consumer inside a TypeScript-workspace monorepo still means Go for that task.
If multiple languages are present and the task does not point at one unambiguously, ask which one applies. Never mix repo libraries across languages in generated code.
If an unsupported language is detected (Python, Java, Swift, …), point the user at shared/drisl.md, shared/car-v1.md, shared/mst.md, and shared/commit-and-signing.md for the wire format, and offer the Go indigo/atproto/repo source as the most complete reference implementation to transliterate from.
Reading guide
For every repo task:
- Read the relevant
shared/*.mdfirst. They are short and define the rules your code must enforce. - Read the relevant task file in the detected language directory:
- DRISL / canonical DAG-CBOR encoding of any block →
{lang}/drisl.md - CAR v1 reading and writing →
{lang}/car.md - MST construction, traversal, diff →
{lang}/mst.md - Commit record shape, signing, verification →
{lang}/commit.md - Library setup, public API at a glance, idioms →
{lang}/README.md
- Consult
shared/divergence-matrix.mdwhenever porting between languages or reviewing cross-stack interop. Theprev: nullvs omitted divergence alone has caused many hours of "why does my signature not verify" debugging.
Always prefer the official library over hand-rolling: atproto-repo crate in Rust, @atproto/repo in TypeScript, github.com/bluesky-social/indigo/atproto/repo in Go.
The conceptual stack
┌──────────────────────────────┐
CAR v1 file ──────▶ │ header: { version:1, roots } │
(on the wire) │ block: [cid, data] … │
│ block: [cid, data] … │
└──────────────────────────────┘
│
▼
┌──────────────────────────────┐
Signed commit ─────▶ │ { did, version:3, data, rev, │
(root block) │ prev, sig } │
└──────────────────────────────┘
│ data: CID
▼
┌──────────────────────────────┐
MST node ──────────▶ │ { l?, e:[entry,entry,…] } │
(many blocks) │ entry = { p, k, v, t? } │
└──────────────────────────────┘
│ v: CID (leaf = record block)
▼
┌──────────────────────────────┐
Record block ──────▶ │ DAG-CBOR encoding of record │
(many blocks) │ { $type: "", … } │
└──────────────────────────────┘
CAR just frames a sequence of (CID, bytes) blocks. The same block bytes travel over getRecord, the firehose, and any cache.
Cross-language hazards to flag up front
High-frequency failure modes; full detail in shared/divergence-matrix.md:
prev: nullvs omitted — When signatures fail on genesis commits only, suspect cross-encoderprevdrift. Rust reference impl omitsprevfor genesis (4-entry map); Go and TS always serializeprev: null(5-entry map). Strip the signature from raw bytes rather than re-encoding before verifying.- TS MST is immutable — When an add/update/delete appears to have no effect, reassign to the return value.
add/update/deletereturn a newMST; the original is unchanged. Rust and Go mutate in place. - TS CAR reader verifies CIDs on ingest — When a CAR that Go or Rust accepts fails TS intake, suspect block corruption.
verifyIncomingCarBlocksdefaults on in TS; Go and Rust do not verify. - Go cbor-gen sorts by struct declaration order, not bytewise — When adding a new cbor-gen struct, audit field order against bytewise canonical order. The
Commitstruct happens to be canonical, but anything you add must be checked. - Partial trees are normal in Go/Rust, exceptional in TS — When a firehose event traversal throws
MissingBlockErrorin TS, treat the partial tree as expected and fall back to a partial walker. Go/Rust return a partial-tree sentinel instead. - Only Go has end-to-end wired verification — When verifying in TS or Rust, resolve the signing DID key separately first.
VerifyCommitSignatureFromCaris Go-only; TS needs a pre-resolved didKey and Rust needs the caller to do everything. - Rust
Mst::insert_recursivecan't cross heights — When building an MST from scratch in Rust, build bottom-up from sorted(key, cid)pairs, not top-down.
Tools you can call
Prefer these MCP tools when the goal is to compute or validate rather than teach an implementation how:
lexicon-garden→create_record_cid(record),transmogrify_record,invoke_xrpc(e.g.com.atproto.sync.getRepo,getBlocks).atpmcp→create_record_cid,get_record,transmogrify_record,generate_tidagainst a local PDS.
Concrete example — computing a spec-conformant record CID against an in-memory record before writing a test vector:
create_record_cid({
"$type": "app.bsky.feed.post",
"text": "hello",
"createdAt": "2024-01-01T00:00:00.000Z"
})
→ "bafyreihsh..."
Use this to verify your own encoder output matches the canonical CID without having to boot a PDS. transmogrify_record is the round-trip companion — feed it a record, get back the DAG-CBOR bytes and the CID together.
For record-side helpers (TID generation, AT-URI parsing), the atproto-record Rust crate ships the cleanest reference; the TS equivalent is @atproto/syntax, and Go uses atproto/syntax in indigo.
Cross-skill plumbing: DID resolution for verification
VerifyCommitSignatureFromCar (Go) does identity lookup and signature check in one call. TypeScript and Rust need the signing key resolved separately before verification:
- Rust — resolve with
atproto-identityfirst, extract the#atprotoverification method, then pass the Multikey intoatproto-repo's verify loop. See../atproto-identity-resolution/rust/resolution.mdfor the resolver andrust/commit.mdfor the verify surface. - TypeScript — resolve via
@atproto/identity→IdResolver.did.resolveAtprotoData(did)→ yields{ signingKey }as adidKey, then pass intoverifyCommitSig. See../atproto-identity-resolution/typescript/resolution.mdandtypescript/commit.md. - Go —
VerifyCommitSignatureFromCarwraps both; no manual plumbing required.
Directory layout
atproto-repository/
├── SKILL.md # this file — router
├── shared/
│ ├── drisl.md # canonical DAG-CBOR rules
│ ├── car-v1.md # CAR v1 byte layout
│ ├── mst.md # MST algorithm + invariants
│ ├── commit-and-signing.md # commit shape, signing bytes, verification
│ ├── data-model.md # records, NSIDs, TIDs, AT-URIs
│ ├── test-vectors.md # fixtures
│ └── divergence-matrix.md # cross-language differences
├── rust/
│ ├── README.md # atproto-repo / atproto-dasl / atproto-record setup
│ ├── drisl.md # atproto-dasl encoding
│ ├── car.md # CarReader / CarWriter
│ ├── mst.md # Mst, insert_recursive, diff_entries
│ └── commit.md # Commit / UnsignedCommit / signing loop
├── typescript/
│ ├── README.md # @atproto/repo setup
│ ├── drisl.md # @atproto/lex-cbor
│ ├── car.md # readCar / writeCarStream / verifyIncomingCarBlocks
│ ├── mst.md # immutable MST class
│ └── commit.md # signCommit / verifyCommitSig / verifyRepo
└── go/
├── README.md # indigo/atproto/repo setup
├── drisl.md # cbor-gen + atdata
├── car.md # LoadRepoFromCAR / go-car
├── mst.md # Tree / Node / partial-tree semantics
└── commit.md # Commit / Sign / VerifyCommitSignatureFromCar
References
All reachable from the tree above. Listed here for quick grep:
shared/drisl.md,shared/car-v1.md,shared/mst.md,shared/commit-and-signing.md,shared/data-model.md,shared/test-vectors.md,shared/divergence-matrix.mdrust/README.md,rust/drisl.md,rust/car.md,rust/mst.md,rust/commit.mdtypescript/README.md,typescript/drisl.md,typescript/car.md,typescript/mst.md,typescript/commit.mdgo/README.md,go/drisl.md,go/car.md,go/mst.md,go/commit.md
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: ngerakines
- Source: ngerakines/atproto-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.