11// / Context: https://ctx.ist
22// ,'`./ do you remember?
33// `.,'\
4- // \ Copyright 2025 -present Context contributors.
4+ // \ Copyright 2026 -present Context contributors.
55// SPDX-License-Identifier: Apache-2.0
66
7- // Package claude provides Claude Code integration templates and utilities.
87package claude
98
109import (
@@ -15,7 +14,14 @@ import (
1514//go:embed tpl/auto-save-session.sh tpl/block-non-path-ctx.sh tpl/commands/*.md
1615var FS embed.FS
1716
18- // GetAutoSaveScript returns the auto-save session script.
17+ // GetAutoSaveScript returns the auto-save session script content.
18+ //
19+ // The script automatically saves Claude Code session transcripts when a
20+ // session ends. It is installed to .claude/hooks/ during ctx init --claude.
21+ //
22+ // Returns:
23+ // - []byte: Raw bytes of the auto-save-session.sh script
24+ // - error: Non-nil if the embedded file cannot be read
1925func GetAutoSaveScript () ([]byte , error ) {
2026 content , err := FS .ReadFile ("tpl/auto-save-session.sh" )
2127 if err != nil {
@@ -24,7 +30,16 @@ func GetAutoSaveScript() ([]byte, error) {
2430 return content , nil
2531}
2632
27- // GetBlockNonPathCtxScript returns the script that blocks non-PATH ctx invocations.
33+ // GetBlockNonPathCtxScript returns the script that blocks non-PATH ctx
34+ // invocations.
35+ //
36+ // The script prevents Claude from running ctx via relative paths (./ctx,
37+ // ./dist/ctx) or "go run", ensuring only the installed PATH version is used.
38+ // It is installed to .claude/hooks/ during ctx init --claude.
39+ //
40+ // Returns:
41+ // - []byte: Raw bytes of the block-non-path-ctx.sh script
42+ // - error: Non-nil if the embedded file cannot be read
2843func GetBlockNonPathCtxScript () ([]byte , error ) {
2944 content , err := FS .ReadFile ("tpl/block-non-path-ctx.sh" )
3045 if err != nil {
@@ -34,6 +49,14 @@ func GetBlockNonPathCtxScript() ([]byte, error) {
3449}
3550
3651// ListCommands returns the list of embedded command file names.
52+ //
53+ // These are Claude Code slash command definitions (e.g., "ctx-status.md",
54+ // "commit-local.md") from the tpl/commands directory. They can be installed
55+ // to .claude/commands/ via "ctx init --claude".
56+ //
57+ // Returns:
58+ // - []string: Filenames of available command definitions
59+ // - error: Non-nil if the commands directory cannot be read
3760func ListCommands () ([]string , error ) {
3861 entries , err := FS .ReadDir ("tpl/commands" )
3962 if err != nil {
@@ -49,7 +72,14 @@ func ListCommands() ([]string, error) {
4972 return names , nil
5073}
5174
52- // GetCommand returns the content of a command file.
75+ // GetCommand returns the content of a command file by name.
76+ //
77+ // Parameters:
78+ // - name: Filename as returned by [ListCommands] (e.g., "ctx-status.md")
79+ //
80+ // Returns:
81+ // - []byte: Raw bytes of the command definition file
82+ // - error: Non-nil if the command file does not exist or cannot be read
5383func GetCommand (name string ) ([]byte , error ) {
5484 content , err := FS .ReadFile ("tpl/commands/" + name )
5585 if err != nil {
@@ -58,40 +88,27 @@ func GetCommand(name string) ([]byte, error) {
5888 return content , nil
5989}
6090
61- // SettingsHooks represents the hooks section of settings.local.json
62- type SettingsHooks struct {
63- PreToolUse []HookMatcher `json:"PreToolUse,omitempty"`
64- SessionEnd []HookMatcher `json:"SessionEnd,omitempty"`
65- }
66-
67- // HookMatcher represents a hook matcher with optional pattern
68- type HookMatcher struct {
69- Matcher string `json:"matcher,omitempty"`
70- Hooks []Hook `json:"hooks"`
71- }
72-
73- // Hook represents a single hook command
74- type Hook struct {
75- Type string `json:"type"`
76- Command string `json:"command"`
77- }
78-
79- // Settings represents the full settings.local.json structure
80- type Settings struct {
81- Hooks SettingsHooks `json:"hooks,omitempty"`
82- Permissions map [string ]interface {} `json:"permissions,omitempty"`
83- }
84-
85- // CreateDefaultHooks returns the default ctx hooks configuration.
86- // Hooks use "ctx" expecting it to be in PATH.
87- func CreateDefaultHooks (projectDir string ) SettingsHooks {
91+ // CreateDefaultHooks returns the default ctx hooks configuration for
92+ // Claude Code.
93+ //
94+ // The returned hooks configure PreToolUseHooks to block non-PATH ctx
95+ // invocations and auto-load context on every tool use, and SessionEndHooks
96+ // to run auto-save-session.sh for persisting session transcripts.
97+ //
98+ // Parameters:
99+ // - projectDir: Project root directory for absolute hook paths; if empty,
100+ // paths are relative (e.g., ".claude/hooks/")
101+ //
102+ // Returns:
103+ // - HookConfig: Configured hooks for PreToolUse and SessionEnd events
104+ func CreateDefaultHooks (projectDir string ) HookConfig {
88105 hooksDir := ".claude/hooks"
89106 if projectDir != "" {
90107 hooksDir = fmt .Sprintf ("%s/.claude/hooks" , projectDir )
91108 }
92109
93- return SettingsHooks {
94- PreToolUse : []HookMatcher {
110+ return HookConfig {
111+ PreToolUseHooks : []HookMatcher {
95112 {
96113 // Block non-PATH ctx invocations (./ctx, ./dist/ctx, go run ./cmd/ctx)
97114 Matcher : "Bash" ,
@@ -103,7 +120,7 @@ func CreateDefaultHooks(projectDir string) SettingsHooks {
103120 },
104121 },
105122 {
106- // Auto-load context on every tool use
123+ // Autoload context on every tool use
107124 Matcher : ".*" ,
108125 Hooks : []Hook {
109126 {
@@ -113,7 +130,7 @@ func CreateDefaultHooks(projectDir string) SettingsHooks {
113130 },
114131 },
115132 },
116- SessionEnd : []HookMatcher {
133+ SessionEndHooks : []HookMatcher {
117134 {
118135 Hooks : []Hook {
119136 {
0 commit comments