Skip to content

feat: add Codex + Copilot CLI harness backends#24

Open
nhuelstng wants to merge 21 commits into
mainfrom
feat/codex-copilot-backends
Open

feat: add Codex + Copilot CLI harness backends#24
nhuelstng wants to merge 21 commits into
mainfrom
feat/codex-copilot-backends

Conversation

@nhuelstng

Copy link
Copy Markdown
Contributor

Summary

Add Codex CLI (codex) and GitHub Copilot CLI (copilot) as supported harness backends in omac, following the same declarative pattern used for OpenCode and Claude Code. Brings the total to four supported agentic coders.

Changes

Go implementation (TDD):

  • internal/config/harness.go — codex + copilot Harness descriptors, SessionListCodex/SessionListCopilot enum values
  • internal/session/session.golistCodex() (reads ~/.codex/sessions/), listCopilot() (reads ~/.copilot/session-store.db via sqlite3 CLI)
  • internal/manifest/manifest.go — shared Render() function extracted (handles ready/pending-credentials/broken states + global target_path warning)
  • internal/sandboxprofile/resolve.go~/.codex + ~/.copilot added to default filesystem allow-list

Bridge scripts:

  • .codex/hooks/omac-bridge.sh + .codex/hooks.json — SessionStart only (Stop is turn-scoped, no deactivation; relies on TTL reaper)
  • .copilot/hooks/omac-bridge.sh + .copilot/hooks/omac.json — SessionStart + SessionEnd, user-level hooks

Docs:

  • README.md — harness tables, bridge mechanisms, quickstart, continue/resume examples, sandbox profile
  • CREATING_A_SKILL.md — skills dirs, discovery section, sidecar section for all 4 harnesses
  • Design spec + implementation plan in docs/superpowers/
  • Openspec change proposal in openspec/changes/support-codex-copilot-harnesses/

Key decisions

  • Codex has NO deactivate on Stop — Stop event is turn-scoped, not session-scoped. Relies on TTL reaper.
  • Copilot uses PascalCase event names (SessionStart/SessionEnd) for snake_case payload compatibility
  • Copilot registration at user-level .copilot/hooks/omac.json (not repo-level .github/hooks/)
  • Copilot alias is co (exec is standalone copilot binary, not gh-copilot)
  • sqlite3 CLI for copilot session listing (opencode already shells out to sqlite3)

Test plan

  • go build ./... passes
  • go test ./... passes (all packages green)
  • Harness descriptor tests (codex + copilot lookup, fields, session metadata)
  • Session listing dispatch tests (codex + copilot dispatch, missing-store handling)
  • Manifest generator tests (Render with ready/pending/broken/global skills)
  • Bridge script tests (codex + copilot: exists, runs, inert when omac absent)
  • TestBundleGuideMatchesRepoRoot — bundled guide synced with repo root

Deferred to separate change

  • omac manifest subcommand + migration of existing bridges
  • COPILOT_HOME env override support
  • Pre-flight binary check (exec.LookPath)

nhuelstng added 21 commits June 29, 2026 11:56
Local worktrees created during investigation/feature work should not
be tracked.
- Add codex and copilot Harness descriptors to harnessRegistry()
- Add SessionListCodex and SessionListCopilot enum values
- Add listCodex() and listCopilot() best-effort session listing
- Codex: reads ~/.codex/sessions/ (path undocumented, best-effort)
- Copilot: reads ~/.copilot/session-store.db via sqlite3 CLI (schema-gated)
- Thread codexRoot + copilotDB through list() for testability
- Copilot alias is 'co' (not 'gh-copilot' — exec is standalone 'copilot')
- Codex alias is 'cx'
- Both have ServerLaunch: nil (serve runs inner as-is)
- TDD: tests written first, verified RED, then implemented to GREEN
- Render() takes activate-response JSON + skillsDir, returns markdown
- Handles skill states: ready, pending-credentials, broken
- Handles global-skill target_path warning (finding #10)
- TDD: tests written first, verified RED, then implemented to GREEN

Skipped: omac manifest subcommand, bridge migration (finding #16 — split
into separate change to avoid scope creep risk to working harnesses).
- .codex/hooks/omac-bridge.sh: SessionStart hook, activates + emits manifest
- .codex/hooks.json: registers bridge for SessionStart (startup|resume|clear|compact)
- No Stop/deactivate handler (finding #1: codex Stop is turn-scoped, not session-scoped)
- Uses hookSpecificOutput.additionalContext (same nesting as Claude Code)
- Uses git-root-relative path for portability (finding #8)
- Bridge test: verifies script exists, runs, is inert when omac absent
- .copilot/hooks/omac-bridge.sh: SessionStart + SessionEnd hook
- .copilot/hooks/omac.json: user-level registration (finding #8: not .github/hooks/)
- Registers with PascalCase event names (finding #3: snake_case payload)
- Uses hookSpecificOutput.additionalContext (finding #2: VS Code-compatible)
- Copilot has SessionEnd (unlike codex) → deactivate on session end
- Uses git-root-relative path for portability (finding #8)
- Bridge test: verifies script exists, runs, is inert when omac absent
- Codex: no Stop/deactivate (turn-scoped, finding #1)
- Copilot: user-level hooks not .github/hooks/ (finding #8)
- Copilot: PascalCase events, hookSpecificOutput nesting (findings #2,#3)
- Copilot alias 'co' not 'gh-copilot' (finding #13)
- sqlite3 CLI not modernc.org/sqlite (finding #6)
- list() signature matches actual code (finding #7)
- Manifest migration deferred to separate change (finding #16)
- File impact table updated to match actual implementation
…v overrides)

- omac manifest subcommand wrapping manifest.Render() for debugging
- Pre-flight binary check (exec.LookPath) in runLaunch + runServe
- Harness binary status section in omac doctor (advisory)
- HomeEnv field + ConfigHome() method on Harness for all 4 harnesses
- Session path resolvers honor *_HOME env overrides via ConfigHome()
- GlobalSkillsDir() + GlobalBridgeDir() use ConfigHome()

Copilot AI left a comment

Copy link
Copy Markdown

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 omac’s harness ecosystem by adding Codex CLI and GitHub Copilot CLI as first-class harness backends, plus follow-on CLI/config improvements (manifest rendering command, inner-binary preflight checks, and *_HOME config-home overrides) and associated docs/bridge assets.

Changes:

  • Add codex/copilot harness descriptors, session-list kinds, and session listing implementations.
  • Extract a shared skills-manifest renderer (internal/manifest.Render) and expose it via omac manifest.
  • Add preflight inner-harness binary checks (start/serve) and advisory harness-binary reporting in omac doctor, plus docs/specs/bridge hook assets.

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
README.md Documents new harness tokens/aliases and updates usage examples and harness tables.
openspec/changes/support-codex-copilot-harnesses/tasks.md Adds/records implementation task tracking for codex+copilot and related follow-ons.
openspec/changes/support-codex-copilot-harnesses/proposal.md Adds an OpenSpec proposal describing codex+copilot harness support.
internal/session/session.go Adds Codex/Copilot session store discovery and listing dispatch.
internal/session/session_test.go Extends session-listing tests to cover new harnesses and missing-store behavior.
internal/sandboxprofile/resolve.go Allows default sandbox filesystem access to ~/.codex and ~/.copilot.
internal/manifest/manifest.go Introduces a harness-agnostic manifest renderer for activate-response JSON.
internal/manifest/manifest_test.go Adds unit tests for manifest rendering across skill states.
internal/config/harness.go Registers codex/copilot harnesses; adds HomeEnv + ConfigHome() and wires global dirs through it.
internal/config/harness_test.go Adds tests for codex/copilot descriptors and *_HOME overrides.
internal/cli/start.go Adds shared checkInnerBinary and wires it into omac start launch flow.
internal/cli/serve.go Wires inner-binary preflight check into omac serve.
internal/cli/manifest_cmd.go Adds omac manifest subcommand for rendering manifest text from activate JSON.
internal/cli/manifest_cmd_test.go Adds tests for omac manifest (stdin/file/invalid/misuse cases).
internal/cli/doctor.go Adds an “Inner harnesses” section reporting binary presence on PATH.
internal/cli/cli.go Registers the new manifest subcommand and updates usage text.
internal/cli/binary_check_test.go Adds unit tests for checkInnerBinary and doctor output coverage.
internal/builtinskills/assets/omac-write-a-skill/references/creating-a-skill.md Updates bundled guidance doc to mention codex/copilot harness directories and bridges.
docs/superpowers/specs/2026-06-29-deferred-items-design.md Adds a design/spec for the “deferred items” (manifest cmd, binary checks, env overrides).
docs/superpowers/specs/2026-06-29-codex-copilot-backends-design.md Adds a detailed design spec for codex/copilot harness support.
docs/superpowers/plans/2026-06-29-deferred-items.md Adds an implementation plan for deferred items (now implemented in this PR).
docs/superpowers/plans/2026-06-29-codex-copilot-backends.md Adds an implementation plan for remaining codex/copilot work.
CREATING_A_SKILL.md Updates public skill authoring doc for codex/copilot directories and bridges.
.gitignore Ignores local /.worktrees/ directory.
.copilot/hooks/omac.json Adds Copilot hook registration JSON (SessionStart/SessionEnd).
.copilot/hooks/omac-bridge.sh Adds Copilot bridge hook script (activate/deactivate + manifest injection).
.copilot/hooks/bridge_test.go Adds a Go test intended to sanity-check the Copilot bridge script.
.codex/hooks/omac-bridge.sh Adds Codex bridge hook script (activate + manifest injection; no deactivate).
.codex/hooks/bridge_test.go Adds a Go test intended to sanity-check the Codex bridge script.
.codex/hooks.json Adds Codex hook registration JSON (SessionStart only).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread README.md
`~/.claude/projects/<encoded-cwd>/<id>.jsonl` (where `<encoded-cwd>` is the
folder path with non-alphanumerics replaced by `-`, the way Claude Code names
it). Titles come from the session's `aiTitle`, and a file's embedded `cwd`
it), Codex via `codex session list`, Copilot via `copilot session list`.
Comment on lines +98 to +102
Deferred to separate change:
- `omac manifest` subcommand + migration of existing bridges to call it
- README.md harness list + CREATING_A_SKILL.md skills-dirs updates
- `COPILOT_HOME` env override support
- Pre-flight binary check (`exec.LookPath`)
- [x] 6.1 Create `openspec/changes/support-codex-copilot-harnesses/proposal.md`
- [x] 6.2 Create `openspec/changes/support-codex-copilot-harnesses/tasks.md`

## 7. Deferred to separate change
# Deferred Items: Manifest Subcommand, Binary Check, Env Overrides

**Date:** 2026-06-29
**Status:** Design approved, pending implementation
Comment on lines +483 to +484
sortNewestFirst(sessions)
return sessions
Comment on lines +1 to +5
package bridge

import (
"encoding/json"
"os/exec"
Comment on lines +1 to +5
package bridge

import (
"encoding/json"
"os/exec"
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