@handsupmin/gc-tree 0.2.1 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.es.md CHANGED
@@ -62,7 +62,7 @@ gctree init
62
62
  2. Instalar los archivos de integración en el repositorio actual
63
63
  3. Completar el onboarding guiado para el gc-branch `main`
64
64
 
65
- Después, tu herramienta de IA aprenderá a llamar a `gctree resolve` antes de planificar o implementar.
65
+ Después, tu herramienta de IA instala integración real de hooks SessionStart/UserPromptSubmit: revisa gc-tree automáticamente antes de trabajar y cachea resultados vacíos/no-match durante la sesión.
66
66
 
67
67
  - **CLI:** `gctree`
68
68
  - **Requisito:** Node.js 20+
package/README.ja.md CHANGED
@@ -62,7 +62,7 @@ gctree init
62
62
  2. 現在のリポジトリへの統合ファイルのインストール
63
63
  3. `main` gc-branch のガイド付きオンボーディング実行
64
64
 
65
- その後は、AI ツールが計画・実装の前に `gctree resolve` を呼ぶ流れを自然に覚えます。
65
+ その後は、AI ツールに実際の SessionStart / UserPromptSubmit フック統合が入り、作業前に gc-tree を自動確認し、空結果や no-match をセッション中キャッシュします。
66
66
 
67
67
  - **CLI:** `gctree`
68
68
  - **動作条件:** Node.js 20+
package/README.ko.md CHANGED
@@ -62,7 +62,7 @@ gctree init
62
62
  2. 현재 레포에 통합 파일 스캐폴딩
63
63
  3. `main` gc-branch 가이드형 온보딩 실행
64
64
 
65
- 이후 AI 도구가 계획·구현 전에 `gctree resolve`를 호출하는 법을 자동으로 알게 됩니다.
65
+ 이후 AI 도구에 실제 SessionStart/UserPromptSubmit 훅 통합이 설치되어, 작업 전에 gc-tree를 자동 확인하고 세션 동안 결과·no-match를 캐시합니다.
66
66
 
67
67
  - **CLI:** `gctree`
68
68
  - **요구 사항:** Node.js 20+
package/README.md CHANGED
@@ -62,7 +62,7 @@ gctree init
62
62
  2. Scaffold the integration files into your current repo
63
63
  3. Run guided onboarding for the `main` gc-branch
64
64
 
65
- After that, your AI tool will know to call `gctree resolve` before planning or implementing.
65
+ After that, your AI tool gets real SessionStart/UserPromptSubmit hook integration, so it auto-checks gc-tree before work and caches empty/no-match results for the session.
66
66
 
67
67
  - **CLI:** `gctree`
68
68
  - **Requires:** Node.js 20+
package/README.zh.md CHANGED
@@ -49,7 +49,7 @@ gctree init
49
49
  2. 在当前仓库安装集成文件
50
50
  3. 为 `main` gc-branch 完成引导式 onboarding
51
51
 
52
- 之后,AI 工具会自动学会在规划或实现前调用 `gctree resolve`。
52
+ 之后,AI 工具会安装真正的 SessionStart / UserPromptSubmit hook 集成:在开始工作前自动检查 gc-tree,并在整个会话内缓存空结果和 no-match。
53
53
 
54
54
  - **CLI:** `gctree`
55
55
  - **要求:** Node.js 20+
package/dist/src/cli.js CHANGED
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import { readFile } from 'node:fs/promises';
3
3
  import { stdin } from 'node:process';
4
+ import { dispatchGcTreeHook } from './hook.js';
4
5
  import { onboardBranch } from './onboard.js';
5
6
  import { buildProviderLaunchPlan, maybeLaunchProvider, promptLanguageSelection, promptLaunchProviderSelection, promptProviderSelection, } from './provider.js';
6
7
  import { DEFAULT_BRANCH, resolveHome } from './paths.js';
@@ -37,12 +38,20 @@ function usage() {
37
38
  Internal commands:
38
39
  gctree __apply-onboarding --input FILE [--home DIR] [--branch NAME]
39
40
  gctree __apply-update --input FILE [--home DIR] [--branch NAME]
41
+ gctree __hook --event <SessionStart|UserPromptSubmit> [--home DIR]
40
42
  `);
41
43
  process.exit(1);
42
44
  }
43
45
  async function readJsonFile(path) {
44
46
  return JSON.parse(await readFile(path, 'utf8'));
45
47
  }
48
+ async function readStdinText() {
49
+ const chunks = [];
50
+ for await (const chunk of process.stdin) {
51
+ chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
52
+ }
53
+ return Buffer.concat(chunks).toString('utf8');
54
+ }
46
55
  function normalizeProvider(value) {
47
56
  if (!value)
48
57
  return undefined;
@@ -337,6 +346,22 @@ async function main() {
337
346
  console.log(JSON.stringify(result, null, 2));
338
347
  return;
339
348
  }
349
+ case '__hook': {
350
+ const event = readArg('--event');
351
+ if (event !== 'SessionStart' && event !== 'UserPromptSubmit')
352
+ usage();
353
+ const raw = await readStdinText();
354
+ const payload = raw.trim() ? JSON.parse(raw) : {};
355
+ const result = await dispatchGcTreeHook({
356
+ event,
357
+ home,
358
+ payload,
359
+ });
360
+ if (result) {
361
+ console.log(JSON.stringify(result, null, 2));
362
+ }
363
+ return;
364
+ }
340
365
  case 'scaffold': {
341
366
  const host = normalizeProviderMode(readArg('--host'));
342
367
  if (!host)
@@ -0,0 +1,209 @@
1
+ import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
+ import { createHash } from 'node:crypto';
3
+ import { dirname } from 'node:path';
4
+ import { DEFAULT_BRANCH } from './paths.js';
5
+ import { hookCachePath, } from './paths.js';
6
+ import { branchScopeStatus, readBranchRepoMap, resolveBranchForRepo } from './repo-map.js';
7
+ import { resolveContext } from './resolve.js';
8
+ import { readHead, statusForBranch } from './store.js';
9
+ function normalizeText(value) {
10
+ return value.trim().replace(/\s+/g, ' ');
11
+ }
12
+ function hashQuery(query) {
13
+ return createHash('sha1').update(normalizeText(query).toLowerCase()).digest('hex');
14
+ }
15
+ function limitMatches(matches, max = 3) {
16
+ return matches.slice(0, max);
17
+ }
18
+ function formatMatches(matches) {
19
+ return limitMatches(matches)
20
+ .map((match, index) => `${index + 1}. ${match.title}\n Summary: ${match.summary}\n Excerpt: ${match.excerpt}`)
21
+ .join('\n');
22
+ }
23
+ function buildSessionStartContext({ gcBranch, currentRepo, repoScopeStatus, }) {
24
+ return [
25
+ `gc-tree auto-resolve is active for this session.`,
26
+ `Active gc-branch: "${gcBranch}".`,
27
+ `Current repo: ${currentRepo || 'unscoped'}.`,
28
+ `Repo scope status: ${repoScopeStatus}.`,
29
+ `Before acting on new user prompts, use gc-tree hook context first. If the hook reports no reusable global context, avoid redundant resolve calls for the same session state unless the repo, gc-branch, or task changes materially.`,
30
+ ].join(' ');
31
+ }
32
+ function buildEmptyBranchContext({ gcBranch, currentRepo, cached, }) {
33
+ return [
34
+ `gc-tree auto-resolve ${cached ? 'used cached state' : 'checked the active gc-branch'} and found no reusable global context for this session because gc-branch "${gcBranch}" currently has 0 docs.`,
35
+ `Repo: ${currentRepo || 'unscoped'}.`,
36
+ `Treat this as "no reusable global context yet" until the gc-branch content changes or a different repo/gc-branch is active.`,
37
+ ].join(' ');
38
+ }
39
+ function buildExcludedContext({ gcBranch, currentRepo, cached, }) {
40
+ return [
41
+ `gc-tree auto-resolve ${cached ? 'used cached state' : 'checked the active gc-branch'} and found that repo "${currentRepo || 'unknown'}" is excluded from gc-branch "${gcBranch}".`,
42
+ `No reusable global context applies here unless the branch-repo mapping changes.`,
43
+ ].join(' ');
44
+ }
45
+ function buildNoMatchContext({ gcBranch, currentRepo, query, cached, }) {
46
+ return [
47
+ `gc-tree auto-resolve ${cached ? 'skipped a redundant lookup using cached no-match state' : 'checked the active gc-branch'} and found no reusable global context for this prompt in gc-branch "${gcBranch}".`,
48
+ `Repo: ${currentRepo || 'unscoped'}.`,
49
+ `Query: "${query}".`,
50
+ `Only re-run resolve if the repo, gc-branch, or task changes materially.`,
51
+ ].join(' ');
52
+ }
53
+ function buildMatchContext({ gcBranch, currentRepo, repoScopeStatus, query, matches, }) {
54
+ return [
55
+ `gc-tree auto-resolve checked gc-branch "${gcBranch}" for repo "${currentRepo || 'unscoped'}" (scope: ${repoScopeStatus}) before this prompt.`,
56
+ `Query: "${query}".`,
57
+ `Use these matching gc-tree summaries before planning or implementation:`,
58
+ formatMatches(matches),
59
+ `Read full docs only if the summaries are insufficient.`,
60
+ ].join('\n');
61
+ }
62
+ async function readHookCache(home, sessionId) {
63
+ try {
64
+ const raw = await readFile(hookCachePath(home, sessionId), 'utf8');
65
+ return JSON.parse(raw);
66
+ }
67
+ catch {
68
+ return null;
69
+ }
70
+ }
71
+ async function writeHookCache(home, cache) {
72
+ const path = hookCachePath(home, cache.session_id);
73
+ await mkdir(dirname(path), { recursive: true });
74
+ await writeFile(path, `${JSON.stringify(cache, null, 2)}\n`, 'utf8');
75
+ }
76
+ function nextCacheState(previous, { sessionId, gcBranch, currentRepo, repoScopeStatus, }) {
77
+ const changed = !previous ||
78
+ previous.gc_branch !== gcBranch ||
79
+ previous.current_repo !== currentRepo ||
80
+ previous.repo_scope_status !== repoScopeStatus;
81
+ return {
82
+ version: 1,
83
+ session_id: sessionId,
84
+ gc_branch: gcBranch,
85
+ current_repo: currentRepo,
86
+ repo_scope_status: repoScopeStatus,
87
+ branch_empty: changed ? false : previous.branch_empty,
88
+ branch_excluded: changed ? false : previous.branch_excluded,
89
+ no_match_signatures: changed ? [] : previous.no_match_signatures,
90
+ updated_at: new Date().toISOString(),
91
+ };
92
+ }
93
+ function readSessionId(payload) {
94
+ const raw = normalizeText(payload.session_id || '');
95
+ return raw || 'default-session';
96
+ }
97
+ export async function dispatchGcTreeHook({ event, home, payload, }) {
98
+ const cwd = payload.cwd || process.cwd();
99
+ const head = (await readHead(home)) || DEFAULT_BRANCH;
100
+ const resolved = await resolveBranchForRepo({ home, head, cwd });
101
+ const gcBranch = resolved.gc_branch;
102
+ const currentRepo = resolved.current_repo;
103
+ const mapping = await readBranchRepoMap(home);
104
+ const repoScopeStatus = branchScopeStatus(mapping, gcBranch, currentRepo);
105
+ const sessionId = readSessionId(payload);
106
+ if (event === 'SessionStart') {
107
+ return {
108
+ hookSpecificOutput: {
109
+ hookEventName: event,
110
+ additionalContext: buildSessionStartContext({
111
+ gcBranch,
112
+ currentRepo,
113
+ repoScopeStatus,
114
+ }),
115
+ },
116
+ };
117
+ }
118
+ const prompt = normalizeText(payload.user_prompt || '');
119
+ if (!prompt)
120
+ return null;
121
+ const branchStatus = await statusForBranch(home, gcBranch);
122
+ const previousCache = await readHookCache(home, sessionId);
123
+ const cache = nextCacheState(previousCache, {
124
+ sessionId,
125
+ gcBranch,
126
+ currentRepo,
127
+ repoScopeStatus,
128
+ });
129
+ if (repoScopeStatus === 'excluded') {
130
+ cache.branch_excluded = true;
131
+ cache.updated_at = new Date().toISOString();
132
+ await writeHookCache(home, cache);
133
+ return {
134
+ hookSpecificOutput: {
135
+ hookEventName: event,
136
+ additionalContext: buildExcludedContext({
137
+ gcBranch,
138
+ currentRepo,
139
+ cached: previousCache?.branch_excluded === true,
140
+ }),
141
+ },
142
+ };
143
+ }
144
+ if (branchStatus.doc_count === 0) {
145
+ const wasCached = cache.branch_empty;
146
+ cache.branch_empty = true;
147
+ cache.updated_at = new Date().toISOString();
148
+ await writeHookCache(home, cache);
149
+ return {
150
+ hookSpecificOutput: {
151
+ hookEventName: event,
152
+ additionalContext: buildEmptyBranchContext({
153
+ gcBranch,
154
+ currentRepo,
155
+ cached: wasCached,
156
+ }),
157
+ },
158
+ };
159
+ }
160
+ const query = currentRepo ? `${currentRepo} ${prompt}` : prompt;
161
+ const signature = hashQuery(query);
162
+ if (cache.no_match_signatures.includes(signature)) {
163
+ cache.updated_at = new Date().toISOString();
164
+ await writeHookCache(home, cache);
165
+ return {
166
+ hookSpecificOutput: {
167
+ hookEventName: event,
168
+ additionalContext: buildNoMatchContext({
169
+ gcBranch,
170
+ currentRepo,
171
+ query,
172
+ cached: true,
173
+ }),
174
+ },
175
+ };
176
+ }
177
+ const result = await resolveContext({ home, branch: gcBranch, query });
178
+ if (result.matches.length === 0) {
179
+ cache.no_match_signatures = [...new Set([...cache.no_match_signatures, signature])];
180
+ cache.updated_at = new Date().toISOString();
181
+ await writeHookCache(home, cache);
182
+ return {
183
+ hookSpecificOutput: {
184
+ hookEventName: event,
185
+ additionalContext: buildNoMatchContext({
186
+ gcBranch,
187
+ currentRepo,
188
+ query,
189
+ cached: false,
190
+ }),
191
+ },
192
+ };
193
+ }
194
+ cache.no_match_signatures = cache.no_match_signatures.filter((entry) => entry !== signature);
195
+ cache.updated_at = new Date().toISOString();
196
+ await writeHookCache(home, cache);
197
+ return {
198
+ hookSpecificOutput: {
199
+ hookEventName: event,
200
+ additionalContext: buildMatchContext({
201
+ gcBranch,
202
+ currentRepo,
203
+ repoScopeStatus,
204
+ query,
205
+ matches: result.matches,
206
+ }),
207
+ },
208
+ };
209
+ }
package/dist/src/paths.js CHANGED
@@ -26,3 +26,9 @@ export function branchIndexPath(home, branch) {
26
26
  export function branchDocsDir(home, branch) {
27
27
  return join(branchDir(home, branch), 'docs');
28
28
  }
29
+ export function hookCacheDir(home) {
30
+ return join(home, 'hook-cache');
31
+ }
32
+ export function hookCachePath(home, sessionId) {
33
+ return join(hookCacheDir(home), `${sessionId}.json`);
34
+ }
@@ -6,8 +6,8 @@ function renderCodexAgentsSnippet() {
6
6
  '# gctree Codex integration snippet',
7
7
  '',
8
8
  '- Treat the active gctree branch as a **gc-branch** when you describe it to users.',
9
- '- Before planning or implementation, run `gctree status` to confirm the active gc-branch if it is unclear.',
10
- '- Use `gctree resolve --query "<task>"` when reusable global context may matter.',
9
+ '- gctree init installs SessionStart and UserPromptSubmit hooks that auto-check gc-tree before work.',
10
+ '- Use the hook-injected gc-tree context first. If hooks are unavailable or clearly stale, run `gctree status` and `gctree resolve --query "<task>"` yourself before planning or implementation.',
11
11
  '- Use `$gc-onboard` only for an empty gc-branch.',
12
12
  '- Use `$gc-update-global-context` when durable context in the active gc-branch should change.',
13
13
  '',
@@ -18,12 +18,39 @@ function renderCodexBootstrapPrompt() {
18
18
  '# gctree Bootstrap',
19
19
  '',
20
20
  '- Keep the active gc-branch explicit whenever global context matters.',
21
- '- Resolve reusable global context before planning or implementation when it may change the answer.',
21
+ '- Trust auto-resolved gc-tree hook context first; if it is missing, resolve reusable global context before planning or implementation.',
22
22
  '- Read summaries first and only open full docs when needed.',
23
23
  '- Treat gctree docs as explicit source-of-truth markdown, not hidden memory.',
24
24
  '',
25
25
  ].join('\n');
26
26
  }
27
+ function renderCodexHooksJson() {
28
+ return JSON.stringify({
29
+ hooks: {
30
+ SessionStart: [
31
+ {
32
+ matcher: 'startup|resume',
33
+ hooks: [
34
+ {
35
+ type: 'command',
36
+ command: 'gctree __hook --event SessionStart',
37
+ },
38
+ ],
39
+ },
40
+ ],
41
+ UserPromptSubmit: [
42
+ {
43
+ hooks: [
44
+ {
45
+ type: 'command',
46
+ command: 'gctree __hook --event UserPromptSubmit',
47
+ },
48
+ ],
49
+ },
50
+ ],
51
+ },
52
+ }, null, 2);
53
+ }
27
54
  function renderCodexResolveSkill() {
28
55
  return [
29
56
  '---',
@@ -80,8 +107,8 @@ function renderClaudeSnippet() {
80
107
  '# gctree Claude Code integration snippet',
81
108
  '',
82
109
  '- Treat the active gctree branch as a **gc-branch** in user-facing language.',
83
- '- Run `gctree status` before relying on global context if the active gc-branch is unclear.',
84
- '- Use `gctree resolve --query "<task>"` when reusable global context may matter.',
110
+ '- gctree init installs SessionStart and UserPromptSubmit hooks that auto-check gc-tree before work.',
111
+ '- Use the hook-injected gc-tree context first. If hooks are unavailable or clearly stale, run `gctree status` and `gctree resolve --query "<task>"` yourself before planning or implementation.',
85
112
  '- Use `/gc-onboard` only for an empty gc-branch.',
86
113
  '- Use `/gc-update-global-context` when durable context in the active gc-branch should change.',
87
114
  '',
@@ -91,12 +118,43 @@ function renderClaudeSessionStartHook() {
91
118
  return [
92
119
  '# gctree Claude Code SessionStart note',
93
120
  '',
94
- '- At session start, confirm the active gc-branch with `gctree status` when reusable global context may matter.',
121
+ '- gctree init installs real SessionStart/UserPromptSubmit hooks via `.claude/hooks/hooks.json`.',
122
+ '- At session start, use the injected hook context to confirm the active gc-branch.',
95
123
  '- Refer to gctree branches as **gc-branches** in user-facing language.',
96
- '- Resolve summaries before planning or implementation when branch-level context may change the answer.',
124
+ '- If hook context is missing or stale, resolve summaries before planning or implementation when branch-level context may change the answer.',
97
125
  '',
98
126
  ].join('\n');
99
127
  }
128
+ function renderClaudeHooksJson() {
129
+ return JSON.stringify({
130
+ hooks: {
131
+ SessionStart: [
132
+ {
133
+ matcher: '*',
134
+ hooks: [
135
+ {
136
+ type: 'command',
137
+ command: 'gctree __hook --event SessionStart',
138
+ timeout: 10,
139
+ },
140
+ ],
141
+ },
142
+ ],
143
+ UserPromptSubmit: [
144
+ {
145
+ matcher: '*',
146
+ hooks: [
147
+ {
148
+ type: 'command',
149
+ command: 'gctree __hook --event UserPromptSubmit',
150
+ timeout: 10,
151
+ },
152
+ ],
153
+ },
154
+ ],
155
+ },
156
+ }, null, 2);
157
+ }
100
158
  function renderClaudeResolveCommand() {
101
159
  return [
102
160
  '---',
@@ -150,6 +208,7 @@ function scaffoldFiles(host) {
150
208
  if (host === 'codex') {
151
209
  return [
152
210
  { path: 'AGENTS.md', content: renderCodexAgentsSnippet() },
211
+ { path: '.codex/hooks.json', content: renderCodexHooksJson() },
153
212
  { path: '.codex/prompts/gctree-bootstrap.md', content: renderCodexBootstrapPrompt() },
154
213
  { path: '.codex/skills/gc-resolve-context/SKILL.md', content: renderCodexResolveSkill() },
155
214
  { path: '.codex/skills/gc-onboard/SKILL.md', content: renderCodexOnboardSkill() },
@@ -158,6 +217,7 @@ function scaffoldFiles(host) {
158
217
  }
159
218
  return [
160
219
  { path: 'CLAUDE.md', content: renderClaudeSnippet() },
220
+ { path: '.claude/hooks/hooks.json', content: renderClaudeHooksJson() },
161
221
  { path: '.claude/hooks/gctree-session-start.md', content: renderClaudeSessionStartHook() },
162
222
  { path: '.claude/commands/gc-resolve-context.md', content: renderClaudeResolveCommand() },
163
223
  { path: '.claude/commands/gc-onboard.md', content: renderClaudeOnboardCommand() },
package/docs/usage.es.md CHANGED
@@ -145,6 +145,7 @@ gctree scaffold --host both --target /path/to/repo
145
145
 
146
146
  ```
147
147
  AGENTS.md ← fragmento de gctree añadido a las instrucciones del agente
148
+ .codex/hooks.json ← hooks de auto-resolve para SessionStart/UserPromptSubmit
148
149
  .codex/prompts/gctree-bootstrap.md ← contexto de arranque para las sesiones de Codex
149
150
  .codex/skills/gc-resolve-context/SKILL.md ← skill de resolve
150
151
  .codex/skills/gc-onboard/SKILL.md ← skill de onboarding
@@ -155,7 +156,8 @@ AGENTS.md ← fragmento de gctree añadido a la
155
156
 
156
157
  ```
157
158
  CLAUDE.md ← fragmento de gctree añadido
158
- .claude/hooks/gctree-session-start.md hook de inicio de sesión
159
+ .claude/hooks/hooks.json hooks de auto-resolve para SessionStart/UserPromptSubmit
160
+ .claude/hooks/gctree-session-start.md ← nota fallback de inicio de sesión
159
161
  .claude/commands/gc-resolve-context.md ← comando slash de resolve
160
162
  .claude/commands/gc-onboard.md ← comando slash de onboard
161
163
  .claude/commands/gc-update-global-context.md ← comando slash de actualización
package/docs/usage.ja.md CHANGED
@@ -145,6 +145,7 @@ gctree scaffold --host both --target /path/to/repo
145
145
 
146
146
  ```
147
147
  AGENTS.md ← gctree のスニペットがエージェント指示に追記される
148
+ .codex/hooks.json ← SessionStart / UserPromptSubmit の自動 resolve フック
148
149
  .codex/prompts/gctree-bootstrap.md ← Codex セッション向けのブートストラップコンテキスト
149
150
  .codex/skills/gc-resolve-context/SKILL.md ← resolve スキル
150
151
  .codex/skills/gc-onboard/SKILL.md ← オンボーディングスキル
@@ -155,7 +156,8 @@ AGENTS.md ← gctree のスニペットがエ
155
156
 
156
157
  ```
157
158
  CLAUDE.md ← gctree のスニペットが追記される
158
- .claude/hooks/gctree-session-start.md セッション開始フック
159
+ .claude/hooks/hooks.json SessionStart / UserPromptSubmit の自動 resolve フック
160
+ .claude/hooks/gctree-session-start.md ← セッション開始のフォールバックメモ
159
161
  .claude/commands/gc-resolve-context.md ← resolve スラッシュコマンド
160
162
  .claude/commands/gc-onboard.md ← onboard スラッシュコマンド
161
163
  .claude/commands/gc-update-global-context.md ← 更新スラッシュコマンド
package/docs/usage.ko.md CHANGED
@@ -145,6 +145,7 @@ gctree scaffold --host both --target /path/to/repo
145
145
 
146
146
  ```
147
147
  AGENTS.md ← 에이전트 지시사항에 gctree 스니펫 추가
148
+ .codex/hooks.json ← SessionStart/UserPromptSubmit 자동 resolve 훅
148
149
  .codex/prompts/gctree-bootstrap.md ← Codex 세션의 부트스트랩 컨텍스트
149
150
  .codex/skills/gc-resolve-context/SKILL.md ← resolve 스킬
150
151
  .codex/skills/gc-onboard/SKILL.md ← 온보딩 스킬
@@ -155,7 +156,8 @@ AGENTS.md ← 에이전트 지시사항에 gctr
155
156
 
156
157
  ```
157
158
  CLAUDE.md ← gctree 스니펫 추가
158
- .claude/hooks/gctree-session-start.md 세션 시작
159
+ .claude/hooks/hooks.json SessionStart/UserPromptSubmit 자동 resolve
160
+ .claude/hooks/gctree-session-start.md ← 세션 시작 fallback 메모
159
161
  .claude/commands/gc-resolve-context.md ← resolve 슬래시 명령
160
162
  .claude/commands/gc-onboard.md ← onboard 슬래시 명령
161
163
  .claude/commands/gc-update-global-context.md ← 업데이트 슬래시 명령
package/docs/usage.md CHANGED
@@ -145,6 +145,7 @@ gctree scaffold --host both --target /path/to/repo
145
145
 
146
146
  ```
147
147
  AGENTS.md ← gctree snippet appended to agent instructions
148
+ .codex/hooks.json ← SessionStart/UserPromptSubmit auto-resolve hooks
148
149
  .codex/prompts/gctree-bootstrap.md ← bootstrap context for Codex sessions
149
150
  .codex/skills/gc-resolve-context/SKILL.md ← resolve skill
150
151
  .codex/skills/gc-onboard/SKILL.md ← onboarding skill
@@ -155,7 +156,8 @@ AGENTS.md ← gctree snippet appended to agent
155
156
 
156
157
  ```
157
158
  CLAUDE.md ← gctree snippet appended
158
- .claude/hooks/gctree-session-start.md session-start hook
159
+ .claude/hooks/hooks.json SessionStart/UserPromptSubmit auto-resolve hooks
160
+ .claude/hooks/gctree-session-start.md ← session-start fallback note
159
161
  .claude/commands/gc-resolve-context.md ← resolve slash command
160
162
  .claude/commands/gc-onboard.md ← onboard slash command
161
163
  .claude/commands/gc-update-global-context.md ← update slash command
package/docs/usage.zh.md CHANGED
@@ -145,6 +145,7 @@ gctree scaffold --host both --target /path/to/repo
145
145
 
146
146
  ```
147
147
  AGENTS.md ← gctree 代码片段追加到 agent 指令中
148
+ .codex/hooks.json ← SessionStart / UserPromptSubmit 自动 resolve hook
148
149
  .codex/prompts/gctree-bootstrap.md ← Codex 会话的引导上下文
149
150
  .codex/skills/gc-resolve-context/SKILL.md ← resolve 技能
150
151
  .codex/skills/gc-onboard/SKILL.md ← onboarding 技能
@@ -155,7 +156,8 @@ AGENTS.md ← gctree 代码片段追加到 agen
155
156
 
156
157
  ```
157
158
  CLAUDE.md ← gctree 代码片段追加
158
- .claude/hooks/gctree-session-start.md 会话启动钩子
159
+ .claude/hooks/hooks.json SessionStart / UserPromptSubmit 自动 resolve hook
160
+ .claude/hooks/gctree-session-start.md ← 会话启动 fallback 说明
159
161
  .claude/commands/gc-resolve-context.md ← resolve 斜杠命令
160
162
  .claude/commands/gc-onboard.md ← onboard 斜杠命令
161
163
  .claude/commands/gc-update-global-context.md ← 更新斜杠命令
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@handsupmin/gc-tree",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Global Context Tree, a lightweight branch-aware global context orchestrator for AI coding tools",
5
5
  "type": "module",
6
6
  "private": false,