Agent skill

Type Map Keeper

by discord-php in discord-php/DiscordPHP

Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants.

MITAuto-check passed

Install Type Map Keeper

skills CLI
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a claude-code

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

GitHub CLI
$ gh skill install discord-php/DiscordPHP type-map-keeper --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/type-map-keeper .claude/skills/type-map-keeper && 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
type-map-keeper
GitHub stars
1.1k
Token cost
~2.9k tokens
SKILL.md length
1,262 words
Files
1
Skills in repo
14
Repo updated
First seen
Licence
MIT

At a glance

Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants.

  • Works in 5 steps: Gateway event handlers → attributeTypedCollectionHelper() in… → attributePartHelper() for single-object… → …
  • Adding subtypes
  • SKILL.md covers Goal, Read in this order, Core contract and How type maps work, plus 9 more sections
  • Instructions only: no scripts, shell commands, URLs or credentials in SKILL.md

What it does

Type Map Keeper is an agent skill from discord-php/DiscordPHP. Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants. Use when adding subtypes or changing polymorphic dispatch.

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

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

  • Adding subtypes
  • Changing polymorphic dispatch

Example prompts

  • “/type-map-keeper”

Workflow steps

5 steps, taken from the step headings in SKILL.md.

  1. Gateway event handlers
  2. attributeTypedCollectionHelper() in PartTrait
  3. attributePartHelper() for single-object dispatch
  4. Resolved data hydration
  5. Builder alias forwarding

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 (its code samples are php).

    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

Type Map Keeper loads about 2.9k tokens when it runs. Until then it costs about 48 tokens; SKILL.md has 1,262 words of instructions outside code blocks.

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

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,262 words, ~2,858 tokens.

Download SKILL.mdSave it as .claude/skills/type-map-keeper/SKILL.md (or your agent's skills folder).
name
type-map-keeper
description
Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants. Use when adding subtypes or changing polymorphic dispatch.

Skill: type-map-keeper

Use this skill when work touches:

  • any TYPES constant array on a part or builder
  • TYPE_* constants on channel, interaction, component, or embed families
  • code that dispatches by type, component_type, or similar runtime discriminator
  • attributeTypedCollectionHelper() or attributePartHelper() calls that consume a TYPES map
  • ChannelBuilder::TYPES alias or equivalent builder-side mirrors

This is subtype-dispatch skill. Load it when a change adds, removes, or reorganizes how the codebase resolves a polymorphic Discord payload into a concrete PHP class.

Goal

Keep type maps as the single source of truth for polymorphic dispatch:

  • one constant array decides which class represents each discriminator value
  • all materialization sites consume that array instead of branching ad hoc
  • builder-side mirrors stay aligned with inbound part maps
  • fallback at index 0 handles unknown future values safely
  • public TYPE_* constants remain stable vocabulary for userland

Read in this order

  1. src/Discord/Parts/Channel/Channel.php — Channel::TYPES and TYPE_* constants, deprecated aliases
  2. src/Discord/Parts/Interactions/Interaction.php — Interaction::TYPES and TYPE_* constants
  3. src/Discord/Parts/Channel/Message/Embed/Embed.php — Embed::TYPES with string-keyed discriminators
  4. src/Discord/Parts/Channel/Message/Component.php — inbound Component::TYPES map
  5. src/Discord/Builders/Components/ComponentObject.php — outbound ComponentObject::TYPES and TYPE_* constants
  6. src/Discord/Parts/PartTrait.php — attributeTypedCollectionHelper() at line ~530, createOf() at line ~429
  7. src/Discord/Builders/ChannelBuilder.php — ChannelBuilder::TYPES = Channel::TYPES alias
  8. Representative event handlers that dispatch through maps:
    • src/Discord/WebSockets/Events/ChannelCreate.php
    • src/Discord/WebSockets/Events/InteractionCreate.php
    • src/Discord/WebSockets/Events/ThreadListSync.php

Core contract

A TYPES constant is a public const array on the root class of a polymorphic family. Keys are discriminator values (integers or strings) sent by Discord in the type field. Values are fully-qualified class names of concrete subtypes. Index 0 (or equivalent) holds the root class itself as a safe fallback for unrecognized discriminator values.

All code that needs to turn a raw discriminator into a class must look up the map instead of writing its own switch/match/if chain. This keeps subtype knowledge centralized: add one map entry and every dispatch site picks it up automatically.

How type maps work

Map shape
php
public const TYPES = [
    0 => self::class,                       // fallback
    self::TYPE_PING => Ping::class,         // known subtypes
    self::TYPE_APPLICATION_COMMAND => ApplicationCommand::class,
    // ...
];

The discriminator field varies by family: type for channels, interactions, and embeds; type or component_type for components. The attributeTypedCollectionHelper() in PartTrait handles both via $part->type ?? $part->component_type ?? 0.

Dispatch expression

At every materialization site, the pattern is:

php
$class::TYPES[$data->type ?? 0]

This resolves to either a known concrete class or the fallback root class. Event handlers may add a secondary fallback with ?? Channel::class for families like channels that lack an explicit index 0 entry.

Known type map families

Root classDiscriminatorFallbackString keysBuilder mirror
Channeltype (int)none — events use ?? Channel::classnoChannelBuilder::TYPES
Interactiontype (int)index 0 => Interaction::classno—
Embedtype (string)index 0 => Embed::classyes ('rich', 'image', …)—
Component (inbound)type / component_type (int)index 0 via helperno—
ComponentObject (outbound)type (int)index 0 via helpernois the builder side

Component::TYPES and ComponentObject::TYPES are independent arrays that happen to share the same key space and constant names. They map to different class hierarchies — inbound parts vs outbound builders.

Materialization sites

Type maps are consumed in these code paths:

1. Gateway event handlers

Event classes call $this->factory->part(TYPES[$data->type] ?? Fallback::class, ...) to hydrate the correct subtype from raw gateway payloads.

  • ChannelCreate, ChannelUpdate, ChannelDelete use ChannelBuilder::TYPES[$data->type] ?? Channel::class
  • ThreadCreate, ThreadUpdate, ThreadDelete, ThreadListSync use the same channel map
  • InteractionCreate uses Interaction::TYPES[$data->type ?? 0]
2. attributeTypedCollectionHelper() in PartTrait

Called by mutators like Message::getEmbedsAttribute() and Message::getComponentsAttribute() to build typed collections from raw payload arrays:

php
$part = $this->createOf($class::TYPES[$part->type ?? $part->component_type ?? 0], $part);
3. attributePartHelper() for single-object dispatch

Used by Section::getAccessoryAttribute(), Label::getComponentAttribute(), and Component::getComponentAttribute() to resolve a single nested object:

php
return $this->attributePartHelper('accessory', Component::TYPES[$this->attributes['accessory']->type ?? 0]);
4. Resolved data hydration

Resolved::getChannelsAttribute() uses ChannelBuilder::TYPES[$channel->type] ?? Channel::class to hydrate resolved channels from interaction payloads.

5. Builder alias forwarding

ChannelBuilder::TYPES = Channel::TYPES makes the builder a transparent proxy. Event handlers reference ChannelBuilder::TYPES so the builder layer can theoretically override mapping without changing the part, though today both are identical.

Adding a new subtype

Follow this sequence:

  1. Add TYPE_* constant on the root class, matching the Discord API integer/string value.
  2. Create the concrete class extending the root part (or sibling base). Keep it in the same namespace family.
  3. Add the map entry in the root class TYPES array, keyed by the new constant.
  4. Update event handlers — any gateway event that hydrates this family will automatically pick up the new entry if it reads TYPES. Verify the fallback expression still works.
  5. Update builder-side mirror if one exists. For channels, ChannelBuilder::TYPES is an alias so it picks up changes automatically. For components, ComponentObject::TYPES must be updated independently.
  6. Update typed collection helpers — if the new subtype appears in a collection context (embeds, components), confirm attributeTypedCollectionHelper() resolves it.
  7. Add docblocks and @property annotations on parent parts if the subtype surfaces through typed collections.
  8. Update $fillable and any subtype-specific mutators, repositories, or permission checks.
  9. Preserve deprecated aliases if the new constant replaces an older name.
Show full SKILL.md (503 more words)Show less

Builder-side mirrors

The component family has independent inbound and outbound type maps:

  • Inbound: Component::TYPES under src/Discord/Parts/Channel/Message/Component.php maps to part classes like ActionRow, Button, StringSelect (the inbound representations).
  • Outbound: ComponentObject::TYPES under src/Discord/Builders/Components/ComponentObject.php maps to builder classes like ActionRow, Button, StringSelect (the builder representations).

Both maps share the same TYPE_* integer constants defined on ComponentObject. When Discord adds a new component type, both maps must be extended. Missing one side means either inbound deserialization or outbound construction silently falls back to the wrong class.

For channels, ChannelBuilder::TYPES = Channel::TYPES is a simple alias, so there is no independent map to forget. But if channel builder logic ever diverges, the alias approach should be revisited.

Fallback behavior

Index 0 is the conventional fallback key. When Discord introduces a type value the library does not yet support:

  • Interaction::TYPES[0] resolves to Interaction::class — a safe generic interaction
  • Embed::TYPES[0] resolves to Embed::class — a safe generic embed
  • Channel::TYPES has no index 0, so event handlers append ?? Channel::class as explicit fallback

The attributeTypedCollectionHelper() defaults to $part->type ?? $part->component_type ?? 0, which falls through to index 0 when neither field is present.

New families should include an explicit index 0 fallback pointing to the root class. Relying on ?? RootClass::class at every call site is fragile and easy to forget.

Constants as public vocabulary

TYPE_* constants serve as stable API for userland code:

php
if ($channel->type === Channel::TYPE_GUILD_VOICE) { ... }
Naming convention
  • Prefix: TYPE_ (always)
  • Body: uppercase snake_case matching Discord's enum name (e.g., TYPE_GUILD_TEXT, TYPE_APPLICATION_COMMAND)
  • Constants are defined on the root class, not on subtypes
Deprecated alias preservation

When Discord renames a concept, keep the old constant as a deprecated alias:

php
/** @deprecated 10.0.0 Use `Channel::TYPE_GUILD_ANNOUNCEMENT` */
public const TYPE_NEWS = self::TYPE_GUILD_ANNOUNCEMENT;

Channel.php carries over a dozen such aliases. Do not remove them without a major version bump. Add @deprecated with the version and migration target.

Smells

Stop if you see:

  • new subtype class created but no entry added to the family TYPES map
  • hardcoded if ($type === 5) branch when a map lookup would work
  • builder-side component map updated but inbound Component::TYPES left stale, or vice versa
  • event handler using its own local type-to-class mapping instead of the canonical TYPES constant
  • attributeTypedCollectionHelper() called with a class whose TYPES constant does not exist
  • missing fallback causing crash on unknown discriminator value from a newer Discord API version
  • deprecated constant alias removed without major version bump
  • TYPE_* constant defined on a subtype instead of the root class

Checklist before commit

  • TYPE_* constant added or updated on the root class
  • TYPES map entry added with constant key → class value
  • Concrete subtype class created in same namespace family
  • Fallback index 0 present or explicit ?? RootClass::class at all dispatch sites
  • Builder-side mirror updated if family has one (ComponentObject::TYPES, ChannelBuilder::TYPES)
  • Event handlers verified — they should pick up new type automatically via map lookup
  • attributeTypedCollectionHelper() and attributePartHelper() callers verified
  • Deprecated aliases preserved with @deprecated docblock if renaming
  • Docblocks on root class updated for new constant
  • Tests cover the new subtype's basic instantiation and type resolution

Bottom line

Type maps centralize subtype dispatch so that adding a new Discord payload variant is a map entry, not a codebase-wide scavenger hunt through branching logic.

© 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/type-map-keeper of discord-php/DiscordPHP.

Open the folder on GitHubat commit 580c66a

Compare with similar skills

Type Map Keeper 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.

Type Map Keeper compared with similar skills
SkillStarsUsed inTokensAuto-checkLicenceRepo updated
Type Map Keeper this skilldiscord-php/DiscordPHP1.1k—~2.9kAutomated safety check: PassMIT
Agent Browser CLIvercel-labs/agent-browser44k24 repos~864Automated safety check: PassApache-2.0
Configuring Horizoncoollabsio/coolify63k4 repos~898Automated safety check: PassMIT
Tailwindcss Developmentanonaddy/anonaddy4.9k10 repos~865Automated safety check: PassMIT
Fortify Developmentcoollabsio/coolify63k4 repos~1.9kAutomated safety check: PassMIT
MCP Developmentcoollabsio/coolify63k1 repos~949Automated safety check: PassMIT

Similar skills

  • Agent Browser CLI

    vercel-labs/agent-browser

    Official

    Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…

    44k GitHub starsUsed in 24 repos~864 tokens
    Productivity & AutomationAuto-check passed
  • Configuring Horizon

    coollabsio/coolify

    A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.

    63k GitHub starsUsed in 4 repos~898 tokens
    Backend & APIsAuto-check passed
  • Tailwindcss Development

    anonaddy/anonaddy

    Always invoke when the user's message includes 'tailwind' in any form.

    4.9k GitHub starsUsed in 10 repos~865 tokens
    Frontend & DesignAuto-check passed
  • Fortify Development

    coollabsio/coolify

    ACTIVATE when the user works on authentication in Laravel. An agent skill from coollabsio/coolify.

    63k GitHub starsUsed in 4 repos~1.9k tokens
    Backend & APIsAuto-check passed
  • MCP Development

    coollabsio/coolify

    A skill your agent uses for Laravel MCP development. An agent skill from coollabsio/coolify.

    63k GitHub starsUsed in 1 repo~949 tokens
    Frontend & DesignAuto-check passed
  • Electron App Automation

    vercel-labs/agent-browser

    Official

    Automates Electron desktop apps such as VS Code, Slack or Discord by connecting agent-browser to their Chrome DevTools Protocol port.

    44k GitHub starsUsed in 5 repos~1.7k tokens
    Productivity & AutomationAuto-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 yesterday
    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 yesterday
    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 yesterday
    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 yesterday
    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 yesterday
    Auto-check passed
  • Part Model Maintainer

    discord-php/DiscordPHP

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

    1.1k GitHub stars~3.4k tokensUpdated yesterday
    Auto-check passed

Works with

Questions about Type Map Keeper

What does Type Map Keeper do?

Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants. Type Map Keeper is an agent skill from discord-php/DiscordPHP. Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants.

When should I use Type Map Keeper?

Type Map Keeper fits situations like: adding subtypes; changing polymorphic dispatch.

How do I install Type Map Keeper in Claude Code?

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

How do I install Type Map Keeper in Codex?

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

Can I use Type Map Keeper 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 type-map-keeper -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/type-map-keeper, .gemini/skills/type-map-keeper, .github/skills/type-map-keeper and .opencode/skills/type-map-keeper in your project.

What does Type Map Keeper need to run?

SKILL.md names no scripts, command-line tools or credentials: Type Map Keeper is instructions for the agent only.

Does Type Map Keeper 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 Type Map Keeper 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 Type Map Keeper use?

Type Map Keeper 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 Type Map Keeper use?

About 2.9k tokens (SKILL.md is roughly 11k 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 Type Map Keeper?

Skills that share tags, products or a category with Type Map Keeper: Agent Browser CLI (vercel-labs/agent-browser, 44k stars), Configuring Horizon (coollabsio/coolify, 63k stars), Tailwindcss Development (anonaddy/anonaddy, 4.9k stars) and Fortify Development (coollabsio/coolify, 63k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.

Who maintains Type Map Keeper?

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.