Skip to content

Commit 1d54a06

Browse files
committed
feat(copilot-cli): Phase 4 — Copilot CLI skill templates
Add 5 embedded skill templates for GitHub Copilot CLI integration: - ctx-status: context summary and health check - ctx-recall: session history browsing - ctx-drift: context drift detection - ctx-compact: archive completed tasks - ctx-next: advance to next task Each skill is written to .github/skills/<name>/SKILL.md when 'ctx hook copilot-cli --write' is invoked. Skills use YAML frontmatter (name, description) with Markdown instructions, following the Copilot CLI skill format. Wiring: - embed.go: glob for hooks/copilot-cli/skills/*/SKILL.md - agent.go: CopilotCLISkills() reader function - run.go: writeCopilotCLISkills() called from WriteCopilotCLIHooks() - asset.go: DirHooksCopilotCLISkills constant - hook.go: DirGitHubSkills, FileSKILLMd constants - text/hook.go: DescKeyWriteHookCopilotCLISkills key Signed-off-by: ersan bilik <ersanbilik@gmail.com>
1 parent a5b447c commit 1d54a06

11 files changed

Lines changed: 279 additions & 18 deletions

File tree

internal/assets/embed.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
//go:embed claude/skills/*/references/*.md claude/skills/*/SKILL.md
1515
//go:embed context/*.md project/* entry-templates/*.md hooks/*.md
1616
//go:embed hooks/copilot-cli/*.json hooks/copilot-cli/*.md hooks/copilot-cli/scripts/*.sh hooks/copilot-cli/scripts/*.ps1
17+
//go:embed hooks/copilot-cli/skills/*/SKILL.md
1718
//go:embed hooks/messages/*/*.txt hooks/messages/registry.yaml
1819
//go:embed prompt-templates/*.md ralph/*.md schema/*.json why/*.md
1920
//go:embed permissions/*.txt commands/*.yaml commands/text/*.yaml journal/*.css
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
---
2+
name: ctx-compact
3+
description: "Archive completed tasks and trim context. Use when context files are growing large."
4+
---
5+
6+
Archive completed tasks and trim stale context entries to keep
7+
the context directory lean and within token budgets.
8+
9+
## When to Use
10+
11+
- When TASKS.md has many completed items
12+
- When context token count is growing large
13+
- When asked to "clean up" or "compact" context
14+
- Before starting a new phase of work
15+
16+
## When NOT to Use
17+
18+
- When all tasks are still active
19+
- When context is already compact
20+
21+
## Execution
22+
23+
Run the compact operation:
24+
25+
```bash
26+
ctx compact
27+
```
28+
29+
This archives completed tasks from TASKS.md into the session
30+
history and trims stale entries from other context files.
31+
32+
After running, confirm:
33+
- How many tasks were archived
34+
- Current token budget usage
35+
- Whether any manual cleanup is recommended
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
---
2+
name: ctx-drift
3+
description: "Detect context drift. Use to find stale paths, broken references, and outdated context."
4+
---
5+
6+
Detect context drift: stale paths, missing files, constitution
7+
violations, and semantic staleness in context files.
8+
9+
## When to Use
10+
11+
- At session start to verify context health
12+
- After refactors, renames, or major structural changes
13+
- When asked "is our context clean?" or "anything stale?"
14+
- Before a release or milestone
15+
16+
## When NOT to Use
17+
18+
- When you just ran ctx status and everything looked fine
19+
- Repeatedly without changes in between
20+
21+
## Execution
22+
23+
Run the structural drift check:
24+
25+
```bash
26+
ctx drift
27+
```
28+
29+
This catches dead paths, missing files, staleness indicators,
30+
and constitution violations.
31+
32+
After running, also do a semantic check: read the context files
33+
and compare them to what you know about the codebase. Look for:
34+
35+
- Outdated conventions that the code no longer follows
36+
- Decisions whose rationale no longer applies
37+
- Architecture descriptions that have changed
38+
- Learnings about bugs that were since fixed
39+
40+
Report findings as actionable items, not raw output. Propose
41+
specific fixes for each issue found.
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
---
2+
name: ctx-next
3+
description: "Advance to the next task. Use when finishing a task or when asked what to work on next."
4+
---
5+
6+
Mark the current task complete and advance to the next one in
7+
the context task list.
8+
9+
## When to Use
10+
11+
- After completing a task
12+
- When the user asks "what's next?"
13+
- When picking up work after a break
14+
15+
## When NOT to Use
16+
17+
- When the user has a specific task in mind already
18+
- When no tasks exist in the context
19+
20+
## Execution
21+
22+
Show the current task and mark it complete:
23+
24+
```bash
25+
ctx next
26+
```
27+
28+
This reads `.context/TASKS.md`, identifies the current in-progress
29+
task, marks it done, and shows the next pending task.
30+
31+
After running, summarize:
32+
- What was completed
33+
- What the next task is
34+
- Any blockers or dependencies noted in the task list
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
name: ctx-recall
3+
description: "Browse session history. Use when referencing past discussions or finding context from previous work."
4+
---
5+
6+
Browse, inspect, and export AI session history.
7+
8+
## When to Use
9+
10+
- When the user asks "what did we do last time?"
11+
- When looking for context from previous work sessions
12+
- When exporting sessions to the journal
13+
- When searching for a specific session by topic or date
14+
15+
## When NOT to Use
16+
17+
- When the user just wants current context (use ctx-status instead)
18+
- For modifying session content (recall is read-only)
19+
20+
## Execution
21+
22+
List recent sessions:
23+
24+
```bash
25+
ctx recall list --limit 5
26+
```
27+
28+
Show details of a specific session:
29+
30+
```bash
31+
ctx recall show --latest
32+
ctx recall show <session-id>
33+
```
34+
35+
Export sessions to journal markdown:
36+
37+
```bash
38+
ctx recall export --all
39+
```
40+
41+
After listing sessions, summarize relevant findings rather than
42+
dumping raw output.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
name: ctx-status
3+
description: "Show context summary and health. Use at session start or when unclear about project state."
4+
---
5+
6+
Show the current context status: files, token budget, tasks, and
7+
recent activity.
8+
9+
## When to Use
10+
11+
- At session start to orient before doing work
12+
- When confused about what is being worked on
13+
- To check token usage and context health
14+
- When the user asks "what's the state of the project?"
15+
16+
## When NOT to Use
17+
18+
- When you already loaded context via `ctx agent` in this session
19+
- Repeatedly within the same session without changes in between
20+
21+
## Execution
22+
23+
```bash
24+
ctx status
25+
```
26+
27+
For verbose output with file previews:
28+
29+
```bash
30+
ctx status --verbose
31+
```
32+
33+
For machine-readable output:
34+
35+
```bash
36+
ctx status --json
37+
```
38+
39+
After running, summarize the key points:
40+
- How many active tasks remain
41+
- Whether any context files are empty or stale
42+
- What was most recently modified

internal/assets/read/agent/agent.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,31 @@ func CopilotCLIScripts() (map[string][]byte, error) {
9090
}
9191
return scripts, nil
9292
}
93+
94+
// CopilotCLISkills reads all embedded Copilot CLI skill templates.
95+
// Returns a map of skill directory name to SKILL.md content for skills
96+
// in hooks/copilot-cli/skills/.
97+
//
98+
// Returns:
99+
// - map[string][]byte: Skill name -> SKILL.md content
100+
// - error: Non-nil if the directory read fails
101+
func CopilotCLISkills() (map[string][]byte, error) {
102+
skills := make(map[string][]byte)
103+
entries, dirErr := fs.ReadDir(assets.FS, asset.DirHooksCopilotCLISkills)
104+
if dirErr != nil {
105+
return nil, dirErr
106+
}
107+
for _, entry := range entries {
108+
if !entry.IsDir() {
109+
continue
110+
}
111+
name := entry.Name()
112+
skillPath := asset.DirHooksCopilotCLISkills + "/" + name + "/" + asset.FileSKILLMd
113+
content, readErr := assets.FS.ReadFile(skillPath)
114+
if readErr != nil {
115+
return nil, readErr
116+
}
117+
skills[name] = content
118+
}
119+
return skills, nil
120+
}

internal/cli/hook/cmd/root/run.go

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,11 @@ func WriteCopilotCLIHooks(cmd *cobra.Command) error {
235235
cmd.Println(" ⚠ mcp-config.json: " + err.Error())
236236
}
237237

238+
// Write .github/skills/<name>/SKILL.md for Copilot CLI skills
239+
if err := writeCopilotCLISkills(cmd); err != nil {
240+
writeErr.WarnFile(cmd, cfgHook.DirGitHubSkills, err)
241+
}
242+
238243
hook.InfoCopilotCLISummary(cmd)
239244
return nil
240245
}
@@ -292,6 +297,35 @@ func writeCopilotCLIInstructions(cmd *cobra.Command) error {
292297
return nil
293298
}
294299

300+
// writeCopilotCLISkills creates .github/skills/<name>/SKILL.md for each
301+
// embedded Copilot CLI skill template. Skips skills that already exist.
302+
func writeCopilotCLISkills(cmd *cobra.Command) error {
303+
skills, readErr := agent.CopilotCLISkills()
304+
if readErr != nil {
305+
return readErr
306+
}
307+
308+
skillsBase := filepath.Join(cfgHook.DirGitHub, cfgHook.DirGitHubSkills)
309+
for name, content := range skills {
310+
skillDir := filepath.Join(skillsBase, name)
311+
target := filepath.Join(skillDir, cfgHook.FileSKILLMd)
312+
313+
if _, err := os.Stat(target); err == nil {
314+
hook.InfoCopilotCLICreated(cmd, target+" (exists, skipped)")
315+
continue
316+
}
317+
318+
if err := os.MkdirAll(skillDir, fs.PermExec); err != nil {
319+
return err
320+
}
321+
if wErr := os.WriteFile(target, content, fs.PermFile); wErr != nil {
322+
return wErr
323+
}
324+
hook.InfoCopilotCLICreated(cmd, target)
325+
}
326+
return nil
327+
}
328+
295329
// WriteAgentsMd generates AGENTS.md in the project root.
296330
//
297331
// Creates AGENTS.md with universal agent instructions. Preserves existing

internal/config/asset/asset.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,24 +10,25 @@ import "path"
1010

1111
// Embedded asset directory names.
1212
const (
13-
DirClaude = "claude"
14-
DirClaudePlugin = "claude/.claude-plugin"
15-
DirClaudeSkills = "claude/skills"
16-
DirCommands = "commands"
17-
DirCommandsText = "commands/text"
18-
DirContext = "context"
19-
DirEntryTemplates = "entry-templates"
20-
DirHooks = "hooks"
21-
DirHooksCopilotCLI = "hooks/copilot-cli"
22-
DirHooksCopilotCLIScrp = "hooks/copilot-cli/scripts"
23-
DirHooksMessages = "hooks/messages"
24-
DirJournal = "journal"
25-
DirPermissions = "permissions"
26-
DirProject = "project"
27-
DirPromptTemplates = "prompt-templates"
28-
DirRalph = "ralph"
29-
DirSchema = "schema"
30-
DirWhy = "why"
13+
DirClaude = "claude"
14+
DirClaudePlugin = "claude/.claude-plugin"
15+
DirClaudeSkills = "claude/skills"
16+
DirCommands = "commands"
17+
DirCommandsText = "commands/text"
18+
DirContext = "context"
19+
DirEntryTemplates = "entry-templates"
20+
DirHooks = "hooks"
21+
DirHooksCopilotCLI = "hooks/copilot-cli"
22+
DirHooksCopilotCLIScrp = "hooks/copilot-cli/scripts"
23+
DirHooksCopilotCLISkills = "hooks/copilot-cli/skills"
24+
DirHooksMessages = "hooks/messages"
25+
DirJournal = "journal"
26+
DirPermissions = "permissions"
27+
DirProject = "project"
28+
DirPromptTemplates = "prompt-templates"
29+
DirRalph = "ralph"
30+
DirSchema = "schema"
31+
DirWhy = "why"
3132
)
3233

3334
// JSON field keys used when parsing embedded asset files.

internal/config/embed/text/hook.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ const (
2424
DescKeyWriteHookAgentsSummary = "write.hook-agents-summary"
2525
DescKeyWriteHookCopilotCLICreated = "write.hook-copilot-cli-created"
2626
DescKeyWriteHookCopilotCLISkipped = "write.hook-copilot-cli-skipped"
27+
DescKeyWriteHookCopilotCLISkills = "write.hook-copilot-cli-skills"
2728
DescKeyWriteHookCopilotCLISummary = "write.hook-copilot-cli-summary"
2829
DescKeyWriteHookCopilotCreated = "write.hook-copilot-created"
2930
DescKeyWriteHookCopilotForceHint = "write.hook-copilot-force-hint"

0 commit comments

Comments
 (0)