agentleFS
discord-phpdiscord-php/DiscordPHP/AGENTS.md

DiscordPHP

AGENTS.md1.1k starsChanged 35 days agoMITView on GitHub

This file is the repo operating manual for AI agents. It describes how to work inside this repository without breaking its design. Specialist skills in .agents/skills/ provide deeper playbooks for specific layers. If a change crosses layers, load multiple skills and use the playbooks in this file to keep boundaries clean. Before changing anything: In this repo, companion surfaces usually matter as much as the line you edit. For Compatibility Watch findings, Discord API/schema drift, or an issue labelled openapi,…

  • Reads credentials

Trending

More talk lately.about the whole repository

Dec 2025: 0 mentionsJan 2026: 0 mentionsFeb 2026: 2 mentionsMar 2026: 0 mentionsApr 2026: 1 mentionMay 2026: 0 mentionsJun 2026: 0 mentionsJul 2026: 0 mentionsAug 2026: 4 mentionsSep 2026: 13 mentionsOct 2026: 9 mentionsNov 2026: 1 mention
Dec 2025Jun 2026Nov 2026
Mentions a month of the discord-php/DiscordPHP repository that our weekly crawl found. There is no adoption data for this file yet.

Who's talking about discord-php/DiscordPHP

The biggest 5 of 52 mentions linking to the repository that our crawl found. Each line is their own headline.

See all 52

Talked about on GitHub and Bluesky (52 times).

On GitHub · 50

45 more on GitHub

The file

Show its rules and text

We split this AGENTS.md into the rules it gives an agent

56 rules. About 0 are common, 43 are distinctive, and 13 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈43

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 13

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    If a change crosses layers, load multiple skills and use the playbooks in this file to keep boundaries clean.

    line 5
  2. Distinctive:

    Read the base abstraction for that layer before copying a concrete class.

    line 12
  3. Distinctive:

    Read one representative concrete implementation from the same family.

    line 13
  4. Distinctive:

    Update companion surfaces that define the same contract.

    line 16
  5. Distinctive:

    Builders own outbound payload rules: If a payload has meaningful shape or validation, it usually deserves a builder.

    line 27
  6. Distinctive:

    Type maps are central dispatch points: If a Discord payload is polymorphic, there is usually one place that decides the concrete subtype.

    line 30
  7. Very specific:

    Use current library idioms: Prefer Factory::part() / Factory::repository(), prefer $part->save($reason) over repository save($part) in …

    line 31
  8. Distinctive:

    When editing endpoint bindings, REST routes, cache storage, or voice audio, you are necessarily touching these packages' contracts.

    line 78
  9. Distinctive:

    If you put transport logic in parts, parts stop being stable domain objects.

    line 88
  10. Distinctive:

    If you put domain validation in repositories, repository APIs stop being predictable.

    line 89
  11. Distinctive:

    If you skip builders, payload rules spread across unrelated methods.

    line 90
  12. Distinctive:

    If gateway handlers do not update caches correctly, every downstream relation becomes stale.

    line 91
  13. Distinctive:

    update events often return both new and old state

    line 167
  14. Distinctive:

    delete events often return cached removed state, not only the raw payload id

    line 168
  15. Distinctive:

    If a part can be saved:

    line 175
  16. Distinctive:

    If userland needs to construct a non-trivial outbound payload:

    line 184
  17. Distinctive:

    add or extend a builder

    line 186
  18. Distinctive:

    keep raw-array construction as an implementation detail only when a builder would be needless overhead

    line 187
  19. Distinctive:

    If Discord can tell us something through gateway dispatch:

    line 193
  20. Distinctive:

    prefer updating cache from the event instead of forcing later REST refetches

    line 195
  21. Distinctive:

    keep parent/child repository relationships coherent at the same time

    line 196
  22. Distinctive:

    When a Discord discriminator chooses a subtype:

    line 218
  23. Distinctive:

    update all materialization sites that depend on that family

    line 221
  24. Distinctive:

    If you touch one of these, inspect the companions too:

    line 227
  25. Distinctive:

    Add or adjust mutators for typed nested data, computed properties, or normalization.

    line 248
  26. Very specific:

    Update $repositories if a new child repository is exposed.

    line 250
  27. Very specific:

    Update getRepositoryAttributes() if child route vars changed.

    line 251
  28. Very specific:

    Update getCreatableAttributes() / getUpdatableAttributes() if persistence shape changed.

    line 252
  29. Very specific:

    Update getRepository() or save() if ownership or permission rules changed.

    line 253
  30. Distinctive:

    Check gateway events and repositories that hydrate or cache the part.

    line 254
  31. Distinctive:

    Add or update tests.

    line 255
  32. Distinctive:

    Keep REST writes and cache writes in sync.

    line 261
  33. Very specific:

    Check owning parts for getRepository() and getRepositoryAttributes() assumptions.

    line 263
  34. Distinctive:

    Update tests and docs if public behavior changed.

    line 264
  35. Distinctive:

    Put payload validation in setters/adders.

    line 268
  36. Distinctive:

    Keep fluent chaining style.

    line 269
  37. Very specific:

    Keep jsonSerialize() aligned with Discord docs and existing payload semantics.

    line 270
  38. Very specific:

    Keep fromPart() edit symmetry in mind.

    line 271
  39. Distinctive:

    Update tests for validation limits and payload shape.

    line 272
  40. Distinctive:

    Update docs/examples if the preferred public construction path changed.

    line 273
  41. Very specific:

    Add or update the event constant in Event.php if needed.

    line 277
  42. Very specific:

    Add or update the handler registration in Handlers.php.

    line 278
  43. Distinctive:

    Update every affected repository and relation cache.

    line 280
  44. Distinctive:

    Keep application-command and prefix-command layers separate.

    line 287
  45. Distinctive:

    Keep interaction typing and resolved-data hydration intact.

    line 288
  46. Distinctive:

    Keep builders as the outbound authoring path for commands, components, and modals.

    line 289
  47. Distinctive:

    Avoid slow interaction-time work that can delay a response.

    line 290
  48. Distinctive:

    Update both inbound event handling and outbound builder/docs surfaces if public behavior shifts.

    line 291
  49. Distinctive:

    If you see one of these, slow down:

    line 295
  50. Distinctive:

    When you need an example worth imitating, start here:

    line 311
  51. Very specific:

    All unit-test classes extend DiscordTestCase.

    line 332
  52. Very specific:

    Use $this->getMockBuilder() for isolated class dependencies and getMockDiscord() when a lightweight real Discord client is needed.

    line 333
  53. Very specific:

    Use and return wait() from tests/functions.php whenever a test performs asynchronous work so PHPUnit tracks it.

    line 334
  54. Distinctive:

    Keep semantic tests focused on behavior, not on incidental implementation details.

    line 335
  55. Distinctive:

    Keep docs in sync when preferred usage or public contracts change.

    line 344
  56. Distinctive:

    When unsure where code belongs, choose the layer that already owns the same kind of knowledge elsewhere in the repo.

    line 364

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

DiscordPHP Agent Guide

This file is the repo operating manual for AI agents. It describes how to work inside this repository without breaking its design. Specialist skills in .agents/skills/ provide deeper playbooks for specific layers.

If a change crosses layers, load multiple skills and use the playbooks in this file to keep boundaries clean.

Start here

Before changing anything:

  1. Identify the layer you are touching.
  2. Read the base abstraction for that layer before copying a concrete class.
  3. Read one representative concrete implementation from the same family.
  4. Trace how that layer connects to adjacent layers.
  5. Make the change in the narrowest layer that can own it.
  6. Update companion surfaces that define the same contract.

In this repo, companion surfaces usually matter as much as the line you edit.

Non-negotiable truths

  1. CLI-only runtime. DiscordPHP is a long-running process built on ReactPHP. Do not design around web requests, controllers, middleware stacks, or per-request state.
  2. Async first. Production I/O is Promise-based. Blocking helpers belong in tests only.
  3. Parts are canonical domain objects. They model Discord resources and expose typed magic properties.
  4. Repositories are persistence and cache boundaries. They are not generic service classes.
  5. Gateway handlers keep caches coherent. They do more than relay notifications.
  6. Builders own outbound payload rules. If a payload has meaningful shape or validation, it usually deserves a builder.
  7. Docblocks are runtime-adjacent documentation. They are not optional decoration.
  8. Traits are preferred over deep inheritance or broad interface hierarchies for shared behavior.
  9. Type maps are central dispatch points. If a Discord payload is polymorphic, there is usually one place that decides the concrete subtype.
  10. Use current library idioms. Prefer Factory::part() / Factory::repository(), prefer $part->save($reason) over repository save($part) in user-facing paths, and prefer builder ->create($repository) helpers where they exist.

Skill map

For Compatibility Watch findings, Discord API/schema drift, or an issue labelled openapi, read the compatibility handoff. Reuse the existing OpenAPI check and issue; retain source/spec revisions and prove affected runtime behavior separately from schema coverage. Do not accept a baseline merely to silence a new finding.

Each skill lives in .agents/skills/<name>/SKILL.md and is loaded automatically when relevant. When a task crosses layers, load multiple skills.

If task touches...Skill to load
Discord.php, startup, intents, cache, loop, gateway connectionruntime-bootstrap-keeper
Parts/*, domain modeling, mutators, typed nested datapart-model-maintainer
Repository/*, endpoint vars, cache, CRUD, fetch/save/deleterepository-cache-keeper
WebSockets/Handlers.php, WebSockets/Event.php, WebSockets/Events/*gateway-cache-sync-keeper
Builders/*, Builders/Components/*, outbound payload rulesbuilder-payload-smith
subtype maps like Channel::TYPES or Interaction::TYPEStype-map-keeper
interactions, slash commands, resolved data, autocomplete, modalsinteraction-flow-keeper
DiscordCommandClient or prefix-command behaviorlegacy-command-client-keeper
tests, guides, docblocks, generated reference expectationsasync-test-and-doc-sync
Voice/*, audio streaming, encryption, voice gateway protocolvoice-subsystem-keeper
Helpers/*, Exceptions/*, cache wrappers, Endpoint::bind(), Collectionhelpers-and-infra-keeper

Architecture map

LayerOwnsPrimary filesWhat to preserve
Runtimeprocess lifecycle, options, loop, gateway, HTTP, root repossrc/Discord/Discord.php__construct() wires dependencies and connects; run() only starts loop
Factorypart/repository instantiationsrc/Discord/Factory/Factory.phpcallers should not construct repo families ad hoc
Partsdomain objects, mutators, typed nested data, high-level operationssrc/Discord/Parts/Part.php, src/Discord/Parts/PartTrait.php, src/Discord/Parts/**/*$fillable, mutators, PHPDoc, save() semantics, created lifecycle
Repositoriestyped collections, cache, REST endpoints, CRUDsrc/Discord/Repository/AbstractRepository.php, src/Discord/Repository/**/*$class, $endpoints, $vars, cache writes, Promise-based API
Buildersoutbound payload construction and validationsrc/Discord/Builders/**/*fluent setters, validation, jsonSerialize(), fromPart() symmetry
Gateway eventspayload hydration, cache mutation, emitted return shapessrc/Discord/WebSockets/Handlers.php, src/Discord/WebSockets/Event.php, src/Discord/WebSockets/Events/*typed part creation, related cache updates, event contract shape
Helperscross-cutting utilities: cache wrappers, BigInt math, multipart uploads, property mutator trait, domain exceptionssrc/Discord/Helpers/*, src/Discord/Exceptions/*no domain logic here; utilities only
Voiceinternal voice protocol types and encryption; runtime integration in Discord.php; audio client in external discord-php-helpers/voice packagesrc/Discord/Voice/*Old* files are legacy — do not extend them; keep protocol and crypto layers separate
Optional command layermessage-prefix command UXsrc/Discord/DiscordCommandClient.php, src/Discord/CommandClient/Command.phpkeep it layered on top of core client, not inside it
Tests and docsbehavioral contracttests/*, guide/*, README.md, docs/*async testing patterns, public guidance, docblock reference surface

External packages

Three external packages are tightly coupled to core runtime behavior. Treat them as first-class parts of the architecture:

PackageWhy it mattersLocal touchpoints
discord-php/httpHTTP client and Endpoint URL template binding used in every repository; handles rate-limiting via Bucket$endpoints arrays in all repositories; use Discord\Http\Endpoint imports
discord-php-helpers/collectionCollection class is the base for every AbstractRepository; discriminator-keyed typed collectionsAbstractRepository extends Collection; $discrim property
discord-php-helpers/voiceManager and VoiceClient implement the actual audio client; src/Discord/Voice/* contains only internal protocol types and encryptionDiscord::joinVoiceChannel(), voice event handlers in Discord.php

When editing endpoint bindings, REST routes, cache storage, or voice audio, you are necessarily touching these packages' contracts.

Repo worldview

Runtime to domain flow

Discord owns bootstrapping. Gateway dispatch goes through Handlers into a dedicated event class. Event classes translate payloads into typed parts and update repositories. Repositories provide cache and REST persistence. Parts expose that state through magic properties and typed helpers. Builders assemble outbound payloads for operations that would otherwise become fragile arrays.

Why the split matters

  • If you put transport logic in parts, parts stop being stable domain objects.
  • If you put domain validation in repositories, repository APIs stop being predictable.
  • If you skip builders, payload rules spread across unrelated methods.
  • If gateway handlers do not update caches correctly, every downstream relation becomes stale.

Common class patterns

Parts

Expect these elements on real resource models:

  • large class-level @property and @property-read docblocks
  • protected $fillable = [...]
  • optional protected $repositories = [...]
  • constants mirroring Discord enums or flags
  • getXAttribute() and setXAttribute() mutators
  • overrides for getCreatableAttributes(), getUpdatableAttributes(), getRepository(), save(), fetch(), or getRepositoryAttributes() when the part is persistable

Semantic rules:

  • raw attribute names stay snake_case to match Discord payloads
  • convenience relations (guild, channel, owner, member) are usually computed, not directly stored
  • nested typed data should become a Part, typed collection, or Carbon value through helper methods
  • permission checks for high-level mutations belong on the part before repository delegation
  • created tells you whether the object already exists remotely
  • a payload that is an existing part's object plus a few fields gets a subclass of that part, which merges only its extra keys into the inherited $fillable
  • a subclass's override declares the narrowest return type it can truly return (PHP return types are covariant), and every path must honour it. For example, GameDirectMessage::getChannelAttribute() returns Channel where Message's returns Part, because a game DM's channel can never be a Thread
  • inherited methods that can never work in a subclass's context return a rejected promise (\BadMethodCallException) instead of sending a request Discord will refuse. See part-model-maintainer for all three
  • parts live under the namespace of the API route they come from: a message, its attachments, reactions and embeds are under Parts\Channel\Message because they come from /channels/{channel.id}/messages. A part that moves keeps its old name working through a class_alias() at the end of src/Discord/functions.php, which Composer loads eagerly, so instanceof, type hints and cached (serialised) data with the old name still work

Repositories

Expect these elements:

  • extends AbstractRepository
  • protected $class = SomePart::class
  • protected $endpoints = [...]
  • optional constructor normalization for route vars
  • occasional domain-specific convenience methods

Semantic rules:

  • repositories are typed collections plus REST/cache wrappers
  • create() builds a local part; save() persists it
  • $vars carries parent route context like guild_id or channel_id
  • cache writes must stay aligned with REST writes and gateway updates
  • special methods should still return typed parts or repositories, not loose payloads

Builders

Expect these elements:

  • extends Builder
  • implements JsonSerializable
  • fluent setX() / getX() methods
  • eager validation in setters or adders
  • new() factory method on most builders
  • create($repository) helper on newer builders

Semantic rules:

  • builders are not parts and should not own persistence or cache logic
  • validation belongs here when it describes outgoing payload shape
  • jsonSerialize() should omit unset optionals when Discord distinguishes missing from explicit null
  • fromPart() should make edit flows symmetrical

Gateway events

Expect these elements:

  • one class per event type under src/Discord/WebSockets/Events
  • matching constant in src/Discord/WebSockets/Event.php
  • matching registration in src/Discord/WebSockets/Handlers.php
  • handle($data) method returning typed semantic values

Semantic rules:

  • event handlers should hydrate the right subtype on first read
  • event handlers are responsible for repository/cache coherence
  • update events often return both new and old state
  • delete events often return cached removed state, not only the raw payload id
  • related user/member caches usually need updating too

Cross-layer rules

1. Parts delegate persistence; repositories own REST

If a part can be saved:

  • the part decides whether the action is allowed and which repository owns it
  • the repository decides how to call Discord and update cache

Smell: a part method manually building endpoints and PATCH payloads when a repository already exists for that family.

2. Parts own semantics; builders own payload ergonomics

If userland needs to construct a non-trivial outbound payload:

  • add or extend a builder
  • keep raw-array construction as an implementation detail only when a builder would be needless overhead

Smell: multiple methods assembling the same nested array by hand.

3. Gateway events own reactive cache updates

If Discord can tell us something through gateway dispatch:

  • prefer updating cache from the event instead of forcing later REST refetches
  • keep parent/child repository relationships coherent at the same time

Smell: event handler creates a part but does not update the repository that should own it.

4. Traits carry horizontal behavior

The codebase prefers traits for shared capabilities across sibling models.

Examples:

  • PartTrait for universal part mechanics
  • ChannelTrait for channel/thread behavior
  • GuildTrait for guild asset and feature helpers
  • DynamicPropertyMutatorTrait for builder/property mutators (src/Discord/Helpers/DynamicPropertyMutatorTrait.php)
  • AbstractRepositoryTrait for repository collection mechanics
  • ComponentsTrait for shared component helpers across builders (src/Discord/Builders/ComponentsTrait.php)
  • VoiceGroupCryptoTrait for voice channel encryption/decryption

Smell: new abstract intermediate base class that only exists to share a few methods between peers that already have a common root.

5. Type maps beat repeated branching

When a Discord discriminator chooses a subtype:

  • extend the relevant TYPES map
  • update all materialization sites that depend on that family

Smell: one event handler special-cases a new subtype but the central type map still does not know it.

Common companion surfaces

If you touch one of these, inspect the companions too:

TouchingAlso inspect
src/Discord/Parts/Part.php or PartTrait.phprepresentative parts, PartInterface, generated docblocks
a concrete Partowning repository, related trait, event handlers, tests, docs
a nested repository relationshipparent part $repositories, getRepositoryAttributes(), repository constructor vars
src/Discord/Repository/AbstractRepository*representative repos, cache wrapper behavior, part save/fetch overrides
a gateway event classEvent.php, Handlers.php, related part/repository, tests
a buildermatching part, callers, tests, docs/examples
Channel::TYPES, Interaction::TYPES, component/ embed mapsevent handlers, typed collection helpers, builder mirrors
DiscordCommandClientCommandClient/Command.php, examples/docs
public magic propertiesclass PHPDoc, guide docs if user-facing behavior changed
Helpers/CacheWrapper.php or cache configAbstractRepository cache behavior, Discord.php options['cache'] wiring
Voice/* or voice event in Discord.phpVoiceGroupCrypto, VoicePacket, external voice package entry points, voice opcodes

Change playbooks

Playbook: editing a Part

  1. Update $fillable.
  2. Add or adjust mutators for typed nested data, computed properties, or normalization.
  3. Update class docblocks.
  4. Update $repositories if a new child repository is exposed.
  5. Update getRepositoryAttributes() if child route vars changed.
  6. Update getCreatableAttributes() / getUpdatableAttributes() if persistence shape changed.
  7. Update getRepository() or save() if ownership or permission rules changed.
  8. Check gateway events and repositories that hydrate or cache the part.
  9. Add or update tests.

Playbook: editing a Repository

  1. Confirm $class, $discrim, and $endpoints still describe the family correctly.
  2. Confirm parent route vars are complete and in the correct shape.
  3. Keep REST writes and cache writes in sync.
  4. Return typed values.
  5. Check owning parts for getRepository() and getRepositoryAttributes() assumptions.
  6. Update tests and docs if public behavior changed.

Playbook: editing a Builder

  1. Put payload validation in setters/adders.
  2. Keep fluent chaining style.
  3. Keep jsonSerialize() aligned with Discord docs and existing payload semantics.
  4. Keep fromPart() edit symmetry in mind.
  5. Update tests for validation limits and payload shape.
  6. Update docs/examples if the preferred public construction path changed.

Playbook: editing a gateway event

  1. Add or update the event constant in Event.php if needed.
  2. Add or update the handler registration in Handlers.php.
  3. Hydrate the correct subtype.
  4. Update every affected repository and relation cache.
  5. Preserve event return shape expected by userland listeners.
  6. Cache related users/members if the payload supplies them.
  7. Re-check any intent-gated or partial-data behavior.

Playbook: editing interactions or commands

  1. Keep application-command and prefix-command layers separate.
  2. Keep interaction typing and resolved-data hydration intact.
  3. Keep builders as the outbound authoring path for commands, components, and modals.
  4. Avoid slow interaction-time work that can delay a response.
  5. Update both inbound event handling and outbound builder/docs surfaces if public behavior shifts.

Design tripwires

If you see one of these, slow down:

  • a new raw nested array where a typed part already exists
  • a repository method returning raw decoded payload instead of a part
  • a part saving itself with hand-built endpoints even though an owning repository exists
  • a new subtype without a TYPES map entry
  • a magic property added in code but not in docblocks
  • a gateway handler that updates one cache but leaves related repositories stale
  • a synchronous wait or loop-stop trick outside tests
  • a new abstraction layer that duplicates what parts, repositories, events, or builders already do
  • web-framework terminology creeping into core runtime code
  • extending OldVoiceClient or any Old* class in src/Discord/Voice/ unless deliberately fixing legacy behavior
  • bypassing Endpoint::bind() with hand-assembled raw URL strings

Preferred reference files

When you need an example worth imitating, start here:

  • Runtime orchestration: src/Discord/Discord.php
  • Base part mechanics: src/Discord/Parts/Part.php, src/Discord/Parts/PartTrait.php
  • Rich part model: src/Discord/Parts/Guild/Guild.php
  • Channel/resource semantics: src/Discord/Parts/Channel/Channel.php
  • Message semantics and repository binding: src/Discord/Parts/Channel/Message/Message.php
  • Repository baseline: src/Discord/Repository/AbstractRepository.php, src/Discord/Repository/AbstractRepositoryTrait.php
  • Simple repo specialization: src/Discord/Repository/Channel/MessageRepository.php
  • Rich repo specialization: src/Discord/Repository/GuildRepository.php
  • Outbound builder style: src/Discord/Builders/MessageBuilder.php
  • Interaction typing: src/Discord/Parts/Interactions/Interaction.php
  • Gateway cache mutation: src/Discord/WebSockets/Events/MessageCreate.php, src/Discord/WebSockets/Events/GuildCreate.php
  • Optional command layer: src/Discord/DiscordCommandClient.php, src/Discord/CommandClient/Command.php
  • Cache infrastructure: src/Discord/Helpers/CacheWrapper.php, src/Discord/Helpers/CacheConfig.php
  • Voice protocol and encryption: src/Discord/Voice/VoiceGroupCrypto.php, src/Discord/Voice/VoicePacket.php

Testing and docs workflow

Tests

  • All unit-test classes extend DiscordTestCase.
  • Use $this->getMockBuilder() for isolated class dependencies and getMockDiscord() when a lightweight real Discord client is needed.
  • Use and return wait() from tests/functions.php whenever a test performs asynchronous work so PHPUnit tracks it.
  • Keep semantic tests focused on behavior, not on incidental implementation details.
  • When a test requires a live Discord or MessageCommandClient instance (for example, to exercise registration, event handling, or runtime integration), obtain it via the wait(function (Discord $discord, $resolve) { ... }) pattern and return that wait() call. Use $this->getMockBuilder() for isolated class dependencies and getMockDiscord() when a lightweight real client is needed without network access.

Docs

  • Public magic properties, repositories, and helpers should be reflected in PHPDoc.
  • Long-form guides live in guide/.
  • Gatsby docs live in docs/.
  • Keep docs in sync when preferred usage or public contracts change.

Useful commands

PurposeCommand
main PHPUnit suitecomposer unit
static analysiscomposer run-script mago-lint
formatter contributors runcomposer run-script cs
non-mutating Pint check./vendor/bin/pint --test --config ./pint.json ./src
Pint formatter (auto-fix)composer pint
test coverage reportcomposer coverage
compare with Discord's live OpenAPI descriptioncomposer openapi (-- --all lists the known gaps too)
accept the live spec and today's gaps as the baselinecomposer openapi:update
docs buildcd docs && yarn install && yarn build

Integration tests expect .env values for DISCORD_TOKEN, TEST_CHANNEL, and TEST_CHANNEL_NAME. Without DISCORD_TOKEN the suite runs offline: tests that answer requests with getMockHttpDriver() run, and only those that call $this->channel() skip. .github/workflows/tests.yml runs it that way on every push and pull request; unit.yml runs it live, by hand.

Final rule

When unsure where code belongs, choose the layer that already owns the same kind of knowledge elsewhere in the repo. Matching the existing ownership model matters more than shaving a few lines off one class.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.