@ghl-ai/aw 0.1.35-beta.2 → 0.1.35-beta.4

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/commands/init.mjs CHANGED
@@ -19,7 +19,6 @@ import { generateCommands, copyInstructions, initAwDocs } from '../integrate.mjs
19
19
  import { setupMcp } from '../mcp.mjs';
20
20
  import { autoUpdate, promptUpdate } from '../update.mjs';
21
21
  import { installGlobalHooks } from '../hooks.mjs';
22
- import { installIdeHooks } from '../ide-hooks.mjs';
23
22
 
24
23
  const __dirname = dirname(fileURLToPath(import.meta.url));
25
24
  const VERSION = JSON.parse(readFileSync(join(__dirname, '..', 'package.json'), 'utf8')).version;
@@ -207,7 +206,6 @@ export async function initCommand(args) {
207
206
  setupMcp(HOME, freshCfg?.namespace || team) || [];
208
207
  if (cwd !== HOME) setupMcp(cwd, freshCfg?.namespace || team);
209
208
  installGlobalHooks();
210
- const ideHookFiles = installIdeHooks(HOME);
211
209
 
212
210
  // Link current project if needed
213
211
  if (cwd !== HOME && !existsSync(join(cwd, '.aw_registry'))) {
@@ -288,7 +286,6 @@ export async function initCommand(args) {
288
286
  const mcpFiles = setupMcp(HOME, team) || [];
289
287
  if (cwd !== HOME) setupMcp(cwd, team);
290
288
  const hooksInstalled = installGlobalHooks();
291
- const ideHookFilesInit = installIdeHooks(HOME);
292
289
  installIdeTasks();
293
290
 
294
291
  // Step 4: Symlink in current directory if it's a git repo
@@ -307,7 +304,6 @@ export async function initCommand(args) {
307
304
  createdFiles: [
308
305
  ...instructionFiles.map(p => p.startsWith(HOME) ? p.slice(HOME.length + 1) : p),
309
306
  ...mcpFiles.map(p => p.startsWith(HOME) ? p.slice(HOME.length + 1) : p),
310
- ...(ideHookFilesInit || []).map(p => p.startsWith(HOME) ? p.slice(HOME.length + 1) : p),
311
307
  ],
312
308
  globalHooksDir: hooksInstalled ? join(HOME, '.aw', 'hooks') : null,
313
309
  };
package/commands/nuke.mjs CHANGED
@@ -9,14 +9,13 @@ import { execSync } from 'node:child_process';
9
9
  import * as fmt from '../fmt.mjs';
10
10
  import { chalk } from '../fmt.mjs';
11
11
  import { removeGlobalHooks } from '../hooks.mjs';
12
- import { removeIdeHooks } from '../ide-hooks.mjs';
13
12
 
14
13
  const HOME = homedir();
15
14
  const GLOBAL_AW_DIR = join(HOME, '.aw_registry');
16
15
  const MANIFEST_PATH = join(GLOBAL_AW_DIR, '.aw-manifest.json');
17
16
 
18
17
  const IDE_DIRS = ['.claude', '.cursor', '.codex', '.agents'];
19
- const CONTENT_TYPES = ['agents', 'skills', 'commands', 'evals'];
18
+ const CONTENT_TYPES = ['agents', 'skills', 'commands', 'evals', 'hooks'];
20
19
 
21
20
  function loadManifest() {
22
21
  if (!existsSync(MANIFEST_PATH)) return null;
@@ -250,10 +249,7 @@ export function nukeCommand(args) {
250
249
  // 4. Remove git hooks (core.hooksPath + legacy template)
251
250
  removeGitHooks(manifest);
252
251
 
253
- // 5. Remove IDE session hooks (superpowers bootstrap)
254
- removeIdeHooks(HOME);
255
-
256
- // 6. Remove IDE auto-init tasks
252
+ // 5. Remove IDE auto-init tasks
257
253
  removeIdeTasks();
258
254
 
259
255
  // 5b. Remove upgrade lock/log (inside .aw_registry, must happen before dir removal)
@@ -94,7 +94,7 @@ function searchLocal(workspaceDir, query) {
94
94
  if (!nsEntry.isDirectory() || nsEntry.name.startsWith('.')) continue;
95
95
  const ns = nsEntry.name;
96
96
 
97
- for (const type of ['agents', 'skills', 'commands', 'evals']) {
97
+ for (const type of ['agents', 'skills', 'commands', 'evals', 'hooks']) {
98
98
  const typeDir = join(workspaceDir, ns, type);
99
99
  if (!existsSync(typeDir)) continue;
100
100
 
package/constants.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  // constants.mjs — Single source of truth for registry settings.
2
2
 
3
3
  /** Base branch for PRs and sync checkout */
4
- export const REGISTRY_BASE_BRANCH = 'sync/platform-superpowers-l8ynb';
4
+ export const REGISTRY_BASE_BRANCH = 'sync/platform-superpowers-n1qrx';
5
5
 
6
6
  /** Default registry repository */
7
7
  export const REGISTRY_REPO = 'GoHighLevel/platform-docs';
package/link.mjs CHANGED
@@ -13,7 +13,7 @@ function forceSymlink(target, linkPath) {
13
13
  const IDE_DIRS = ['.claude', '.cursor', '.codex'];
14
14
  // Per-file symlink types
15
15
  const FILE_TYPES = ['agents'];
16
- const ALL_KNOWN_TYPES = new Set([...FILE_TYPES, 'skills', 'commands', 'evals', 'docs']);
16
+ const ALL_KNOWN_TYPES = new Set([...FILE_TYPES, 'skills', 'commands', 'evals', 'hooks', 'docs']);
17
17
 
18
18
  /**
19
19
  * List namespace directories inside .aw_registry/ (skip dotfiles).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.35-beta.2",
3
+ "version": "0.1.35-beta.4",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {
@@ -24,8 +24,7 @@
24
24
  "registry.mjs",
25
25
  "apply.mjs",
26
26
  "update.mjs",
27
- "hooks.mjs",
28
- "ide-hooks.mjs"
27
+ "hooks.mjs"
29
28
  ],
30
29
  "engines": {
31
30
  "node": ">=18.0.0"
package/paths.mjs CHANGED
@@ -3,7 +3,7 @@
3
3
  import { existsSync, statSync, lstatSync, readlinkSync } from 'node:fs';
4
4
  import { join, resolve, relative, basename, dirname } from 'node:path';
5
5
 
6
- const VALID_TYPES = new Set(['agents', 'skills', 'commands', 'evals']);
6
+ const VALID_TYPES = new Set(['agents', 'skills', 'commands', 'evals', 'hooks']);
7
7
 
8
8
  // IDE dirs that may contain symlinks into .aw_registry/
9
9
  const IDE_PREFIXES = ['.claude/', '.cursor/', '.codex/', '.agents/'];
package/plan.mjs CHANGED
@@ -46,8 +46,9 @@ export function computePlan(registryDirs, workspaceDir, includePatterns = [], {
46
46
  targetFilename = `${entry.namespacePath}/${entry.type}/${entry.slug}/${entry.skillRelPath}`;
47
47
  targetPath = join(workspaceDir, entry.namespacePath, entry.type, entry.slug, entry.skillRelPath);
48
48
  } else {
49
- targetFilename = `${entry.namespacePath}/${entry.type}/${entry.slug}.md`;
50
- targetPath = join(workspaceDir, entry.namespacePath, entry.type, `${entry.slug}.md`);
49
+ const fileName = entry.filename || `${entry.slug}.md`;
50
+ targetFilename = `${entry.namespacePath}/${entry.type}/${fileName}`;
51
+ targetPath = join(workspaceDir, entry.namespacePath, entry.type, fileName);
51
52
  }
52
53
 
53
54
  const manifestKey = targetFilename;
@@ -113,7 +114,7 @@ export function computePlan(registryDirs, workspaceDir, includePatterns = [], {
113
114
  const parts = manifestKey.split('/');
114
115
  let typeIdx = -1;
115
116
  for (let i = 0; i < parts.length; i++) {
116
- if (['agents', 'skills', 'commands', 'evals'].includes(parts[i])) {
117
+ if (['agents', 'skills', 'commands', 'evals', 'hooks'].includes(parts[i])) {
117
118
  typeIdx = i;
118
119
  break;
119
120
  }
package/registry.mjs CHANGED
@@ -4,7 +4,7 @@ import { readFileSync, existsSync, readdirSync, statSync } from 'node:fs';
4
4
  import { join, relative } from 'node:path';
5
5
  import { createHash } from 'node:crypto';
6
6
 
7
- const TYPE_DIRS = new Set(['agents', 'skills', 'commands', 'evals']);
7
+ const TYPE_DIRS = new Set(['agents', 'skills', 'commands', 'evals', 'hooks']);
8
8
  const SKIP_DIRS = new Set(['docs']);
9
9
 
10
10
  export function sha256(content) {
@@ -84,7 +84,7 @@ export function walkRegistryTree(baseDir, baseName) {
84
84
  });
85
85
  }
86
86
  } else {
87
- // Agents, commands — flat files
87
+ // Agents, commands, hooks — flat files
88
88
  for (const fileEntry of readdirSync(fullPath)) {
89
89
  if (fileEntry === '.gitkeep' || fileEntry.startsWith('.')) continue;
90
90
  const filePath = join(fullPath, fileEntry);
package/ide-hooks.mjs DELETED
@@ -1,193 +0,0 @@
1
- // ide-hooks.mjs — Generate IDE session-start hooks for superpowers bootstrap.
2
- //
3
- // installIdeHooks(cwd) → writes/merges hook configs into ~/.claude/ and ~/.cursor/
4
- // removeIdeHooks(cwd) → removes aw-generated hook entries from IDE hook configs
5
-
6
- import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
7
- import { join } from 'node:path';
8
- import { homedir } from 'node:os';
9
- import * as fmt from './fmt.mjs';
10
-
11
- const HOME = homedir();
12
- const AW_REGISTRY = join(HOME, '.aw_registry');
13
- const HOOKS_DIR = join(AW_REGISTRY, 'platform', 'superpowers', 'hooks');
14
- const SESSION_START = join(HOOKS_DIR, 'session-start');
15
- const RUN_HOOK_CMD = join(HOOKS_DIR, 'run-hook.cmd');
16
-
17
- const AW_MARKER = 'aw-superpowers-session';
18
-
19
- /**
20
- * Install IDE session-start hooks that bootstrap using-superpowers.
21
- * Only installs if the superpowers hooks exist in the registry.
22
- * Merges with existing hook configs — never clobbers user hooks.
23
- * @returns {string[]} paths of created/modified hook config files
24
- */
25
- export function installIdeHooks(cwd) {
26
- if (!existsSync(SESSION_START)) return [];
27
-
28
- const created = [];
29
-
30
- const claudeResult = installClaudeCodeHooks(cwd);
31
- if (claudeResult) created.push(claudeResult);
32
-
33
- const cursorResult = installCursorHooks(cwd);
34
- if (cursorResult) created.push(cursorResult);
35
-
36
- if (created.length > 0) {
37
- fmt.logStep('IDE session hooks installed (superpowers bootstrap)');
38
- }
39
-
40
- return created;
41
- }
42
-
43
- /**
44
- * Remove aw-generated hook entries from IDE hook configs.
45
- */
46
- export function removeIdeHooks(cwd) {
47
- removeClaudeCodeHooks(cwd);
48
- removeCursorHooks(cwd);
49
- fmt.logStep('IDE session hooks removed');
50
- }
51
-
52
- // ── Claude Code ─────────────────────────────────────────────────────────
53
-
54
- function installClaudeCodeHooks(cwd) {
55
- const hooksPath = join(HOME, '.claude', 'hooks.json');
56
-
57
- const hookEntry = {
58
- matcher: AW_MARKER,
59
- hooks: [{
60
- type: 'command',
61
- command: `"${RUN_HOOK_CMD}" session-start`,
62
- async: false,
63
- }],
64
- };
65
-
66
- let config;
67
- if (existsSync(hooksPath)) {
68
- try {
69
- config = JSON.parse(readFileSync(hooksPath, 'utf8'));
70
- } catch {
71
- return null;
72
- }
73
-
74
- if (!config.hooks) config.hooks = {};
75
- if (!Array.isArray(config.hooks.SessionStart)) config.hooks.SessionStart = [];
76
-
77
- const existing = config.hooks.SessionStart.findIndex(
78
- e => e.matcher === AW_MARKER
79
- );
80
- if (existing !== -1) {
81
- config.hooks.SessionStart[existing] = hookEntry;
82
- } else {
83
- config.hooks.SessionStart.push(hookEntry);
84
- }
85
- } else {
86
- mkdirSync(join(HOME, '.claude'), { recursive: true });
87
- config = {
88
- hooks: {
89
- SessionStart: [hookEntry],
90
- },
91
- };
92
- }
93
-
94
- writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
95
- return hooksPath;
96
- }
97
-
98
- function removeClaudeCodeHooks(cwd) {
99
- const hooksPath = join(HOME, '.claude', 'hooks.json');
100
- if (!existsSync(hooksPath)) return;
101
-
102
- try {
103
- const config = JSON.parse(readFileSync(hooksPath, 'utf8'));
104
- if (!config.hooks?.SessionStart) return;
105
-
106
- config.hooks.SessionStart = config.hooks.SessionStart.filter(
107
- e => e.matcher !== AW_MARKER
108
- );
109
-
110
- if (config.hooks.SessionStart.length === 0) {
111
- delete config.hooks.SessionStart;
112
- }
113
- if (Object.keys(config.hooks).length === 0) {
114
- delete config.hooks;
115
- }
116
-
117
- if (Object.keys(config).length === 0) {
118
- writeFileSync(hooksPath, '{}\n');
119
- } else {
120
- writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
121
- }
122
- } catch { /* best effort */ }
123
- }
124
-
125
- // ── Cursor ──────────────────────────────────────────────────────────────
126
-
127
- function installCursorHooks(cwd) {
128
- const hooksPath = join(HOME, '.cursor', 'hooks.json');
129
-
130
- const hookEntry = {
131
- command: SESSION_START,
132
- _aw: AW_MARKER,
133
- };
134
-
135
- let config;
136
- if (existsSync(hooksPath)) {
137
- try {
138
- config = JSON.parse(readFileSync(hooksPath, 'utf8'));
139
- } catch {
140
- return null;
141
- }
142
-
143
- if (!config.hooks) config.hooks = {};
144
- if (!Array.isArray(config.hooks.sessionStart)) config.hooks.sessionStart = [];
145
-
146
- const existing = config.hooks.sessionStart.findIndex(
147
- e => e._aw === AW_MARKER
148
- );
149
- if (existing !== -1) {
150
- config.hooks.sessionStart[existing] = hookEntry;
151
- } else {
152
- config.hooks.sessionStart.push(hookEntry);
153
- }
154
- } else {
155
- mkdirSync(join(HOME, '.cursor'), { recursive: true });
156
- config = {
157
- version: 1,
158
- hooks: {
159
- sessionStart: [hookEntry],
160
- },
161
- };
162
- }
163
-
164
- writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
165
- return hooksPath;
166
- }
167
-
168
- function removeCursorHooks(cwd) {
169
- const hooksPath = join(HOME, '.cursor', 'hooks.json');
170
- if (!existsSync(hooksPath)) return;
171
-
172
- try {
173
- const config = JSON.parse(readFileSync(hooksPath, 'utf8'));
174
- if (!config.hooks?.sessionStart) return;
175
-
176
- config.hooks.sessionStart = config.hooks.sessionStart.filter(
177
- e => e._aw !== AW_MARKER
178
- );
179
-
180
- if (config.hooks.sessionStart.length === 0) {
181
- delete config.hooks.sessionStart;
182
- }
183
- if (config.hooks && Object.keys(config.hooks).length === 0) {
184
- delete config.hooks;
185
- }
186
-
187
- if (Object.keys(config).length <= 1 && config.version) {
188
- writeFileSync(hooksPath, JSON.stringify({ version: config.version }, null, 2) + '\n');
189
- } else {
190
- writeFileSync(hooksPath, JSON.stringify(config, null, 2) + '\n');
191
- }
192
- } catch { /* best effort */ }
193
- }