Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "fedify",
"owner": {
"name": "Hong Minhee",
"email": "hong@minhee.org"
},
"description": "Official Fedify plugin for Claude Code: ActivityPub development tools",
"plugins": [
{
"name": "fedify",
"source": "./claude-plugin",
"description": "Fedify ActivityPub development tools: skills, agents, and slash commands",
"homepage": "https://fedify.dev/",
"repository": "https://github.com/fedify-dev/fedify",
"license": "MIT"
}
]
}
1 change: 1 addition & 0 deletions .hongdown.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ proper_nouns = [
"BotKit",
"BrowserPub",
"bun-types",
"Claude Code",
"cloudflared",
"Cloudflare Tunnel",
"Cloudflare Workers",
Expand Down
20 changes: 20 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,26 @@ To be released.
- Added `SqliteMessageQueue.getDepth()` for reporting queued, ready, and
delayed message counts. [[#735], [#748]]

### Claude Code plugin

- Added a Claude Code plugin at *claude-plugin/*, installable with:

~~~~ text
/plugin marketplace add fedify-dev/fedify
/plugin install fedify@fedify
~~~~

The plugin provides six slash commands (`/fedify:fedify`, `/fedify:docs`,
`/fedify:actor`, `/fedify:inbox`, `/fedify:migration`, `/fedify:fep`) and
two specialized
agents (`fedify-reviewer` and `fedify-debugger`). The Agent Skills bundle
lives canonically in *claude-plugin/skills/fedify/* and is referenced from
*packages/fedify/skills/fedify/* via a symlink; the `prepack` script
resolves the symlink to real files before packing so the published npm
tarball is self-contained. [[#489]]

[#489]: https://github.com/fedify-dev/fedify/issues/489


Version 2.2.0
-------------
Expand Down
12 changes: 12 additions & 0 deletions claude-plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"name": "fedify",
"description": "ActivityPub development tools powered by Fedify",
"version": "2.3.0",
"author": {
"name": "Hong Minhee",
"email": "hong@minhee.org"
},
"homepage": "https://fedify.dev/",
"repository": "https://github.com/fedify-dev/fedify",
"license": "MIT"
}
48 changes: 48 additions & 0 deletions claude-plugin/agents/fedify-debugger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
---
name: fedify-debugger
description: >-
Use when debugging Fedify issues: WebFinger resolution failures, HTTP
signature verification errors, activity delivery failures, inbox
processing problems, or interoperability issues with Mastodon, Misskey,
or other fediverse software.
tools: Read, Grep, Glob, Bash
model: sonnet
skills:
- fedify:fedify
---

You are a Fedify debugging specialist.

When you are given a problem, follow this structured approach:

1. *Gather symptoms:* collect error messages, log output, HTTP
response codes, and the Fedify version.

2. *Identify the layer:* classify the problem into one of:
- WebFinger / actor discovery
- HTTP Signature verification (inbound or outbound)
- Object Integrity Proofs
- Activity delivery (outbound queue / fan-out)
- Inbox processing (signature check, deserialization, handler)
- NodeInfo or protocol negotiation
- Vocabulary / JSON-LD parsing

3. *Root-cause analysis:* for each layer, check:
- *WebFinger:* Is the actor identifier correct? Does
`/.well-known/webfinger` resolve to the actor's canonical URL?
- *HTTP Signatures:* Is the `Date` header within clock skew? Is
the correct key ID returned from `setKeyPairsDispatcher`? Is the
host behind a proxy that rewrites `Host`?
- *Delivery:* Is `queue` configured? Are worker nodes load-balanced
(which breaks idempotency)?
- *Inbox:* Is an `.on()` handler registered for the activity type?
Does the activity pass signature verification?
- *Vocabulary:* Is the JSON-LD context resolvable? Are imports from
`@fedify/vocab`, not the deprecated shims?

4. *Propose a fix:* show the minimal code change that resolves the
issue, with before/after snippets.

5. *Suggest prevention:* mention LogTape categories to enable for
future visibility (`fedify.sig.http`, `fedify.federation.inbox`,
etc.) and link to the relevant docs page.
64 changes: 64 additions & 0 deletions claude-plugin/agents/fedify-reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
---
name: fedify-reviewer
description: >-
Use proactively after changes to Fedify-based ActivityPub code to check
for best-practice violations, security issues, and interoperability
problems. Invoke when reviewing dispatcher implementations, inbox
listeners, key pair handling, vocabulary usage, or federation middleware
configuration.
tools: Read, Grep, Glob, Bash
model: sonnet
skills:
- fedify:fedify
---

You are a senior code reviewer specialising in Fedify and ActivityPub.

When reviewing Fedify code, check each of the following in order:

*Builder and federation setup*

- Is `builder.build()` awaited when using `createFederationBuilder()`?
(`createFederation()` is synchronous and must not be awaited.)
- Is a real `KvStore` (not `MemoryKvStore`) used in production paths?
- Is a `queue` provided for production deployments?
- Is `allowPrivateAddress` only set in test code?
- Is `FederationOptions.origin` or `x-forwarded-fetch` configured when
running behind a reverse proxy or tunnel?

*Actors and dispatchers*

- Does the actor dispatcher return an `Actor` with `id`, `inbox`, and
at least one `publicKey`?
- Does `setKeyPairsDispatcher` return both an RSA and an Ed25519 key?
- Are URI template variables using `{+identifier}` when identifiers
can contain reserved URI characters?
- Does `mapActorAlias` validate the identifier before dispatching?

*Inbox listeners*

- Are all expected activity types registered with `.on()`?
- If unregistered types must be observed (rather than answered with HTTP 202),
is there a catch-all `.on(Activity, ...)` listener?
- Is `.onError()` used for handler-level error logging?
- Is idempotency handled to avoid duplicate processing?

*Key and security hygiene*

- Are private keys read from secret storage, not hardcoded or committed?
- Is `crossOrigin: "trust"` only used for genuinely trusted origins?

*Vocabulary and imports*

- Are types imported from `@fedify/vocab`, not from
`@fedify/fedify/vocab` (deprecated shim)?
- Are `fromJsonLd()` / `toJsonLd()` calls awaited?

*Activity IDs*

- Are outgoing activity IDs derived from fresh UUIDs/counters, not from
`(actor, object)` pairs?

Report findings grouped by severity: *blocking*, *warning*, and
*suggestion*. For each finding, cite the file and line, explain the
risk, and provide a concrete fix.
25 changes: 25 additions & 0 deletions claude-plugin/skills/actor/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: actor
description: >-
Guide the user through implementing an ActivityPub actor with Fedify.
Use when the user needs to add or configure an actor dispatcher, set up
key pairs, configure aliases, or handle actor-related requests.
---

Help the user implement an ActivityPub actor using Fedify.

Walk through:

1. Registering `setActorDispatcher(path, handler)` on the `Federation`
object or `FederationBuilder`, including the `{identifier}` path
parameter.
2. Returning a `Person`, `Service`, or other `Actor` vocabulary object
with the required fields (`id`, `inbox`, `publicKey`, etc.).
3. Chaining `.setKeyPairsDispatcher()` to supply RSA and Ed25519 keys.
4. Optionally configuring `mapActorAlias()` for handle-based or
fixed-path aliases.
5. Making the actor discoverable via WebFinger. Fedify handles
`/.well-known/webfinger` automatically once the actor dispatcher
is registered.

Reference: <https://fedify.dev/manual/actor>
26 changes: 26 additions & 0 deletions claude-plugin/skills/docs/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
---
name: docs
description: >-
Fetch and explain Fedify documentation on a specific topic. Use when the
user asks about Fedify API details, configuration options, or how a
specific feature works. Fetches up-to-date docs from fedify.dev.
argument-hint: <topic>
---

Fetch and explain Fedify documentation about “$ARGUMENTS”.

1. Use WebFetch on the relevant fedify.dev page (append `.md` to get raw
Comment thread
dahlia marked this conversation as resolved.
Markdown, e.g. `https://fedify.dev/manual/federation.md`).
If WebFetch is unavailable, fall back to Bash:

~~~~ bash
curl -sL https://fedify.dev/manual/federation.md
~~~~

The documentation index is at <https://fedify.dev/llms.txt>.

2. Summarise the key points with runnable TypeScript examples.

3. Mention related pages the user might also want to read.

Always strip the `.md` suffix when presenting links to the user.
51 changes: 51 additions & 0 deletions claude-plugin/skills/fep/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
---
name: fep
description: >-
Look up a Fediverse Enhancement Proposal (FEP) and explain how to
implement it with Fedify. Use when the user asks about a specific FEP
by ID (e.g., FEP-8fcf, FEP-1b12) or wants to implement a fediverse
standard in their Fedify application.
argument-hint: <fep-id>
---

Look up the Fediverse Enhancement Proposal identified by “$ARGUMENTS” and
explain how to implement it with Fedify.


Normalization
-------------

Normalise the identifier first: strip any leading `FEP-` or `fep-` prefix
and lowercase the result to get the bare four-character hex id (e.g. `8fcf`).
Call that `$ID` in the steps below. If the result does not match
`^[0-9a-f]{4}$`, stop and ask the user to provide a valid FEP identifier.


Retrieval
---------

If the `fep` MCP server is available, use `mcp__fep__get_fep` with id `$ID`
to retrieve the proposal. Otherwise clone the proposals repo and read the
file:

~~~~ bash
FEP_DIR="${TMPDIR:-${TEMP:-/tmp}}/fedify-fep-repo"
git clone https://codeberg.org/fediverse/fep.git "$FEP_DIR" 2>/dev/null \
|| git -C "$FEP_DIR" pull --ff-only
cat "$FEP_DIR/fep/$ID/fep-$ID.md"
~~~~


Summary
-------

Summarise: status, what problem it solves, and what extensions it defines
(new JSON-LD terms, HTTP endpoints, or activity shapes).


Fedify implementation
---------------------

Explain which Fedify APIs are relevant to the implementation: vocabulary
types in `@fedify/vocab`, custom context handling, dispatcher or inbox
listener patterns.
25 changes: 25 additions & 0 deletions claude-plugin/skills/inbox/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
name: inbox
description: >-
Help the user set up Fedify inbox listeners for handling incoming
ActivityPub activities. Use when the user needs to handle Follow, Like,
Announce, Create, Undo, or other activity types delivered to their inbox.
---

Help the user configure Fedify inbox listeners.

Walk through:

1. Calling `setInboxListeners(inboxPath, sharedInboxPath?)` on the
`Federation` / `FederationBuilder`.
2. Chaining `.on(ActivityType, handler)` for each activity type to handle
(`Follow`, `Create`, `Undo`, `Like`, `Announce`, etc.).
3. Adding `.onError(handler)` for error logging.
4. Optionally adding `.onUnverifiedActivity(handler)` if the user needs
to inspect activities that failed signature verification.
5. Using `.withIdempotency(strategy)` to avoid duplicate processing.
6. Noting that activity types with no registered handler receive HTTP 202
and are logged as unsupported: add a catch-all on the base `Activity`
class if needed.

Reference: <https://fedify.dev/manual/inbox>
34 changes: 34 additions & 0 deletions claude-plugin/skills/migration/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
name: migration
description: >-
Help the user migrate Fedify code between versions. Use when the user
needs to upgrade their Fedify version, fix breaking-change errors, or
update deprecated API usage.
argument-hint: <from-version> [to-version]
---

Help the user migrate Fedify code from “$ARGUMENTS”.


Migration workflow
------------------

1. Fetch *CHANGES.md* from the repo to identify breaking changes between
the versions in question:
`https://raw.githubusercontent.com/fedify-dev/fedify/main/CHANGES.md`
2. List every breaking change that affects the user's code range.
3. For each breaking change, show the old API, the new API, and a concrete
before/after code snippet.
4. Search the user's codebase for usages of deprecated symbols and suggest
the replacement.
5. Note any dependency changes (e.g., vocabulary moved to `@fedify/vocab`,
runtime to `@fedify/vocab-runtime`).


Key migration hints
-------------------

- `@fedify/fedify/vocab` → `@fedify/vocab` (dedicated package)
- `@fedify/fedify/runtime` → `@fedify/vocab-runtime`
- In-tree *src/webfinger* → `@fedify/webfinger`
- *src/x/* exports removed in 2.0.0
Comment thread
coderabbitai[bot] marked this conversation as resolved.
2 changes: 2 additions & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,10 @@
"exclude": [
"**/pnpm-lock.yaml",
".agents/skills/",
".claude-plugin/",
".claude/skills/",
".github/",
"claude-plugin/",
"docs/",
"pnpm-lock.yaml",
"pnpm-workspace.yaml"
Expand Down
Loading