@ghl-ai/aw 0.1.38-beta.17 → 0.1.38-beta.19

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.
Files changed (2) hide show
  1. package/ecc.mjs +71 -1
  2. package/package.json +1 -1
package/ecc.mjs CHANGED
@@ -9,7 +9,7 @@ import * as fmt from "./fmt.mjs";
9
9
 
10
10
  const AW_ECC_REPO_SSH = "git@github.com:shreyansh-ghl/aw-ecc.git";
11
11
  const AW_ECC_REPO_HTTPS = "https://github.com/shreyansh-ghl/aw-ecc.git";
12
- const AW_ECC_TAG = "v1.4.27";
12
+ const AW_ECC_TAG = "v1.4.28";
13
13
 
14
14
  const MARKETPLACE_NAME = "aw-marketplace";
15
15
  const PLUGIN_KEY = `aw@${MARKETPLACE_NAME}`;
@@ -124,8 +124,57 @@ function installClaudePlugin(repoDir) {
124
124
  // previously-registered path, which may point to a stale/wrong directory.
125
125
  try { run(`claude plugin uninstall ${PLUGIN_KEY} --scope user`); } catch { /* not installed */ }
126
126
  try { run(`claude plugin marketplace remove ${MARKETPLACE_NAME}`); } catch { /* not registered */ }
127
+
128
+ // Purge stale plugin cache — Claude Code caches by package.json version,
129
+ // so old entries with outdated hooks can shadow a fresh install.
130
+ const cacheDir = join(homedir(), ".claude", "plugins", "cache", MARKETPLACE_NAME);
131
+ if (existsSync(cacheDir)) {
132
+ try { rmSync(cacheDir, { recursive: true, force: true }); } catch { /* best effort */ }
133
+ }
134
+
127
135
  run(`claude plugin marketplace add ${repoDir} --scope user`);
128
136
  run(`claude plugin install ${PLUGIN_KEY} --scope user`);
137
+
138
+ // Plugin SessionStart hooks have a known issue where Claude Code fires them
139
+ // but silently discards the output. As a workaround, also register the
140
+ // SessionStart hook directly in ~/.claude/settings.json — this path is
141
+ // reliable and bypasses the plugin hook dispatch entirely.
142
+ ensureSessionStartHook(repoDir);
143
+ }
144
+
145
+ /**
146
+ * Add a SessionStart hook to ~/.claude/settings.json that calls the
147
+ * using-aw-skills session-start script directly. This is more reliable
148
+ * than the plugin hook path because Claude Code's plugin hook dispatch
149
+ * sometimes silently drops SessionStart output.
150
+ */
151
+ function ensureSessionStartHook(repoDir) {
152
+ const settingsPath = join(homedir(), ".claude", "settings.json");
153
+ let settings = {};
154
+ try {
155
+ if (existsSync(settingsPath)) {
156
+ settings = JSON.parse(readFileSync(settingsPath, "utf8"));
157
+ }
158
+ } catch { /* start fresh */ }
159
+
160
+ const hookCmd = `bash "$HOME/.aw-ecc/skills/using-aw-skills/hooks/session-start.sh"`;
161
+
162
+ // Check if already present
163
+ const existing = settings.hooks?.SessionStart || [];
164
+ const alreadyHas = existing.some((entry) =>
165
+ entry.hooks?.some((h) => h.command === hookCmd),
166
+ );
167
+ if (alreadyHas) return;
168
+
169
+ if (!settings.hooks) settings.hooks = {};
170
+ if (!settings.hooks.SessionStart) settings.hooks.SessionStart = [];
171
+
172
+ settings.hooks.SessionStart.push({
173
+ hooks: [{ type: "command", command: hookCmd }],
174
+ });
175
+
176
+ mkdirSync(dirname(settingsPath), { recursive: true });
177
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
129
178
  }
130
179
 
131
180
  function uninstallClaudePlugin() {
@@ -133,6 +182,22 @@ function uninstallClaudePlugin() {
133
182
  try { run(`claude plugin marketplace remove ${MARKETPLACE_NAME}`); } catch { /* not registered */ }
134
183
  }
135
184
 
185
+ function removeSessionStartHook() {
186
+ const settingsPath = join(homedir(), ".claude", "settings.json");
187
+ if (!existsSync(settingsPath)) return;
188
+ try {
189
+ const settings = JSON.parse(readFileSync(settingsPath, "utf8"));
190
+ const hooks = settings.hooks?.SessionStart;
191
+ if (!Array.isArray(hooks)) return;
192
+ settings.hooks.SessionStart = hooks.filter((entry) =>
193
+ !entry.hooks?.some((h) => h.command?.includes(".aw-ecc/")),
194
+ );
195
+ if (settings.hooks.SessionStart.length === 0) delete settings.hooks.SessionStart;
196
+ if (Object.keys(settings.hooks).length === 0) delete settings.hooks;
197
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2));
198
+ } catch { /* best effort */ }
199
+ }
200
+
136
201
  /**
137
202
  * Move ecc command files from ~/.cursor/commands/*.md → ~/.cursor/commands/aw/*.md
138
203
  * so Cursor exposes them as /aw:tdd, /aw:plan — consistent with Claude Code's plugin namespace.
@@ -261,6 +326,11 @@ export function uninstallAwEcc({ silent = false } = {}) {
261
326
  removed++;
262
327
  } catch { /* best effort */ }
263
328
 
329
+ // Remove SessionStart hook from settings.json
330
+ try {
331
+ removeSessionStartHook();
332
+ } catch { /* best effort */ }
333
+
264
334
  // Cursor + Codex: remove file-copied content via install-state
265
335
  for (const cfg of Object.values(TARGET_STATE)) {
266
336
  const statePath = join(HOME, cfg.state);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.38-beta.17",
3
+ "version": "0.1.38-beta.19",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": "bin.js",