Agent Browser CLI
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
Maintain TYPES maps and subtype dispatch — Channel::TYPES, Interaction::TYPES, Component types, and related constants.
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install discord-php/DiscordPHP type-map-keeper --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ 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-srcUse ~/.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/
Install the "type-map-keeper" agent skill from https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeper into .claude/skills/type-map-keeper/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "type-map-keeper", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeperType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install discord-php/DiscordPHP type-map-keeper --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/discord-php/DiscordPHP.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/type-map-keeper .agents/skills/type-map-keeper && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "type-map-keeper" agent skill from https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeper into .agents/skills/type-map-keeper/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "type-map-keeper", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install discord-php/DiscordPHP type-map-keeper --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/discord-php/DiscordPHP.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/type-map-keeper .cursor/skills/type-map-keeper && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "type-map-keeper" agent skill from https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeper into .cursor/skills/type-map-keeper/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "type-map-keeper", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/discord-php/DiscordPHP.git --path .agents/skills/type-map-keeper--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install discord-php/DiscordPHP type-map-keeper --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/discord-php/DiscordPHP.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/type-map-keeper .gemini/skills/type-map-keeper && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "type-map-keeper" agent skill from https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeper into .gemini/skills/type-map-keeper/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "type-map-keeper", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install discord-php/DiscordPHP type-map-keeperInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/discord-php/DiscordPHP.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/type-map-keeper .github/skills/type-map-keeper && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "type-map-keeper" agent skill from https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeper into .github/skills/type-map-keeper/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "type-map-keeper", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add discord-php/DiscordPHP --skill type-map-keeper -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install discord-php/DiscordPHP type-map-keeper --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/discord-php/DiscordPHP.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/type-map-keeper .opencode/skills/type-map-keeper && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "type-map-keeper" agent skill from https://github.com/discord-php/DiscordPHP/tree/master/.agents/skills/type-map-keeper into .opencode/skills/type-map-keeper/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "type-map-keeper", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
type-map-keeperMaintain 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. 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.
5 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 580c66a. It shows what the files ask for, not the result of running them.
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.
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.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
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.
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.
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.
The full file from discord-php/DiscordPHP at commit 580c66a, republished under its MIT licence (© discord-php). 1,262 words, ~2,858 tokens.
.claude/skills/type-map-keeper/SKILL.md (or your agent's skills folder).Use this skill when work touches:
TYPES constant array on a part or builderTYPE_* constants on channel, interaction, component, or embed familiestype, component_type, or similar runtime discriminatorattributeTypedCollectionHelper() or attributePartHelper() calls that consume a TYPES mapChannelBuilder::TYPES alias or equivalent builder-side mirrorsThis 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.
Keep type maps as the single source of truth for polymorphic dispatch:
0 handles unknown future values safelyTYPE_* constants remain stable vocabulary for userlandsrc/Discord/Parts/Channel/Channel.php — Channel::TYPES and TYPE_* constants, deprecated aliasessrc/Discord/Parts/Interactions/Interaction.php — Interaction::TYPES and TYPE_* constantssrc/Discord/Parts/Channel/Message/Embed/Embed.php — Embed::TYPES with string-keyed discriminatorssrc/Discord/Parts/Channel/Message/Component.php — inbound Component::TYPES mapsrc/Discord/Builders/Components/ComponentObject.php — outbound ComponentObject::TYPES and TYPE_* constantssrc/Discord/Parts/PartTrait.php — attributeTypedCollectionHelper() at line ~530, createOf() at line ~429src/Discord/Builders/ChannelBuilder.php — ChannelBuilder::TYPES = Channel::TYPES aliassrc/Discord/WebSockets/Events/ChannelCreate.phpsrc/Discord/WebSockets/Events/InteractionCreate.phpsrc/Discord/WebSockets/Events/ThreadListSync.phpA 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.
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.
At every materialization site, the pattern is:
$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.
| Root class | Discriminator | Fallback | String keys | Builder mirror |
|---|---|---|---|---|
Channel | type (int) | none — events use ?? Channel::class | no | ChannelBuilder::TYPES |
Interaction | type (int) | index 0 => Interaction::class | no | — |
Embed | type (string) | index 0 => Embed::class | yes ('rich', 'image', …) | — |
Component (inbound) | type / component_type (int) | index 0 via helper | no | — |
ComponentObject (outbound) | type (int) | index 0 via helper | no | is 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.
Type maps are consumed in these code paths:
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::classThreadCreate, ThreadUpdate, ThreadDelete, ThreadListSync use the same channel mapInteractionCreate uses Interaction::TYPES[$data->type ?? 0]attributeTypedCollectionHelper() in PartTraitCalled by mutators like Message::getEmbedsAttribute() and Message::getComponentsAttribute() to build typed collections from raw payload arrays:
$part = $this->createOf($class::TYPES[$part->type ?? $part->component_type ?? 0], $part);attributePartHelper() for single-object dispatchUsed by Section::getAccessoryAttribute(), Label::getComponentAttribute(), and Component::getComponentAttribute() to resolve a single nested object:
return $this->attributePartHelper('accessory', Component::TYPES[$this->attributes['accessory']->type ?? 0]);Resolved::getChannelsAttribute() uses ChannelBuilder::TYPES[$channel->type] ?? Channel::class to hydrate resolved channels from interaction payloads.
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.
Follow this sequence:
TYPE_* constant on the root class, matching the Discord API integer/string value.TYPES array, keyed by the new constant.TYPES. Verify the fallback expression still works.ChannelBuilder::TYPES is an alias so it picks up changes automatically. For components, ComponentObject::TYPES must be updated independently.attributeTypedCollectionHelper() resolves it.@property annotations on parent parts if the subtype surfaces through typed collections.$fillable and any subtype-specific mutators, repositories, or permission checks.The component family has independent inbound and outbound type maps:
Component::TYPES under src/Discord/Parts/Channel/Message/Component.php maps to part classes like ActionRow, Button, StringSelect (the inbound representations).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.
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 interactionEmbed::TYPES[0] resolves to Embed::class — a safe generic embedChannel::TYPES has no index 0, so event handlers append ?? Channel::class as explicit fallbackThe 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.
TYPE_* constants serve as stable API for userland code:
if ($channel->type === Channel::TYPE_GUILD_VOICE) { ... }TYPE_ (always)TYPE_GUILD_TEXT, TYPE_APPLICATION_COMMAND)When Discord renames a concept, keep the old constant as a deprecated alias:
/** @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.
Stop if you see:
TYPES mapif ($type === 5) branch when a map lookup would workComponent::TYPES left stale, or vice versaTYPES constantattributeTypedCollectionHelper() called with a class whose TYPES constant does not existTYPE_* constant defined on a subtype instead of the root classTYPE_* constant added or updated on the root classTYPES map entry added with constant key → class value0 present or explicit ?? RootClass::class at all dispatch sitesComponentObject::TYPES, ChannelBuilder::TYPES)attributeTypedCollectionHelper() and attributePartHelper() callers verified@deprecated docblock if renamingType 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
Just SKILL.md in .agents/skills/type-map-keeper of discord-php/DiscordPHP.
Open the folder on GitHubat commit 580c66a
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.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Type Map Keeper this skilldiscord-php/DiscordPHP | 1.1k | — | ~2.9k | Automated safety check: Pass | MIT | |
| Agent Browser CLIvercel-labs/agent-browser | 44k | 24 repos | ~864 | Automated safety check: Pass | Apache-2.0 | |
| Configuring Horizoncoollabsio/coolify | 63k | 4 repos | ~898 | Automated safety check: Pass | MIT | |
| Tailwindcss Developmentanonaddy/anonaddy | 4.9k | 10 repos | ~865 | Automated safety check: Pass | MIT | |
| Fortify Developmentcoollabsio/coolify | 63k | 4 repos | ~1.9k | Automated safety check: Pass | MIT | |
| MCP Developmentcoollabsio/coolify | 63k | 1 repos | ~949 | Automated safety check: Pass | MIT |
vercel-labs/agent-browser
Browser automation CLI for AI agents. Use when the user needs to interact with websites, including navigating pages, filling forms, clicking buttons, taking…
coollabsio/coolify
A skill your agent uses whenever the user mentions Horizon by name in a Laravel context.
anonaddy/anonaddy
Always invoke when the user's message includes 'tailwind' in any form.
coollabsio/coolify
ACTIVATE when the user works on authentication in Laravel. An agent skill from coollabsio/coolify.
coollabsio/coolify
A skill your agent uses for Laravel MCP development. An agent skill from coollabsio/coolify.
vercel-labs/agent-browser
Automates Electron desktop apps such as VS Code, Slack or Discord by connecting agent-browser to their Chrome DevTools Protocol port.
discord-php/DiscordPHP
Maintain test and documentation alignment — PHPUnit tests, async testing patterns, PHPDoc contracts, guide pages, and documentation workflow.
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…
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…
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…
discord-php/DiscordPHP
Work with DiscordPHP's infrastructure utilities — CacheWrapper, CacheConfig, BigInt, Multipart, Endpoint::bind URL templates, Collection base class, and domain Exceptions.
discord-php/DiscordPHP
Maintain Part domain models — fillable attributes, mutators, typed nested data, save/fetch behavior, permission checks, PHPDoc, and repository bindings.
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.
Type Map Keeper fits situations like: adding subtypes; changing polymorphic dispatch.
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.
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.
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.
SKILL.md names no scripts, command-line tools or credentials: Type Map Keeper is instructions for the agent only.
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.
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.
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.
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.
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.
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.