Skip to content

Add GitHub Copilot CLI as a coding agent#455

Merged
sbertix merged 2 commits into
supabitapp:mainfrom
blacroix:copilot-cli-agent
Jun 22, 2026
Merged

Add GitHub Copilot CLI as a coding agent#455
sbertix merged 2 commits into
supabitapp:mainfrom
blacroix:copilot-cli-agent

Conversation

@blacroix

@blacroix blacroix commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds GitHub Copilot CLI (displayed as "Copilot CLI") to the SkillAgent agent-integration system, alongside Claude Code, Codex, Kiro, OpenCode, and Pi. Installing the integration wires up sidebar/tab agent-presence badges and notifications for Copilot, the same as the other agents.

How it works

Copilot CLI auto-loads every JSON hook file under ~/.copilot/hooks/, so Supacode writes and owns its own ~/.copilot/hooks/supacode.json (the Pi/OpenCode "own-file" model) rather than merging into a shared settings object — no prune/append, no feature flag. The hooks emit the shared OSC 3008 presence signals, mapped to Copilot's lifecycle events (per GitHub's hooks docs):

Copilot event Signal
sessionStart session_start
userPromptSubmitted / preToolUse / postToolUse busy
agentStop idle + done-notification
sessionEnd session_end
notification (permission_prompt / elicitation_dialog) awaiting_input + rich alert

pre/postToolUse also recover the badge to busy after a permission prompt flips it to awaiting_input. The notification hook reads the payload and only acts on the "needs you" types so the done-notification (owned by agentStop) isn't duplicated.

Changes

  • SkillAgent: new .copilot case (.copilot dir, "Copilot CLI", copilot-mark)
  • CopilotHookSettings / CopilotHooksInstaller: build + install/uninstall the owned supacode.json (sentinel ownership; only ever touches supacode.json, never sibling user hook files)
  • AgentPresenceOSC.emitNotifyShell gains readsStdin so the branching notification hook can emit a notify from an already-captured payload
  • Wired into AgentIntegrationFactory, CLISkillInstaller/CLISkillContent, and the Developer settings row
  • copilot-mark asset (template-rendered, works in light + dark) + CopilotHooksInstallerTests

Testing

  • Unit tests pass: CopilotHooksInstallerTests, AgentPresenceOSCTests, SettingsFeatureAgentIntegrationTests.
  • Verified at the hook level by capturing a live Copilot session: Copilot runs the installed hooks with the Supacode env present (SUPACODE_SURFACE_ID etc.) and the commands emit valid OSC 3008 to the surface tty (write_to_tty=OK). Presence events (sessionStart/userPromptSubmitted/preToolUse/agentStop) all fire.

⚠️ Not verified locally: end-to-end badges / notifications

I could not verify the rendered badge or notifications locally, because that requires a GhosttyKit.xcframework built with the OSC 3008 context-signal support (added June 2026). The local framework is from March and lacks the callback, and rebuilding it isn't possible on my machine:

  • make build-ghostty-xcframework requires zig 0.15.2 (ghostty's requireZig enforces this exact version), but zig 0.15.2 fails to link against the current macOS 26.5 SDK — a handful of re-exported libc symbols (_sigaction, _waitpid, _realpath$DARWIN_EXTSN, _malloc_size, _posix_memalign, _sysctlbyname, _sigemptyset) come back undefined (a known zig .tbd re-export bug). Same failure on the 15.4 / 26.4 / 26.5 SDKs.
  • zig 0.16.0 (the only newer version available) both fails to compile ghostty (process has no EnvMap) and is rejected by requireZig.

So the presence-badge and notification rendering needs to be confirmed in CI / a build environment with a current GhosttyKit. The agent side (hooks fire, valid OSC emitted) and all unit tests are verified.

Open question for review

Copilot's notification event did not fire for an in-CLI elicitation in my testing, so the permission/"needs you" alert depends on Copilot actually emitting notification events (its own setting). The presence states (busy/idle via the other hooks) are independent of that.

@blacroix blacroix marked this pull request as draft June 22, 2026 18:36
@blacroix blacroix force-pushed the copilot-cli-agent branch from 95404c8 to a130df7 Compare June 22, 2026 18:36
@blacroix blacroix marked this pull request as ready for review June 22, 2026 18:50
Add Copilot CLI ("Copilot CLI") to the SkillAgent integration system
alongside Claude Code, Codex, Kiro, OpenCode, and Pi.

Copilot CLI auto-loads any JSON hook file under ~/.copilot/hooks/, so the
integration writes and owns ~/.copilot/hooks/supacode.json (the Pi/OpenCode
own-file model) rather than merging into a shared settings object. Hooks emit
the OSC 3008 presence signals every other agent uses, mapped to Copilot's
lifecycle events (verified against GitHub's hooks docs):
  sessionStart        -> session_start
  userPromptSubmitted -> busy
  pre/postToolUse     -> busy
  agentStop           -> idle
  sessionEnd          -> session_end
  notification        -> rich alert for every Copilot notification; also flips
                         the badge to awaiting_input for permission_prompt /
                         elicitation_dialog ("needs you") types.

Done/permission notifications route through Copilot's `notification` event
(carries message/title), so they're richer than agentStop (whose payload has
no assistant text).

- SkillAgent: new .copilot case (.copilot dir, "Copilot CLI", copilot-mark)
- CopilotHookSettings: builds the {version,hooks} JSON; notification hook reads
  stdin once and branches on notification_type
- AgentPresenceOSC.emitNotifyShell gains readsStdin (emit notify from a payload
  already captured by a branching hook)
- CopilotHooksInstaller: own-file install/uninstall/state, sentinel ownership,
  only ever touches supacode.json (never sibling user hook files)
- AgentIntegrationFactory / CLISkillInstaller / DeveloperSettingsView wired up
- copilot-mark asset + CopilotHooksInstaller tests
@blacroix blacroix force-pushed the copilot-cli-agent branch from a130df7 to 27a734f Compare June 22, 2026 18:59
Insert Copilot in alphabetical position in SkillAgent so it surfaces in
order in Settings and the sidebar card instead of trailing the list. Make
CopilotHookSettings.source() throw rather than returning an empty string, so
an encode failure can never write a marker-less hook file the installer can
no longer recognize or remove.

Backfill the sidebar-card mode fixtures with the new case (a missing case
read as still-checking and hid the card) and add coverage for the notify
shell stdin capture, notification prompt gating, non-UTF8 install state, and
the alphabetical ordering invariant.

@sbertix sbertix left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thank you 🙇‍♂️ just sorted the agents cases (so they read alphabetically) and adding some missing tests

@sbertix sbertix enabled auto-merge (squash) June 22, 2026 19:36
@sbertix sbertix disabled auto-merge June 22, 2026 19:36
@sbertix sbertix enabled auto-merge (squash) June 22, 2026 19:36
@sbertix sbertix merged commit ed69392 into supabitapp:main Jun 22, 2026
1 check passed
@blacroix blacroix deleted the copilot-cli-agent branch June 23, 2026 07:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants