Skip to content

Capture generic slash-command skill invocations - #1333

Merged
dipree merged 1 commit into
mainfrom
feat/generic-slash-skill-events
Jun 3, 2026
Merged

Capture generic slash-command skill invocations#1333
dipree merged 1 commit into
mainfrom
feat/generic-slash-skill-events

Conversation

@dipree

@dipree dipree commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Problem

Prompt-based skill/prompt invocations were only captured for one fixed slash-command shape. Agents that invoke skills via ordinary slash commands (Codex, Cursor, OpenCode, Gemini, Factory) recorded no skill events, even though a leading /<command> is exactly such an invocation.

Solution

Record a prompt_invocation skill event for any leading /<command> in a submitted prompt.

This is safe because a slash command only reaches a recorded prompt if it submitted a model turn:

  • Runtime/UI-only commands (/mcp, /model, /help, /clear, …) are handled in the agent REPL, never submit a turn, and never fire the turn-start hook — so they're excluded for free, no denylist needed.
  • Pasted filesystem paths (/Users/..., /tmp/...) are the only non-command class and are rejected via a filesystem-root denylist. A bare root-name command (/dev) stays a command; only a root followed by a path segment (/dev/null) is rejected.

Details:

  • Only the command token is stored — never prompt arguments (privacy).
  • Pi's /skill:<name> is normalized to the bare name so it dedupes against Pi's native event.
  • Built-in vs custom is just a label; both are injected prompts and recorded.
  • Wiring is unchanged — handleLifecycleTurnStart already appends for every agent that exposes event.Prompt.

Behavior note: Claude Code sessions now also get prompt_invocation events for slash commands, alongside tool_invocation events from its native Skill tool (different event types, not deduped).

Testing

  • go test ./cmd/entire/cli/agent ./cmd/entire/cli; mise run fmt + golangci-lint clean.
  • Table tests cover built-ins, custom commands, :/path namespacing, arg-stripping, the Pi form, bare root-name commands, and path/non-command rejection.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 2, 2026 20:24
@dipree
dipree requested a review from a team as a code owner June 2, 2026 20:24

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR expands prompt-based skill invocation capture from the Pi-specific /skill:<name> shape to a generic “leading slash command” shape (/<command>), enabling Codex/Cursor/OpenCode/Gemini/Factory-style prompt skills to be persisted as prompt_invocation skill events (storing only the command token for privacy).

Changes:

  • Add a generic prompt slash-command parser and event appender (prompt_slash_command), including filesystem-path rejection and Pi /skill: normalization for dedupe.
  • Update TurnStart lifecycle handling to append the generic prompt-derived skill event only when the agent matches the session owner (or ownership is unset).
  • Add unit tests for parsing variants and lifecycle tests for TurnStart recording + forwarded-hook dedupe.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
cmd/entire/cli/lifecycle.go Appends a generic prompt-derived skill event on TurnStart after session ownership is known.
cmd/entire/cli/lifecycle_test.go Adds lifecycle coverage for recording the prompt-derived event and avoiding duplicates from forwarded hooks.
cmd/entire/cli/agent/skill_events.go Introduces the prompt_slash_command signal constant.
cmd/entire/cli/agent/skill_events_prompt.go Implements parsing/normalization/denylist logic and dedupe for prompt slash-command skill events.
cmd/entire/cli/agent/skill_events_prompt_test.go Adds table-driven tests for parser variants and adapter-vs-generic dedupe behavior.

Comment thread cmd/entire/cli/lifecycle.go Outdated
@dipree
dipree force-pushed the feat/generic-slash-skill-events branch 2 times, most recently from 397fd1f to e096289 Compare June 2, 2026 20:32
Generalize the turn-start prompt parser to record a skill/prompt event for
any leading `/<command>`, not just one fixed namespace.

A slash command only reaches a recorded prompt if it submitted a model turn,
so runtime/UI-only commands (`/mcp`, `/model`, `/help`, ...) are naturally
excluded — they never fire the turn-start hook. The one remaining non-command
class is pasted absolute filesystem paths (`/Users/...`, `/tmp/...`), rejected
via a filesystem-root denylist; a bare root-name command (`/dev`) stays a
command, only `/dev/null`-style continuations are rejected.

Only the command token is stored (never prompt args). Pi's `/skill:<name>` is
normalized to the bare name so it dedupes against Pi's native event. Built-in
vs custom is just a label; both are injected prompts and recorded.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dipree
dipree force-pushed the feat/generic-slash-skill-events branch from e096289 to 48cac9e Compare June 2, 2026 20:37
@dipree
dipree merged commit 8a4e5a4 into main Jun 3, 2026
9 checks passed
@dipree
dipree deleted the feat/generic-slash-skill-events branch June 3, 2026 10:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants