Skip to content

Agent guide, a gibhub skill, and a BRC-73 permission manifest - #2

Merged
shruggr merged 2 commits into
mainfrom
docs/agent-readiness
Sep 20, 2026
Merged

shruggr merged 2 commits into
mainfrom
docs/agent-readiness

Conversation

@shruggr

@shruggr shruggr commented Sep 20, 2026

Copy link
Copy Markdown
Collaborator

Three things, each verified against the code rather than against memory.

1. AGENTS.md, with CLAUDE.md as a symlink to it

CLAUDE.md was 46 lines and had drifted. It is replaced by AGENTS.md
(git mode 120000 symlink at CLAUDE.md), the arrangement the gib CLI
uses.

It covers every route and what it renders, the lib modules that matter,
the head token's exact fields and vocabulary, the overlay and ORDFS
routes the site calls and what each returns, the fact that
lib/gib-head.ts decodes heads locally so /me works with no overlay,
and the conventions already present in the code — server components by
default, server-side handle resolution behind one shared cache, the
react-query keys in use, and the standing rule not to reimplement
anything the @1sat SDK ships.

The "things that will bite you" section is drawn from real facts: the
repository origin resolving to the genesis tree forever, handle
verification being per head rather than per commit, the hard-coded gib
basket, and CI's bun pin.

2. skills/gibhub/SKILL.md

A short skill for agents working in this codebase, listed in a catalog
table in AGENTS.md. This is not a monorepo, so skills/ at the root
is the only copy; there is nothing to mirror it to.

3. A BRC-73 grouped permission manifest

The site made the wallet prompt separately for each permission as the
user reached it. /manifest.json now carries a
metanet.groupPermissions block so a BRC-100 wallet asks once.

The permissions block went into the existing app/manifest.json/route.ts
rather than a new public/manifest.json, because the babbage.trust
block there is conditional on an environment variable and so the
document has to be built per request. Nothing was clobbered.

Declared, and nothing more:

Declared Reached by
[1, "identity key retrieval"] getPublicKey({ identityKey: true }) on connect
[1, "gib branch"] pushDropLock / unlockByScript
[1, "action label gib push"] mintHead
[1, "action label gib delete"] burnHead
basket gib listOutputs({ basket: "gib" }), and where minted heads are filed
spendingAuthorization, 10 000 sat/month createAction's net spend for the 1-satoshi head plus fees

Spending authorization is declared because the code needs one, not on
assumption: createAction computes netSpent > 0 for the 1-satoshi
head and calls ensureSpendingAuthorization.

Three details are not guessable from the spec name and are recorded in
AGENTS.md:

  • Action labels are not a category. GroupedPermissions has only
    description, spendingAuthorization, protocolPermissions,
    basketAccess, certificateAccess. A label is gated as the level-1
    protocol action label <name>.
  • Level-1 entries carry no counterparty. The manager forces it to
    "" at level 1, and a literal "" is a reserved slot that drops the
    entry — so no entry here declares one, even though gib-wallet.ts
    signs with counterparty anyone.
  • No extra keys. The grant path deep-equals granted entries against
    the requested ones, which are these literal objects.

The response also sets access-control-allow-origin: *, matching BSV
Desktop's own manifest route: a wallet running in a page fetches this
cross-origin, and a failed fetch is cached as "no manifest" for five
minutes.

Verification

bun run lint, bun run typecheck, bun test and bun run build all
pass. The manifest was fetched from a running dev server and checked two
ways: that it parses and matches the GroupedPermissions shape with no
dead (level 0), dropped (counterparty: "", level 2 without a
counterparty) or non-spec entries; and that the manager's
isRequestIncludedInGroupPermissions matcher, transcribed from source,
covers all six requests this app actually makes and nothing else.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX

shruggr and others added 2 commits September 20, 2026 01:52
CLAUDE.md was 46 lines and out of date. Replace it with AGENTS.md, the
arrangement the gib CLI uses, and make CLAUDE.md a symlink to it.

Covers what the code actually does: every route and what it renders, the
lib modules that matter, the head token's exact fields and vocabulary,
the overlay and ORDFS routes the site calls and what each returns, and
the conventions already in the code (server components by default,
server-side handle resolution behind one shared cache, react-query keys,
and the standing rule not to reimplement anything the @1sat SDK ships).

Adds skills/gibhub/SKILL.md for agents working in this codebase, listed
in a catalog table in AGENTS.md. This is not a monorepo, so skills/ at
the root is the only copy; there is nothing to mirror it to.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX
The site made a wallet prompt for each permission as the user reached it:
identity key on connect, then the protocol, then the label, then the
basket, then spending. A manifest lets the wallet ask once.

/manifest.json already existed for PWA metadata and the babbage.trust
block, so the permissions go into that same route rather than a new
public/manifest.json: the trust block is conditional on an environment
variable, so the document has to be built per request.

Shape and placement follow WalletPermissionsManager in
@bsv/wallet-toolbox, which is what @1sat/connect bundles. It reads
`manifest.metanet || manifest.babbage` then `.groupPermissions`, and
validates nothing, so three things had to be got exactly right:

- Action labels are not a category. GroupedPermissions has only
  description, spendingAuthorization, protocolPermissions, basketAccess
  and certificateAccess. A label is gated as the level-1 protocol
  `action label <name>`, so that is how `gib push` and `gib delete` are
  declared.
- Level-1 entries carry no counterparty. The manager forces it to "" at
  level 1, and a literal "" is a reserved slot that drops the entry.
- No extra keys: the grant path deep-equals granted entries against the
  requested ones, which are these literal objects.

Declared: the identity key protocol, `gib branch`, the two action
labels, basket `gib`, and a 10,000 sat monthly spending allowance.
Spending is needed and not assumed: createAction computes a net spend
for the 1-satoshi head plus fees and calls ensureSpendingAuthorization.
Nothing else is declared; every one of those six is reached by code in
lib/gib-wallet.ts or the @1sat/connect handshake.

Also sets access-control-allow-origin on the response. A wallet running
in a page fetches this cross-origin, and a failed fetch is cached as
"no manifest" for five minutes. BSV Desktop's own manifest route does
the same.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Claude-Session: https://claude.ai/code/session_01EM5trZ4BfZpW7pBjq2onqX
@vercel

vercel Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
gibhub Ready Ready Preview Sep 20, 2026 5:54am UTC

Request Review

@shruggr
shruggr merged commit 671a85d into main Sep 20, 2026
3 checks passed
@shruggr
shruggr deleted the docs/agent-readiness branch September 20, 2026 05:55

This branch was successfully deployed

1 active deployment
Preview — c642e0e7 Deployed Sep 20, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant