Agent skill
kb-lemmy
Background knowledge about Lemmy, the federated link aggregation and discussion platform (Reddit alternative). Covers Lemmy's fundamental architectural decision of Communities as Group actors that automatically Announce all content to followers, the ActivityPub object type mappings (Post as Page with mandatory title, Comment as Note with inReplyTo tree, Community as Group, User as Person, Instance as Application, Private Message as ChatMessage), voting via Like/Dislike activities (unique first-class downvotes unlike most Fediverse platforms), ranking algorithms (Active, Hot, Scaled, Top), the full activity reference (Create/Update/Delete for posts and comments, Follow/Accept for community subscription, Remove/Block/Lock for moderation, Flag for reporting, Announce for community relay), federation modes (allowlist, blocklist, open), custom namespace extensions (stickied, distinguished, commentsEnabled, postingRestrictedToMods), the Lemmy JSON-LD context (join-lemmy.org/context.json), the REST API v3 with JWT auth and pictrs image service, known interoperability issues (name vs preferredUsername reversal, JSON-LD context errors, Mastodon reply propagation failures, vote federation inconsistencies, strict parsing), the tech stack (Rust/Actix-web/Diesel/PostgreSQL backend, TypeScript/Inferno.js frontend, activitypub-federation-rust library), and the Threadiverse ecosystem (Kbin/Mbin, PieFed, Sublinks). Load when the user asks about Lemmy federation; implementing a Lemmy- compatible ActivityPub server; how Lemmy communities work as Group actors; how Lemmy voting federates; Lemmy's Page object type; how posts and comments federate in Lemmy; Lemmy's moderation activities; interoperating with Lemmy instances; the Lemmy API; or the Threadiverse.
Install this agent skill to your Project
npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/other/other/kb-lemmy
SKILL.md
Lemmy — Complete Reference
Overview
Lemmy is a self-hosted, federated social link aggregation and discussion forum — the Fediverse equivalent of Reddit. Created by Dessalines in February 2019, with Nutomic as co-creator and primary federation implementer. Built in Rust (Actix-web, Diesel ORM, PostgreSQL) with a TypeScript/Inferno.js frontend. Licensed AGPL-3.0.
Lemmy federates via ActivityPub. Its fundamental design choice is
representing communities as Group actors that automatically relay all
content via Announce activities, ensuring cross-instance consistency.
It is the largest platform in the "Threadiverse" — the threaded discussion
subset of the Fediverse.
1. Technology Stack
| Component | Technology |
|---|---|
| Backend language | Rust |
| Web framework | Actix-web (actor-model based) |
| ORM | Diesel (type-safe) |
| Database | PostgreSQL (R2D2 connection pooling) |
| Frontend language | TypeScript + CSS |
| Frontend framework | Inferno.js (React-compatible) |
| API client | lemmy-js-client |
| Image service | pictrs |
| Deployment | Docker, Ansible, ARM64/RPi supported |
| License | AGPL-3.0 |
| Federation library | activitypub-federation-rust (standalone reusable crate) |
2. ActivityPub Object Type Mapping
| Lemmy Concept | ActivityPub Type | Notes |
|---|---|---|
| Community | Group |
Automated relay actor; Announces all content to followers |
| User | Person |
Creates content, moderates, sends PMs |
| Instance | Application |
Instance-level actor at root path |
| Post | Page |
Mandatory title (name), optional URL and body |
| Comment | Note |
Tree structure via inReplyTo |
| Private Message | ChatMessage |
Direct user-to-user, no threading |
Why Page for Posts?
Lemmy posts have a mandatory title (name), distinguishing them from
Note (typically untitled) and Article (long-form). The Page type
aligns with the concept of a web page with a URL, title, and optional
body.
3. Communities as Group Actors
This is the fundamental architectural decision. Communities are Group
actors with their own inboxes. Every post, comment, vote, and moderation
action is received by the community and then Announced (wrapped and
forwarded) to all followers across all instances.
Community Object
{
"@context": [
"https://www.w3.org/ns/activitystreams",
"https://join-lemmy.org/context.json"
],
"id": "https://enterprise.lemmy.ml/c/main",
"type": "Group",
"preferredUsername": "main",
"name": "The Main Community",
"summary": "<p>Welcome to the main community!</p>",
"inbox": "https://enterprise.lemmy.ml/c/main/inbox",
"outbox": "https://enterprise.lemmy.ml/c/main/outbox",
"followers": "https://enterprise.lemmy.ml/c/main/followers",
"featured": "https://enterprise.lemmy.ml/c/main/featured",
"attributedTo": ["https://enterprise.lemmy.ml/u/picard"],
"publicKey": {
"id": "https://enterprise.lemmy.ml/c/main#main-key",
"owner": "https://enterprise.lemmy.ml/c/main",
"publicKeyPem": "..."
}
}
Key Fields
| Field | Description |
|---|---|
preferredUsername |
Machine-readable community name |
name |
Human-readable display name |
summary |
Description / rules (HTML) |
icon / image |
Avatar / banner |
outbox |
Limited to 20 latest posts |
followers |
Count only (no individual references — privacy) |
attributedTo |
Creators and moderators |
featured |
Pinned posts collection |
postingRestrictedToMods |
Whether only mods can post |
The Announce Relay Pattern
User on Instance A Community on Instance B Instance C subscriber
| | |
|--- Create{Page} -----------> | |
| |--- Announce{Create{Page}} ->|
| | |
All content activities (Create, Update, Delete, Like, Dislike, Remove,
Lock) flow through the community Group actor, which wraps each in an
Announce and broadcasts to all followers. This is how cross-instance
consistency is maintained.
4. Post (Page) Object
{
"type": "Page",
"id": "https://enterprise.lemmy.ml/post/123",
"attributedTo": "https://enterprise.lemmy.ml/u/riker",
"to": [
"https://www.w3.org/ns/activitystreams#Public",
"https://ds9.lemmy.ml/c/main"
],
"audience": "https://ds9.lemmy.ml/c/main",
"name": "An interesting link",
"content": "<p>Check this out!</p>",
"source": {
"content": "Check this out!",
"mediaType": "text/markdown"
},
"attachment": [],
"image": {},
"commentsEnabled": true,
"sensitive": false,
"stickied": false,
"published": "2024-01-15T12:00:00.000Z"
}
| Field | Description |
|---|---|
name |
Title (mandatory — distinguishes Post from Comment) |
content |
Body text (HTML-rendered) |
source |
Original markdown with mediaType: "text/markdown" |
audience |
Target community (for routing) |
attachment |
Links/images array |
image |
Thumbnail |
commentsEnabled |
Post lock status (custom extension) |
sensitive |
NSFW flag |
stickied |
Pinned status (custom extension) |
language |
Language metadata (identifier + name) |
5. Comment (Note) Object
{
"type": "Note",
"id": "https://enterprise.lemmy.ml/comment/95",
"attributedTo": "https://enterprise.lemmy.ml/u/picard",
"to": "https://enterprise.lemmy.ml/c/main",
"content": "I agree with this take.",
"source": {
"content": "I agree with this take.",
"mediaType": "text/markdown"
},
"inReplyTo": [
"https://enterprise.lemmy.ml/post/38",
"https://voyager.lemmy.ml/comment/73"
],
"tag": [
{
"type": "Mention",
"href": "https://voyager.lemmy.ml/u/janeway",
"name": "@[email protected]"
}
],
"distinguished": false,
"published": "2024-01-15T13:00:00.000Z"
}
| Field | Description |
|---|---|
inReplyTo |
Parent post and/or parent comment (builds tree) |
tag |
Mention objects for user references |
distinguished |
Mod-highlighted comment (custom extension) |
6. Voting — Like and Dislike
Lemmy uses both Like (upvote) and Dislike (downvote) as first-class
ActivityPub activities. This is unique among major Fediverse platforms
— most only support Like.
Upvote
{
"type": "Like",
"actor": "https://enterprise.lemmy.ml/u/picard",
"object": "https://enterprise.lemmy.ml/post/123",
"audience": "https://ds9.lemmy.ml/c/main"
}
Downvote
{
"type": "Dislike",
"actor": "https://enterprise.lemmy.ml/u/worf",
"object": "https://enterprise.lemmy.ml/post/123",
"audience": "https://ds9.lemmy.ml/c/main"
}
Undo Vote
{
"type": "Undo",
"actor": "https://enterprise.lemmy.ml/u/picard",
"object": {
"type": "Like",
"actor": "https://enterprise.lemmy.ml/u/picard",
"object": "https://enterprise.lemmy.ml/post/123"
}
}
All votes include audience for community routing and are wrapped in
Announce by the community actor.
Privacy note: Every instance that subscribes to the community receives all vote activities — instance admins can see who voted on what.
Ranking Algorithms
| Algorithm | Description |
|---|---|
| Active (default) | Score + latest comment time with decay |
| Hot | Score + post publication time with decay |
| Scaled | Hot with boost for less active communities |
| New / Old | Chronological |
| Most Comments | Comment count |
| New Comments | Forum-style bump on new reply |
| Top (Day/Week/Month/Year/All) | Score within time window |
Score = upvotes minus downvotes.
7. Full Activity Reference
User → Community
| Activity | Purpose |
|---|---|
Follow |
Subscribe to community |
Undo{Follow} |
Unsubscribe |
Create{Page} |
New post |
Create{Note} |
New comment |
Update{Page} |
Edit post |
Update{Note} |
Edit comment |
Like |
Upvote |
Dislike |
Downvote |
Undo{Like} / Undo{Dislike} |
Remove vote |
Delete |
Delete own content |
Undo{Delete} |
Restore deleted content |
Flag |
Report content (with summary reason) |
Community → Followers
| Activity | Purpose |
|---|---|
Accept{Follow} |
Automatic response to Follow |
Announce{*} |
Rebroadcast any received activity to all followers |
Moderation
| Activity | Purpose |
|---|---|
Remove |
Remove content (with summary reason) |
Block |
Ban user (with target scope, optional removeData, expires, summary) |
Lock |
Prevent new comments on post |
Add to /moderators |
Add moderator |
Remove from /moderators |
Remove moderator |
Add to /featured |
Pin post |
Remove from /featured |
Unpin post |
User → User
| Activity | Purpose |
|---|---|
Create{ChatMessage} |
Send private message |
Update{ChatMessage} |
Edit private message |
Delete{ChatMessage} |
Delete private message |
Instance-Level
- Instance actor (type
Application) at root path - Admins can remove any content instance-wide
Deleteon user actor withremoveData: truefor account deletion
All activities are signed with RSA keys (key ID: {actor-url}#main-key).
8. JSON-LD Context and Custom Extensions
Required Context
[
"https://join-lemmy.org/context.json",
"https://www.w3.org/ns/activitystreams"
]
Namespace Prefixes
{
"lemmy": "https://join-lemmy.org/ns#",
"litepub": "http://litepub.social/ns#",
"pt": "https://joinpeertube.org/ns#",
"sc": "http://schema.org/"
}
Custom Properties
| Property | Namespace | Used on | Description |
|---|---|---|---|
stickied |
lemmy | Page | Pinned post |
distinguished |
lemmy | Note | Mod-highlighted comment |
commentsEnabled |
lemmy | Page | Post lock status |
postingRestrictedToMods |
lemmy | Group | Restricted posting |
moderators |
lemmy | Group | Moderator collection |
language |
lemmy | Page, Note | Language metadata |
sensitive |
as | Page | NSFW flag |
matrixUserId |
lemmy | Person | Matrix chat ID |
Important: Lemmy parses ActivityPub objects as plain JSON, not as
JSON-LD. The @context is included for other software's benefit but
Lemmy does not perform JSON-LD expansion or compaction.
9. Federation Modes and Fetching
Federation Modes
| Mode | Description |
|---|---|
| Allowlist | Only connect to specified instances |
| Blocklist | Block specific instances, open to all others |
| Open (default) | Connect to any instance |
Cascading Fetch Behavior
- Community fetch: Also fetches most recent posts (not comments/votes)
- Post fetch: Also fetches community and author
- Comment fetch: Also fetches all parent comments, the post, authors, and the community
This ensures referential integrity across the federated network.
10. REST API
| Aspect | Details |
|---|---|
| Version | v3 (/api/v3/...) |
| Auth | JWT (cookies or Authorization header since 0.19.0) |
| Image service | pictrs — upload, resize, format conversion |
| Feeds | RSS/Atom at /feeds/ paths |
| Rate limiting | IP-based (Docker: requires X-Forwarded-For header) |
| Client library | lemmy-js-client (official TypeScript) |
| OpenAPI spec | Unofficial: mv-gh.github.io/lemmy_openapi_spec/ |
11. Interoperability Issues
name vs preferredUsername (Historical)
Lemmy initially reversed these: name for usernames, preferredUsername
for display names. This is the opposite of the ActivityPub spec and
Mastodon. Nutomic acknowledged it as "completely counterintuitive."
JSON-LD Context Errors
Lemmy's @context had incorrect declarations:
"stickied": "as:stickied"— falsely impliedstickiedis in the ActivityStreams namespace"pt"prefix expanded to Lemmy's domain instead of PeerTube's
Nutomic admitted: "the truth is that I don't really understand how [@context] works."
Mastodon Reply Propagation
Replies from Mastodon can fail to reach all Lemmy instances because Mastodon doesn't include the community inbox in its recipient lists. The community Group actor must be in the recipient list to Announce the reply.
Mastodon Vote Federation
Mastodon's Like targets personal inboxes, not shared inboxes. Lemmy
processes the vote locally but does not Announce it, causing vote count
inconsistencies across instances.
Strict Parsing
Lemmy is "really inflexible when it comes to incoming activities." Arrays vs single values, or object IDs vs full inlined objects, can cause parsing errors. The Lemmy protocol is described as "a strict subset of the ActivityPub Protocol."
12. The Threadiverse Ecosystem
"Threadiverse" refers to Reddit-style threaded discussion platforms in the Fediverse. All federate with each other via ActivityPub.
| Platform | Language | Terminology | Notes |
|---|---|---|---|
| Lemmy | Rust | Communities | Largest, most mature |
| Mbin | PHP (fork of Kbin) | Magazines | Also supports microblogs (Mastodon-style) |
| PieFed | Python | Topics | Rapid development, approaching feature-parity |
| Sublinks | Java | — | Drop-in Lemmy replacement (alpha) |
Users on any Threadiverse platform can see and interact with content from any other, including subscribing to Lemmy communities from Mbin or PieFed.
13. Known Quirks for Implementers
-
Posts use
Page, notNote— if your server sendsNoteobjects to a Lemmy community, they will be treated as comments, not posts. Posts requirePagetype with aname(title). -
Community must be in recipients — activities targeting a Lemmy community must include the community in
toorcc. Sending only to the post author's inbox will not distribute the activity. -
audiencefield — Lemmy uses theaudienceproperty to route activities to the correct community. Include it for reliable delivery. -
Dislikeis real — unlike most Fediverse platforms, Lemmy usesDislikeas a distinct activity type for downvotes, notUndo{Like}. -
sourcewith markdown — Lemmy preserves original markdown in thesourcefield withmediaType: "text/markdown". Thecontentfield contains the HTML-rendered version. -
Outbox is limited — community outbox only contains the 20 most recent posts. Comments and votes are not included.
-
Followers collection is opaque — returns only a total count, not individual follower references (for privacy).
-
No JSON-LD processing — Lemmy parses JSON directly. Do not rely on JSON-LD compaction/expansion when interoperating with Lemmy.
-
ChatMessagefor PMs — Lemmy uses the non-standardChatMessagetype for private messages rather thanNotewith direct addressing.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
agent-ops-spec
Manage specification documents in .agent/specs/. Use when user provides requirements, acceptance criteria, or feature descriptions that need to be tracked and validated against implementation.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-testing
Test strategy, execution, and coverage analysis. Use when designing tests, running test suites, or analyzing test results beyond baseline checks.
agent-ops-state
Maintain .agent state files. Use at session start, after meaningful steps, and before concluding: read/update constitution/memory/focus/issues/baseline consistently.
Didn't find tool you were looking for?