Agent skill

Part Model Maintainer

by discord-php in discord-php/DiscordPHP

Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings.

MITAuto-check passedDevelopment

Install Part Model Maintainer

skills CLI
$ npx skills add discord-php/DiscordPHP --skill part-model-maintainer -a claude-code

Project install by default; add -g for ~/.claude/skills/.

GitHub CLI
$ gh skill install discord-php/DiscordPHP part-model-maintainer --agent claude-code

Project scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).

Manual copy
$ git clone --depth 1 https://github.com/discord-php/DiscordPHP.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/part-model-maintainer .claude/skills/part-model-maintainer && rm -rf skills-src

Use ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.

Claude Code skills documentation · loads skills from .claude/skills/

Facts

Skill name
part-model-maintainer
GitHub stars
1.1k
Token cost
~3.4k tokens
SKILL.md length
1,734 words
Files
1
Skills in repo
14
Repo updated
First seen
Licence
MIT

At a glance

Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings.

  • Works in 5 steps: src/Discord/Parts/Part.php → src/Discord/Parts/PartTrait.php → Representative concrete parts for the… → …
  • Modifying any Discord Part class
  • SKILL.md covers Goal, Read in this order, Core contract and Meaning of common properties, plus 4 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Part Model Maintainer is an agent skill from discord-php/DiscordPHP. Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings. Use when adding or modifying any Discord Part class.

Its SKILL.md is about 3.4k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.

It sits in Development. It works with Discord and PHP. The repository describes itself as: An API to interact with the popular messaging app Discord. The licence is MIT.

When your agent uses it

  • Modifying any Discord Part class

Example prompts

  • “/part-model-maintainer”

Workflow steps

5 steps, taken from the first numbered list in SKILL.md.

  1. src/Discord/Parts/Part.php
  2. src/Discord/Parts/PartTrait.php
  3. Representative concrete parts for the family you are touching
  4. The owning repository for the part
  5. Gateway events that hydrate or update the part

What it can do on your machine

Read from SKILL.md and the folder at commit 580c66a. It shows what the files ask for, not the result of running them.

  • Tool permissions

    Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.

    From allowed-tools in the SKILL.md frontmatter.

  • Runs code

    No scripts in the folder and no shell commands in SKILL.md.

    From the folder's file list and the shell code blocks in SKILL.md.

  • Network

    No URLs in SKILL.md.

    From URLs in SKILL.md, links to its own repository left out.

  • Credentials

    Names no API keys, tokens, secrets or passwords.

    From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.

Context cost

Part Model Maintainer loads about 3.4k tokens when it runs. Until then it costs about 57 tokens; SKILL.md has 1,734 words of instructions outside code blocks.

Always · name and description, kept in context so the agent knows when to use it
~57
When it runs · the whole SKILL.md, loaded when a task matches
~3.4k

Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.

Safety

Auto-check passed

The automated check found no risky patterns in SKILL.md.

Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.

SKILL.md

The full file from discord-php/DiscordPHP at commit 580c66a, republished under its MIT licence (© discord-php). 1,734 words, ~3,374 tokens.

Download SKILL.mdSave it as .claude/skills/part-model-maintainer/SKILL.md (or your agent's skills folder).
name
part-model-maintainer
description
Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings. Use when adding or modifying any Discord Part class.

Skill: part-model-maintainer

Use this skill when work touches src/Discord/Parts/**/*.

This is not syntax guard. This is domain-model guard. Load it when changing what a Discord resource is, how it is hydrated, how it exposes related objects, or how it saves itself.

Goal

Keep Part classes as the canonical in-memory representation of Discord resources:

  • raw API-shaped data lives in attributes
  • typed access lives through mutators and helpers
  • persistence delegates to repositories
  • permission and high-level domain rules stay close to the part
  • public magic surface stays documented

Read in this order

  1. src/Discord/Parts/Part.php
  2. src/Discord/Parts/PartTrait.php
  3. Representative concrete parts for the family you are touching:
    • src/Discord/Parts/Guild/Guild.php
    • src/Discord/Parts/Channel/Channel.php
    • src/Discord/Parts/Channel/Message/Message.php
    • src/Discord/Parts/User/User.php
    • src/Discord/Parts/Guild/Member/Member.php
    • src/Discord/Parts/Channel/Thread/Thread.php
    • src/Discord/Parts/Interactions/Interaction.php
  4. The owning repository for the part
  5. Gateway events that hydrate or update the part

Do not start from a random leaf class alone. PartTrait defines most real behavior.

Core contract

Every real part sits on same base contract:

  • extends Discord\Parts\Part
  • inherits PartTrait
  • constructed with (Discord $discord, array $attributes = [], bool $created = false)
  • stores raw Discord payload fields in $attributes
  • only mass-assigns keys in $fillable
  • exposes related repositories from $repositories
  • resolves computed or typed values through get{Studly}Attribute()
  • normalizes writes through set{Studly}Attribute()
  • persists through getRepository() + save()

If change breaks one of those assumptions, stop and re-check layer ownership.

Meaning of common properties

$fillable

Whitelist for fill() and dynamic writes. If field is missing here:

  • gateway hydration ignores it
  • REST fetch hydration ignores it
  • direct $part->field = ... writes do not persist to $attributes
  • magic property docblocks become misleading

When adding new API field, first ask: should this be part of canonical stored state? If yes, add it to $fillable.

$attributes

Raw storage. Usually snake_case and Discord-shaped. Avoid putting derived state here unless the API itself uses that field.

$repositories

Map of magic property name to repository class. This is how parts expose child collections like:

  • $guild->channels
  • $channel->messages
  • $message->reactions

If child data should behave like a repository, wire it here. Do not fake repo behavior with arrays.

$created

Tracks whether part already exists on Discord side.

  • false means local draft or partial unsaved object
  • true means known remote object

Repository save() uses this to choose POST vs PATCH. Nested createOf() links child created state back to parent. Preserve that when materializing nested parts.

Core methods and what they mean

fill(array $attributes)

Hydrates only fillable keys. It is not "dump every payload field in object". If new data is not appearing after fetch/event handling, check $fillable first.

getAttribute() / __get()

Resolution order matters:

  1. repository from $repositories
  2. getter mutator
  3. raw attribute
  4. null

This is why magic properties can expose both repositories and computed values. Preserve this behavior when adding convenience fields.

__isset() / offsetExists()

Both return getAttribute($key) !== null, so isset(), empty() and ?? agree with __get(). Repositories and mutators count, and a computed relation such as guild is set only while it resolves. Collection::get($attr, $value) relies on this to match parts by any attribute. Inside a part, isset($this->guild_id) reads through the mutator too; use isset($this->attributes['x']) only when you mean the raw payload key. Do not call isset($this->x) from getXAttribute() itself: PHP's recursion guard makes that inner check false.

setAttribute() / __set()

Setter mutator first, then raw write only if key is fillable. This protects parts from accidental shape drift. Do not bypass it by writing stray protected properties for true resource state.

getCreatableAttributes() / getUpdatableAttributes()

These define what the repository sends to Discord. They are not debug dumps. They should express API intent:

  • required vs optional
  • create vs update differences
  • omit optional values that were never set when API cares about missing vs null

Prefer makeOptionalAttributes() to avoid serializing absent optional fields.

getRepository()

Returns the owning repository for this part instance. This is frequently context-sensitive:

  • Guild returns top-level $discord->guilds
  • Channel chooses guild channels vs private channels
  • Message chooses channel messages vs webhook messages
  • Member depends on guild_id
  • Thread depends on parent channel

When repository ownership depends on parent IDs, also inspect getRepositoryAttributes().

save(?string $reason = null)

Part-level save() is where high-level semantic guards live:

  • permission checks
  • ownership routing
  • special-case endpoints for current user/current member/group DM/webhook cases

Rule: if logic needs knowledge of what operation means, it likely belongs here. If logic only knows how to execute REST+cache, it belongs in repository.

fetch()

Only override when part can be refreshed independently from Discord and that contract is meaningful. If part is not fetchable, default runtime exception is fine.

Helper methods to prefer

attributeCarbonHelper($key)

Use for timestamp-ish fields. Keeps repeated Carbon::parse logic out of concrete parts.

attributePartHelper($key, $class, $extraData = [])

Use when field is a nested Discord object and you want lazy typed hydration with caching in $attributes.

Good for:

  • nested User
  • nested Guild
  • nested Message
  • nested message metadata objects
attributeCollectionHelper($key, $class, ?string $discrim = 'id', ?array $extraData = [])

Use for homogeneous nested collections of one concrete part type.

attributeTypedCollectionHelper($class, $key)

Use when payload element type decides subclass at runtime. This is important for:

  • message components
  • other subtype families with TYPES maps
createOf(string $class, array|object $data)

Prefer this over raw factory calls for nested child parts because it preserves created linkage.

Part design patterns already used in repo

Raw ID plus resolved relation

Common pair:

  • raw: guild_id, channel_id, owner_id
  • resolved: guild, channel, owner

Keep both if the API provides IDs and the library benefits from relation convenience.

Constants as public vocabulary

Large resource parts publish Discord enum values and flags as class constants. Keep aliases when the project already supports deprecated constant names for compatibility.

Traits for shared semantics

If behavior applies horizontally across siblings, prefer trait:

  • ChannelTrait
  • GuildTrait

Do not introduce a new intermediate abstract class unless there is truly no cleaner trait shape.

PHPDoc as magic surface contract

Update class docblock whenever you add:

  • fillable raw field
  • computed read-only property
  • repository property
  • new typed collection

If code and docblock drift, IDE help and generated reference docs drift too.

Save and routing playbook

When making a part persistable or changing save behavior:

  1. Define or update getCreatableAttributes()
  2. Define or update getUpdatableAttributes()
  3. Define or update getRepository()
  4. Define or update save()
  5. Define or update getRepositoryAttributes()
  6. Inspect owning repository endpoint vars
  7. Inspect gateway events that hydrate/update the part
Examples worth copying
  • Channel::save() handles guild permission checks and group-DM special case before repository delegation
  • Message::save() handles send/manage permissions and webhook message routing
  • Member::save() handles current-member special route instead of generic repository save
  • Thread::save() blocks unsupported creation path and redirects callers to Channel::startThread()
Show full SKILL.md (682 more words)Show less

Nested data playbook

When new Discord payload includes nested object:

  1. Ask if repo already has a Part type for it
  2. If yes, add field to $fillable
  3. Add getter mutator using helper
  4. Add docblock type
  5. If nested collection, choose homogeneous vs typed collection helper
  6. If nested item needs parent IDs, pass extraData

Do not leave meaningful nested objects as raw arrays if equivalent typed part exists.

Repository-binding playbook

When child repository routes depend on parent context:

  1. expose repository in $repositories
  2. make sure parent part has required IDs in $attributes
  3. override getRepositoryAttributes() when raw $attributes is not enough or not in right shape
  4. inspect repository constructor for $vars assumptions

Examples:

  • channels need guild_id and channel_id
  • messages need channel_id, maybe guild_id, maybe webhook context
  • members need guild_id

Extending a concrete part

When a payload is an existing part's object plus a few fields, extend that part rather than copying its fields or adding the extras to it. Example: the GAME_DIRECT_MESSAGE_* payload is Discord's message object with the DM channel attached, so GameDirectMessage extends Message.

  • Fields: declare only the extra keys, and merge them into the inherited $fillable in the constructor before parent::__construct(), so the subclass keeps up as the parent gains fields.
  • Narrow return types whenever possible. When an override can only ever return a subset of what the parent declares, declare the narrowest type it truly returns; PHP allows covariant return types. Message::getChannelAttribute() returns Part because a guild message's channel may be a Thread, which extends Part, not Channel. A game DM's channel is only a DM or GroupDM, so GameDirectMessage::getChannelAttribute() returns Channel.
  • When it is not possible: the return type has already shipped on a class users may extend. A user subclass overriding the method with the old type would then fatal, so narrow it only in a major release. New classes and new overrides have no such constraint.
  • Make every path honour the narrower type:
    • don't return parent::method() when the parent's declared type is broader;
    • don't hydrate through a TYPES map that also holds types outside it (Channel::TYPES maps thread types to Thread subclasses). Choose from the subset, falling back to one of its members.
  • Inherited methods that cannot work in the subclass's context (for example, REST calls through a channel the bot is not in):
    • override them to return reject(new \BadMethodCallException(...)), naming the method and what to use instead, rather than sending a request Discord will refuse or throwing synchronously;
    • return false from boolean guards such as isDeletable();
    • keep the parent's exact signature, including by-reference parameters.
  • Tests:
    • assert the narrowed type on every path, including a payload that would have produced a type outside it;
    • assert each rejected method rejects without sending a request.

Smells

Stop if you see:

  • an override declaring the parent's broad return type when it can only ever return a narrower one
  • a subclass that copies its parent's $fillable instead of merging its extra keys
  • an inherited method left to fail at Discord, or to throw, when the subclass knows it can never work
  • raw arrays where typed nested parts already exist
  • new field added to docblock but not to $fillable
  • save() building raw endpoints even though repository exists
  • permission check added only in repository while part clearly knows semantic action
  • part state stored in new ad hoc property instead of $attributes
  • child repository added without getRepositoryAttributes() support
  • subtype family added without updating a TYPES map or typed collection helper path

Checklist before commit

  • $fillable matches intended canonical fields
  • getter/setter mutators added where typing or normalization needed
  • $repositories updated if new child collection exposed
  • getCreatableAttributes() / getUpdatableAttributes() express API semantics
  • getRepository() and getRepositoryAttributes() route correctly
  • save() enforces semantic permission or special-case behavior when needed
  • class docblock reflects public magic surface
  • a subclass's overrides declare the narrowest return type every path honours
  • related repository and gateway event code still coherent
  • tests/docs updated if public behavior changed

Bottom line

Part classes in this repo are not dumb DTOs and not service objects. They are typed, lazily-resolved domain resources with controlled hydration and repository-backed persistence. Keep them centered on that job.

© discord-php, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file

Files

Just SKILL.md in .agents/skills/part-model-maintainer of discord-php/DiscordPHP.

Open the folder on GitHubat commit 580c66a

Compare with similar skills

Part Model Maintainer next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.

Part Model Maintainer compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Part Model Maintainer this skilldiscord-php/DiscordPHP1.1k—~3.4kAutomated safety check: PassMIT
WooCommerce Code Reviewwoocommerce/woocommerce11k3 repos~1.1kAutomated safety check: PassCustom licence
Skill Doli Code ReviewDolibarr/dolibarr7.7k1 repos~1.1kAutomated safety check: PassMIT
Bug Triagesymfony/symfony31k—~1.9kAutomated safety check: PassMIT
Merge Upsymfony/symfony31k—~4kAutomated safety check: PassMIT
Wp Interactivity APIAutomattic/agent-skills2113 repos~1.5kAutomated safety check: PassNone

Similar skills

  • WooCommerce Code Review

    woocommerce/woocommerce

    Reviews WooCommerce code changes against the project's standards, flagging backend PHP architecture, naming, documentation, data integrity and testing violations.

    11k GitHub starsUsed in 3 repos~1.1k tokens
    DevelopmentAuto-check passed
  • Skill Doli Code Review

    Dolibarr/dolibarr

    Reviews Dolibarr PHP code for compliance with coding standards and security best practices, and fixes identified issues.

    7.7k GitHub starsUsed in 1 repo~1.1k tokens
    DevelopmentAuto-check passed
  • Bug Triage

    symfony/symfony

    Decide whether open Bug PRs target the correct branch. An agent skill from symfony/symfony.

    31k GitHub stars~1.9k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Merge Up

    symfony/symfony

    Cascade-merge maintained Symfony branches from oldest to newest (e.g.

    31k GitHub stars~4k tokensUpdated yesterday
    DevelopmentAuto-check passed
  • Wp Interactivity API

    Automattic/agent-skills

    A skill your agent uses when building or debugging WordPress Interactivity API features (data-wp- directives, @wordpress/interactivity store/state/actions, block viewScriptModule integration…

    211 GitHub starsUsed in 3 repos~1.5k tokens
    DevelopmentAuto-check passed
  • PR Merge

    symfony/symfony

    Merge a reviewed pull request the way the Symfony core team does: one --no-ff merge commit per PR, whose message archives the whole discussion, with the review gates checked first.

    31k GitHub stars~3.1k tokensUpdated yesterday
    DevelopmentAuto-check passed

More from discord-php/DiscordPHP

All 14 skills in this repo
  • Async Test And Doc Sync

    discord-php/DiscordPHP

    Maintain test and documentation alignment — PHPUnit tests, async testing patterns, PHPDoc contracts, guide pages, and documentation workflow.

    1.1k GitHub stars~3.4k tokensUpdated 2 days ago
    Auto-check: notes
  • Discord Php Bot Security

    discord-php/DiscordPHP

    Audit checklist for DiscordPHP bots and API libraries — stop the bot token leaking to third-party APIs or logs, keep secrets out of customids and exception messages, use constant-time comparison and…

    1.1k GitHub stars~1.2k tokensUpdated 2 days ago
    Auto-check: notes
  • Discord Php Extension

    discord-php/DiscordPHP

    Scaffold and maintain a DiscordPHP-based bot or an API-library-on-DiscordPHP (the DiscordPHP-MTG / DiscordPHP-NHA / DiscordPHP-Sabacc pattern) — client subclass, third-party HTTP layer, Parts…

    1.1k GitHub stars~1.7k tokensUpdated 2 days ago
    Auto-check passed
  • Discord Php Interactions

    discord-php/DiscordPHP

    Build DiscordPHP slash commands and message components — global command trees with subcommands, user- AND guild-installable commands usable in DMs / group DMs / guild channels, Components V2…

    1.1k GitHub stars~1.5k tokensUpdated 2 days ago
    Auto-check passed
  • Helpers And Infra Keeper

    discord-php/DiscordPHP

    Work with DiscordPHP's infrastructure utilities — CacheWrapper, CacheConfig, BigInt, Multipart, Endpoint::bind URL templates, Collection base class, and domain Exceptions.

    1.1k GitHub stars~2.2k tokensUpdated 2 days ago
    Auto-check passed
  • Runtime Bootstrap Keeper

    discord-php/DiscordPHP

    Maintain Discord.php runtime bootstrapping, startup options, event loop, gateway connection, reconnection, member chunking, cache configuration, and process lifecycle.

    1.1k GitHub stars~4k tokensUpdated 2 days ago
    Auto-check passed

Works with

Categories

Questions about Part Model Maintainer

What does Part Model Maintainer do?

Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings. Part Model Maintainer is an agent skill from discord-php/DiscordPHP. Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings.

When should I use Part Model Maintainer?

Part Model Maintainer fits situations like: modifying any Discord Part class.

How do I install Part Model Maintainer in Claude Code?

Run `npx skills add discord-php/DiscordPHP --skill part-model-maintainer -a claude-code`. Or copy the skill folder (.agents/skills/part-model-maintainer in discord-php/DiscordPHP) into .claude/skills/part-model-maintainer in your project. Claude Code loads it when a task matches its description.

How do I install Part Model Maintainer in Codex?

Run `npx skills add discord-php/DiscordPHP --skill part-model-maintainer -a codex`. Or copy the skill folder (.agents/skills/part-model-maintainer in discord-php/DiscordPHP) into .agents/skills/part-model-maintainer in your project. Codex loads it when a task matches its description.

Can I use Part Model Maintainer in Cursor, Gemini CLI or GitHub Copilot?

Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add discord-php/DiscordPHP --skill part-model-maintainer -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/part-model-maintainer, .gemini/skills/part-model-maintainer, .github/skills/part-model-maintainer and .opencode/skills/part-model-maintainer in your project.

What does Part Model Maintainer need to run?

SKILL.md names no scripts, command-line tools or credentials: Part Model Maintainer is instructions for the agent only.

Does Part Model Maintainer access the network?

SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.

Is Part Model Maintainer safe to install?

Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.

What licence does Part Model Maintainer use?

Part Model Maintainer is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.

How many tokens does Part Model Maintainer use?

About 3.4k tokens (SKILL.md is roughly 13k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.

What are the alternatives to Part Model Maintainer?

Skills that share tags, products or a category with Part Model Maintainer: WooCommerce Code Review (woocommerce/woocommerce, 11k stars), Skill Doli Code Review (Dolibarr/dolibarr, 7.7k stars), Bug Triage (symfony/symfony, 31k stars) and Merge Up (symfony/symfony, 31k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Part Model Maintainer?

discord-php (a GitHub organization) maintains it in discord-php/DiscordPHP, which has 1,080 GitHub stars. The repository holds 14 skills in this directory. The repository was last updated on October 6, 2026.

Source: discord-php/DiscordPHP on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.