Context: Studying Claude Code source code (backup branch)
How Skills Are Triggered, Dispatched, and Recorded
Two invocation paths exist for the same skill definitions:
Slash commands (user-driven): User types /skillname args. Parsed by parseSlashCommand(), dispatched via getMessagesForSlashCommand(). Recorded in session JSONL with XML tags (<command-name>, <command-args>).
SkillTool (model-driven): Claude emits a Skill tool_use block with {skill, args}. Dispatched via SkillTool.call() which calls processPromptSlashCommand(). Recorded as standard tool_use/tool_result pairs in JSONL. Only type: 'prompt' commands with !disableModelInvocation are available to the model.
Args mechanism: The args string is substituted into SKILL.md content via substituteArguments() in src/utils/argumentSubstitution.ts. Supports $ARGUMENTS (full string), $0/$1 (indexed), and named arguments from frontmatter. Parsed with shell-quote. Falls back to appending ARGUMENTS: {args} if no placeholders found.
Execution modes: Both paths support inline (expand into current context) and forked (spawn sub-agent with isolated agentId). Forked slash commands gated behind KAIROS feature flag.
Key files: src/commands.ts (registry), src/tools/SkillTool/SkillTool.ts (model invocation), src/skills/loadSkillsDir.ts (loading), src/utils/processUserInput/processSlashCommand.tsx (slash dispatch), src/types/command.ts (type definitions)