aiblueprint-cli 1.4.97 → 1.4.99

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.md CHANGED
@@ -146,6 +146,7 @@ npx skills add Melvynx/aiblueprint --skill skill-manager
146
146
  | `create-pr` | Auto-generated pull requests |
147
147
  | `fix-pr-comments` | Resolve PR review comments |
148
148
  | `grill-me` | Stress-test a plan with focused questions |
149
+ | `hooks-manager` | Create and debug Claude Code hooks |
149
150
  | `merge` | Context-aware branch merging |
150
151
  | `environments-manager` | Set up per-worktree agent environments |
151
152
  | `oneshot` | Implement one focused change quickly |
@@ -160,7 +161,22 @@ npx skills add Melvynx/aiblueprint --skill skill-manager
160
161
  | `use-goal` | Create evidence-based agent goals |
161
162
  | `ultrathink` | Deep thinking mode for elegant solutions |
162
163
 
163
- ## 💎 Premium
164
+ ## 🤖 Assistant Pro
165
+
166
+ Install the latest complete skill bundle from the private
167
+ [`assistant-pro-skills`](https://github.com/Melvynx/assistant-pro-skills)
168
+ repository:
169
+
170
+ ```bash
171
+ npx aiblueprint-cli@latest assistants pro setup
172
+ ```
173
+
174
+ The command asks for the Assistant Pro access key when needed, installs the
175
+ versioned `all` bundle into `~/.agents/skills`, creates Claude Code and Codex
176
+ skill symlinks, adds the shared directory to Hermes, and exposes the same skills
177
+ to OpenClaw through its native `~/.agents/skills` discovery.
178
+
179
+ ## 💎 Agents Config Pro
164
180
 
165
181
  Unlock advanced features at [mlv.sh/claude-cli](https://mlv.sh/claude-cli)
166
182
 
@@ -197,6 +213,7 @@ bun run test-local
197
213
  - Node.js 16+ or Bun
198
214
  - Claude Code installed
199
215
  - Optional: `bun`, `gh CLI`
216
+ - Python 3 for `assistants pro setup`
200
217
 
201
218
  ## 🤝 Contributing
202
219
 
@@ -0,0 +1,53 @@
1
+ ---
2
+ name: hooks-manager
3
+ description: Create, edit, configure, and debug Claude Code hooks. Use when working with hooks, event listeners, command validation, automated workflows, notifications, or hook events such as PreToolUse, PostToolUse, Stop, SessionStart, and UserPromptSubmit.
4
+ ---
5
+
6
+ # Hooks Manager
7
+
8
+ Configure Claude Code hooks as event-driven commands or prompts. Use hooks for validation, logging, formatting, notifications, context injection, and bounded completion checks.
9
+
10
+ ## Quick workflow
11
+
12
+ 1. Identify the scope: project `.claude/hooks.json` or user `~/.claude/hooks.json`.
13
+ 2. Select the event (`PreToolUse`, `PostToolUse`, `UserPromptSubmit`, `Stop`, `SubagentStop`, `SessionStart`, `SessionEnd`, `PreCompact`, or `Notification`).
14
+ 3. Choose a command hook for deterministic shell logic, or a prompt hook when natural-language reasoning is required.
15
+ 4. Add a regex matcher for the tools that should trigger it.
16
+ 5. Validate the JSON with `jq` and test with `claude --debug`.
17
+
18
+ ## Hook shape
19
+
20
+ ```json
21
+ {
22
+ "hooks": {
23
+ "PreToolUse": [
24
+ {
25
+ "matcher": "Bash",
26
+ "hooks": [
27
+ { "type": "command", "command": "./.claude/hooks/check.sh", "timeout": 30000 }
28
+ ]
29
+ }
30
+ ]
31
+ }
32
+ }
33
+ ```
34
+
35
+ Command hooks receive JSON on stdin and may return JSON on stdout. Prompt hooks receive `#$ARGUMENTS` and should return a structured decision. Blocking hooks use `{"decision":"block","reason":"..."}`; non-blocking hooks may return a `systemMessage`.
36
+
37
+ ## Safety requirements
38
+
39
+ - Check `stop_hook_active` in `Stop` and `SubagentStop` hooks to prevent recursive blocking.
40
+ - Set reasonable timeouts, especially for external commands.
41
+ - Use `$CLAUDE_PROJECT_DIR` or another trusted absolute path for scripts.
42
+ - Validate hook JSON with `jq` before relying on it.
43
+ - Keep blocking rules selective so normal work is not accidentally interrupted.
44
+ - Ensure referenced scripts are executable.
45
+
46
+ ## References
47
+
48
+ - `references/hook-types.md`: events, input/output, and blocking behavior.
49
+ - `references/command-vs-prompt.md`: choose command versus prompt hooks.
50
+ - `references/matchers.md`: regex and MCP matcher patterns.
51
+ - `references/input-output-schemas.md`: event schemas and response fields.
52
+ - `references/examples.md`: notifications, logging, formatting, tests, and safety examples.
53
+ - `references/troubleshooting.md`: debug, JSON, matcher, permission, and timeout checks.
@@ -0,0 +1,7 @@
1
+ interface:
2
+ display_name: "Hooks Manager"
3
+ short_description: "Create, edit, configure, and debug Claude Code hooks"
4
+ icon_small: "./assets/codex-icon.svg"
5
+ icon_large: "./assets/codex-icon.svg"
6
+ brand_color: "#868259"
7
+ default_prompt: "Use $hooks-manager to help with this task."
@@ -0,0 +1,5 @@
1
+ <svg role="img" aria-label="hooks-manager skill icon" width="64" height="64" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg">
2
+ <rect width="64" height="64" rx="16" fill="#868259"/>
3
+ <path d="M20 22h24v6H20v-6Zm0 14h16v6H20v-6Zm0 14h24v6H20v-6Z" fill="#fff"/>
4
+ <circle cx="44" cy="39" r="7" fill="#868259" stroke="#fff" stroke-width="4"/>
5
+ </svg>
@@ -0,0 +1,12 @@
1
+ # Command vs Prompt Hooks
2
+
3
+ Use command hooks for deterministic, fast work: file checks, regex validation, formatters, linters, logs, and notifications. They receive JSON through stdin and may emit JSON through stdout.
4
+
5
+ Use prompt hooks when the decision requires semantic or natural-language reasoning. They are slower and consume model/API budget. Include `#$ARGUMENTS` and specify the exact JSON response shape.
6
+
7
+ ```json
8
+ {
9
+ "type": "prompt",
10
+ "prompt": "Evaluate this change: #$ARGUMENTS\nReturn {\"decision\":\"approve\" or \"block\",\"reason\":\"...\"}"
11
+ }
12
+ ```
@@ -0,0 +1,15 @@
1
+ # Hook Examples
2
+
3
+ Log Bash commands:
4
+
5
+ ```json
6
+ {"type":"command","command":"jq -r '.tool_input.command' >> ~/.claude/bash-log.txt"}
7
+ ```
8
+
9
+ Format files after edits:
10
+
11
+ ```json
12
+ {"type":"command","command":"prettier --write \"$CLAUDE_PROJECT_DIR\"","timeout":10000}
13
+ ```
14
+
15
+ Block destructive commands with a `PreToolUse` prompt hook, or run a test-checking command on `Stop`. Keep examples scoped to the project and validate the resulting JSON with `jq`.
@@ -0,0 +1,13 @@
1
+ # Hook Types and Events
2
+
3
+ | Event | Fires | Can block? |
4
+ | --- | --- | --- |
5
+ | `PreToolUse` | Before a tool runs | Yes |
6
+ | `PostToolUse` | After a tool completes | No |
7
+ | `UserPromptSubmit` | When the user submits a prompt | Yes |
8
+ | `Stop` / `SubagentStop` | Before an agent stops | Yes |
9
+ | `SessionStart` / `SessionEnd` | At session boundaries | No |
10
+ | `PreCompact` | Before context compaction | Yes |
11
+ | `Notification` | When Claude needs input | No |
12
+
13
+ Blocking responses should include `decision: "block"` and a useful `reason`. Stop hooks must honor `stop_hook_active` to avoid infinite loops.
@@ -0,0 +1,11 @@
1
+ # Input and Output Schemas
2
+
3
+ Common hook input includes `session_id`, `transcript_path`, `cwd`, `permission_mode`, and `hook_event_name`. Tool events also include `tool_name` and `tool_input`; prompt submission includes `prompt`.
4
+
5
+ Blocking output:
6
+
7
+ ```json
8
+ {"decision":"block","reason":"Explain what must change"}
9
+ ```
10
+
11
+ Non-blocking output may include `systemMessage` and `suppressOutput`. `PreToolUse` may additionally return `permissionDecision` and `updatedInput`. `Stop` may return `continue: true` and should not block when `stop_hook_active` is true.
@@ -0,0 +1,9 @@
1
+ # Matchers
2
+
3
+ Matchers are JavaScript regular expressions tested against the tool name. Use `Bash` for one tool, `Write|Edit` for alternatives, `^Bash` for a tool family, `mcp__.*` for all MCP tools, and `mcp__github__.*` for one MCP server. Omitting `matcher` matches every tool for that event.
4
+
5
+ Patterns are case-sensitive. Validate uncertain patterns in isolation:
6
+
7
+ ```bash
8
+ node -e "console.log(/Bash/.test('Bash'))"
9
+ ```
@@ -0,0 +1,10 @@
1
+ # Troubleshooting
2
+
3
+ 1. Run `claude --debug` and confirm the event and matcher were found.
4
+ 2. Check the config location: `.claude/hooks.json`, `~/.claude/hooks.json`, or the plugin hook file.
5
+ 3. Validate syntax with `jq . .claude/hooks.json`.
6
+ 4. Confirm matcher case and regex escaping; `bash` does not match `Bash`.
7
+ 5. Run command hooks directly with representative JSON on stdin.
8
+ 6. Check script permissions, dependencies such as `jq`, trusted paths, and timeout values.
9
+
10
+ If a Stop hook blocks repeatedly, inspect `stop_hook_active` and return an allow/no-decision response when it is true.
package/dist/cli.js CHANGED
@@ -37539,11 +37539,14 @@ import path21 from "path";
37539
37539
  var import_fs_extra15 = __toESM(require_lib4(), 1);
37540
37540
  import os17 from "os";
37541
37541
  import path19 from "path";
37542
- import { exec as exec3 } from "child_process";
37542
+ import { exec as exec3, execFile } from "child_process";
37543
37543
  import { promisify as promisify2 } from "util";
37544
37544
  var execAsync2 = promisify2(exec3);
37545
+ var execFileAsync = promisify2(execFile);
37545
37546
  var PREMIUM_REPO = "Melvynx/aiblueprint-cli-premium";
37546
37547
  var PREMIUM_BRANCH = "main";
37548
+ var ASSISTANT_PRO_REPO = "Melvynx/assistant-pro-skills";
37549
+ var ASSISTANT_PRO_BRANCH = "main";
37547
37550
  var CONFIG_FOLDER_CANDIDATES2 = ["agents-config", "ai-coding", "claude-code-config", "ai-config"];
37548
37551
  function routePath(relativePath) {
37549
37552
  const segments = relativePath.split(path19.sep);
@@ -37771,6 +37774,164 @@ async function syncAllAgentSymlinks(agentsDir, claudeDir) {
37771
37774
  await syncCategorySymlinks(category, agentsDir, claudeDir, undefined, true);
37772
37775
  }
37773
37776
  }
37777
+ function getAssistantProCacheDir() {
37778
+ return path19.join(os17.homedir(), ".config", "aiblueprint", "pro-repos", "assistant-pro-skills");
37779
+ }
37780
+ async function runAuthenticatedGit(args, token, cwd) {
37781
+ const authorization = Buffer.from(`x-access-token:${token}`).toString("base64");
37782
+ try {
37783
+ await execFileAsync("git", ["-c", `http.extraHeader=Authorization: Basic ${authorization}`, ...args], { cwd, timeout: 120000 });
37784
+ } catch {
37785
+ throw new Error("Unable to download the latest Assistant Pro skills from GitHub");
37786
+ }
37787
+ }
37788
+ async function cloneOrUpdateAssistantProRepo(githubToken) {
37789
+ const cacheDir = getAssistantProCacheDir();
37790
+ const repoUrl = `https://github.com/${ASSISTANT_PRO_REPO}.git`;
37791
+ if (await import_fs_extra15.default.pathExists(path19.join(cacheDir, ".git"))) {
37792
+ await runAuthenticatedGit(["fetch", "origin", ASSISTANT_PRO_BRANCH], githubToken, cacheDir);
37793
+ await runAuthenticatedGit(["merge", "--ff-only", "FETCH_HEAD"], githubToken, cacheDir);
37794
+ return cacheDir;
37795
+ }
37796
+ if (await import_fs_extra15.default.pathExists(cacheDir)) {
37797
+ throw new Error(`Assistant Pro cache is not a Git repository: ${cacheDir}`);
37798
+ }
37799
+ await import_fs_extra15.default.ensureDir(path19.dirname(cacheDir));
37800
+ await runAuthenticatedGit([
37801
+ "clone",
37802
+ "--branch",
37803
+ ASSISTANT_PRO_BRANCH,
37804
+ "--single-branch",
37805
+ repoUrl,
37806
+ cacheDir
37807
+ ], githubToken);
37808
+ return cacheDir;
37809
+ }
37810
+ async function installAssistantProSkills(options) {
37811
+ const cacheDir = await cloneOrUpdateAssistantProRepo(options.githubToken);
37812
+ const installerPath = path19.join(cacheDir, "ap_skills.py");
37813
+ const manifestPath = path19.join(cacheDir, "manifest.json");
37814
+ if (!await import_fs_extra15.default.pathExists(installerPath) || !await import_fs_extra15.default.pathExists(manifestPath)) {
37815
+ throw new Error("Assistant Pro repository is missing ap_skills.py or manifest.json");
37816
+ }
37817
+ try {
37818
+ await execFileAsync("python3", [
37819
+ installerPath,
37820
+ "--home",
37821
+ options.rootDir,
37822
+ "--json",
37823
+ "install",
37824
+ "--bundle",
37825
+ "all",
37826
+ "--target",
37827
+ "codex"
37828
+ ], { cwd: cacheDir, timeout: 120000 });
37829
+ } catch (error) {
37830
+ const message = error instanceof Error ? error.message : "Unknown error";
37831
+ throw new Error(`Assistant Pro skill installation failed: ${message}`);
37832
+ }
37833
+ const manifest = await import_fs_extra15.default.readJson(manifestPath);
37834
+ return {
37835
+ version: manifest.version ?? "unknown",
37836
+ skillCount: manifest.bundles?.all?.length ?? 0
37837
+ };
37838
+ }
37839
+ function countLeadingSpaces(line) {
37840
+ return line.length - line.trimStart().length;
37841
+ }
37842
+ function isYamlContentLine(line) {
37843
+ const trimmed = line.trim();
37844
+ return trimmed.length > 0 && !trimmed.startsWith("#");
37845
+ }
37846
+ async function ensureHermesExternalSkillsDir(hermesDir, agentsSkillsDir) {
37847
+ const configPath = path19.join(hermesDir, "config.yaml");
37848
+ const resolvedSkillsDir = path19.resolve(agentsSkillsDir);
37849
+ const defaultSkillsDir = path19.join(os17.homedir(), ".agents", "skills");
37850
+ const configuredPath = resolvedSkillsDir === defaultSkillsDir ? "~/.agents/skills" : resolvedSkillsDir;
37851
+ const yamlEntry = ` - ${JSON.stringify(configuredPath)}`;
37852
+ await import_fs_extra15.default.ensureDir(hermesDir);
37853
+ if (!await import_fs_extra15.default.pathExists(configPath)) {
37854
+ await import_fs_extra15.default.writeFile(configPath, `skills:
37855
+ external_dirs:
37856
+ ${yamlEntry}
37857
+ `, "utf-8");
37858
+ return true;
37859
+ }
37860
+ const original = await import_fs_extra15.default.readFile(configPath, "utf-8");
37861
+ const lines = original.split(/\r?\n/);
37862
+ let skillsIndex = lines.findIndex((line) => /^skills:\s*(?:#.*)?$/.test(line));
37863
+ if (skillsIndex === -1) {
37864
+ const inlineSkillsIndex = lines.findIndex((line) => /^skills:\s*\S+/.test(line));
37865
+ if (inlineSkillsIndex !== -1) {
37866
+ const inlineValue = lines[inlineSkillsIndex].replace(/^skills:\s*/, "").replace(/\s+#.*$/, "").trim();
37867
+ if (inlineValue === "{}" || inlineValue === "null" || inlineValue === "~") {
37868
+ lines[inlineSkillsIndex] = "skills:";
37869
+ skillsIndex = inlineSkillsIndex;
37870
+ } else {
37871
+ throw new Error(`Hermes skills uses an inline value in ${configPath}; add ${configuredPath} manually`);
37872
+ }
37873
+ }
37874
+ }
37875
+ if (skillsIndex === -1) {
37876
+ const separator = original.length > 0 && !original.endsWith(`
37877
+ `) ? `
37878
+ ` : "";
37879
+ await import_fs_extra15.default.writeFile(configPath, `${original}${separator}skills:
37880
+ external_dirs:
37881
+ ${yamlEntry}
37882
+ `, "utf-8");
37883
+ return true;
37884
+ }
37885
+ let skillsEnd = lines.length;
37886
+ for (let index = skillsIndex + 1;index < lines.length; index += 1) {
37887
+ if (isYamlContentLine(lines[index]) && countLeadingSpaces(lines[index]) === 0) {
37888
+ skillsEnd = index;
37889
+ break;
37890
+ }
37891
+ }
37892
+ const externalIndex = lines.findIndex((line, index) => {
37893
+ return index > skillsIndex && index < skillsEnd && /^\s+external_dirs:\s*/.test(line);
37894
+ });
37895
+ if (externalIndex === -1) {
37896
+ lines.splice(skillsIndex + 1, 0, " external_dirs:", yamlEntry);
37897
+ } else {
37898
+ const match = lines[externalIndex].match(/^(\s+)external_dirs:\s*(.*)$/);
37899
+ let inlineValue = match?.[2]?.replace(/\s+#.*$/, "").trim() ?? "";
37900
+ if (inlineValue === "[]") {
37901
+ lines[externalIndex] = `${match?.[1] ?? " "}external_dirs:`;
37902
+ inlineValue = "";
37903
+ }
37904
+ if (inlineValue) {
37905
+ if (inlineValue.includes(configuredPath) || inlineValue.includes(resolvedSkillsDir)) {
37906
+ return false;
37907
+ }
37908
+ throw new Error(`Hermes external_dirs uses an inline value in ${configPath}; add ${configuredPath} manually`);
37909
+ }
37910
+ const externalIndent = match?.[1].length ?? 2;
37911
+ let externalEnd = skillsEnd;
37912
+ for (let index = externalIndex + 1;index < skillsEnd; index += 1) {
37913
+ if (isYamlContentLine(lines[index]) && countLeadingSpaces(lines[index]) <= externalIndent) {
37914
+ externalEnd = index;
37915
+ break;
37916
+ }
37917
+ }
37918
+ const existingValues = lines.slice(externalIndex + 1, externalEnd).map((line) => line.trim().replace(/^-\s*/, "").replace(/^['"]|['"]$/g, ""));
37919
+ if (existingValues.includes(configuredPath) || existingValues.includes(resolvedSkillsDir)) {
37920
+ return false;
37921
+ }
37922
+ const listIndent = " ".repeat(externalIndent + 2);
37923
+ lines.splice(externalEnd, 0, `${listIndent}- ${JSON.stringify(configuredPath)}`);
37924
+ }
37925
+ await import_fs_extra15.default.writeFile(configPath, `${lines.join(`
37926
+ `).replace(/\n+$/, "")}
37927
+ `, "utf-8");
37928
+ return true;
37929
+ }
37930
+ async function configureAssistantProConsumers(options) {
37931
+ await syncCategorySymlinks("skills", options.agentsDir, options.claudeDir, undefined, true);
37932
+ await syncCategorySymlinks("skills", options.agentsDir, options.codexDir, undefined, true);
37933
+ await ensureHermesExternalSkillsDir(options.hermesDir, path19.join(options.agentsDir, "skills"));
37934
+ }
37774
37935
 
37775
37936
  // src/lib/token-storage.ts
37776
37937
  var import_fs_extra16 = __toESM(require_lib4(), 1);
@@ -37789,6 +37950,9 @@ function getConfigDir() {
37789
37950
  function getTokenFilePath2() {
37790
37951
  return path20.join(getConfigDir(), "token.txt");
37791
37952
  }
37953
+ function getAssistantProTokenFilePath() {
37954
+ return path20.join(getConfigDir(), "assistant-pro-token.txt");
37955
+ }
37792
37956
  async function saveToken(githubToken) {
37793
37957
  const tokenFile = getTokenFilePath2();
37794
37958
  const configDir = path20.dirname(tokenFile);
@@ -37803,6 +37967,11 @@ async function saveToken(githubToken) {
37803
37967
  }
37804
37968
  await import_fs_extra16.default.writeFile(tokenFile, githubToken, { mode: 384 });
37805
37969
  }
37970
+ async function saveAssistantProToken(githubToken) {
37971
+ const tokenFile = getAssistantProTokenFilePath();
37972
+ await import_fs_extra16.default.ensureDir(path20.dirname(tokenFile));
37973
+ await import_fs_extra16.default.writeFile(tokenFile, githubToken, { mode: 384 });
37974
+ }
37806
37975
  async function getToken() {
37807
37976
  const tokenFile = getTokenFilePath2();
37808
37977
  if (!await import_fs_extra16.default.pathExists(tokenFile)) {
@@ -37815,17 +37984,36 @@ async function getToken() {
37815
37984
  return null;
37816
37985
  }
37817
37986
  }
37987
+ async function getAssistantProToken() {
37988
+ const tokenFile = getAssistantProTokenFilePath();
37989
+ if (!await import_fs_extra16.default.pathExists(tokenFile)) {
37990
+ return null;
37991
+ }
37992
+ try {
37993
+ const token = await import_fs_extra16.default.readFile(tokenFile, "utf-8");
37994
+ return token.trim();
37995
+ } catch {
37996
+ return null;
37997
+ }
37998
+ }
37818
37999
  function getTokenInfo() {
37819
38000
  return {
37820
38001
  path: getTokenFilePath2(),
37821
38002
  platform: os18.platform()
37822
38003
  };
37823
38004
  }
38005
+ function getAssistantProTokenInfo() {
38006
+ return {
38007
+ path: getAssistantProTokenFilePath(),
38008
+ platform: os18.platform()
38009
+ };
38010
+ }
37824
38011
 
37825
38012
  // src/commands/pro.ts
37826
38013
  var import_fs_extra17 = __toESM(require_lib4(), 1);
37827
38014
  var API_URL = "https://codeline.app/api/products";
37828
38015
  var PRODUCT_IDS = ["prd_XJVgxVPbGG", "prd_NKabAkdOkw"];
38016
+ var ASSISTANT_PRO_PRODUCT_ID = "prd_t2GRwX3aH1";
37829
38017
 
37830
38018
  class PremiumActivationError extends Error {
37831
38019
  code;
@@ -37844,9 +38032,9 @@ function logPremiumActivationError(error) {
37844
38032
  M2.info("\uD83D\uDC8E Get AIBlueprint CLI Premium at: https://mlv.sh/claude-cli");
37845
38033
  }
37846
38034
  }
37847
- async function promptForPremiumToken() {
38035
+ async function promptForPremiumToken(message = "Enter your Premium access token:", cancelMessage = "Premium activation cancelled") {
37848
38036
  const result = await he({
37849
- message: "Enter your Premium access token:",
38037
+ message,
37850
38038
  placeholder: "Your ProductsOnUsers ID from codeline.app",
37851
38039
  validate: (value) => {
37852
38040
  if (!value)
@@ -37857,14 +38045,14 @@ async function promptForPremiumToken() {
37857
38045
  }
37858
38046
  });
37859
38047
  if (pD(result)) {
37860
- xe("Premium activation cancelled");
38048
+ xe(cancelMessage);
37861
38049
  process.exit(0);
37862
38050
  }
37863
38051
  return result;
37864
38052
  }
37865
- async function fetchPremiumActivationData(userToken) {
38053
+ async function fetchPremiumActivationData(userToken, productIds = PRODUCT_IDS) {
37866
38054
  const encodedToken = encodeURIComponent(userToken);
37867
- for (const productId of PRODUCT_IDS) {
38055
+ for (const productId of productIds) {
37868
38056
  const response = await fetch(`${API_URL}/${productId}/have-access?token=${encodedToken}`);
37869
38057
  if (response.ok) {
37870
38058
  const responseData = await response.json();
@@ -37875,14 +38063,14 @@ async function fetchPremiumActivationData(userToken) {
37875
38063
  }
37876
38064
  return null;
37877
38065
  }
37878
- async function activatePremiumToken(userToken) {
37879
- const premiumToken = userToken ?? await promptForPremiumToken();
38066
+ async function activatePremiumToken(userToken, options = {}) {
38067
+ const premiumToken = userToken ?? await promptForPremiumToken(options.promptMessage, options.cancelMessage);
37880
38068
  const spinner = Y2();
37881
- spinner.start("Validating token against premium products...");
37882
- const data = await fetchPremiumActivationData(premiumToken);
38069
+ spinner.start(options.validationMessage ?? "Validating token against premium products...");
38070
+ const data = await fetchPremiumActivationData(premiumToken, options.productIds);
37883
38071
  if (!data) {
37884
38072
  spinner.stop("Token validation failed");
37885
- throw new PremiumActivationError("invalid-token", "Invalid token or no access to premium products");
38073
+ throw new PremiumActivationError("invalid-token", options.invalidMessage ?? "Invalid token or no access to premium products");
37886
38074
  }
37887
38075
  spinner.stop("Token validated");
37888
38076
  const githubToken = data.product?.metadata?.["cli-github-token"];
@@ -37890,7 +38078,7 @@ async function activatePremiumToken(userToken) {
37890
38078
  throw new PremiumActivationError("missing-github-token", "No GitHub token found in product metadata. Please contact support.");
37891
38079
  }
37892
38080
  spinner.start("Saving token...");
37893
- await saveToken(githubToken);
38081
+ await (options.saveGithubToken ?? saveToken)(githubToken);
37894
38082
  spinner.stop("Token saved");
37895
38083
  return { githubToken, data };
37896
38084
  }
@@ -38043,6 +38231,65 @@ async function proSetupCommand(options = {}) {
38043
38231
  process.exit(1);
38044
38232
  }
38045
38233
  }
38234
+ async function assistantProSetupCommand(options = {}) {
38235
+ Ie(source_default.blue(`\uD83E\uDD16 Setup Assistant Pro ${source_default.gray(`v${getVersion()}`)}`));
38236
+ try {
38237
+ let githubToken = await getAssistantProToken();
38238
+ if (!githubToken) {
38239
+ M2.info("Enter your Assistant Pro access key to activate and continue setup.");
38240
+ const activation = await activatePremiumToken(undefined, {
38241
+ productIds: [ASSISTANT_PRO_PRODUCT_ID],
38242
+ promptMessage: "Enter your Assistant Pro access key:",
38243
+ validationMessage: "Validating Assistant Pro access key...",
38244
+ invalidMessage: "Invalid key or no access to AssistantPro",
38245
+ cancelMessage: "Assistant Pro setup cancelled",
38246
+ saveGithubToken: saveAssistantProToken
38247
+ });
38248
+ githubToken = activation.githubToken;
38249
+ M2.success("✅ Assistant Pro key activated. Continuing setup...");
38250
+ }
38251
+ const { rootDir, claudeDir, codexDir, agentsDir } = resolveFolders(options);
38252
+ const hermesDir = options.hermesFolder ? path21.resolve(options.hermesFolder) : path21.join(rootDir, ".hermes");
38253
+ const spinner = Y2();
38254
+ spinner.start("Installing the latest Assistant Pro skills...");
38255
+ const result = await installAssistantProSkills({
38256
+ githubToken,
38257
+ rootDir
38258
+ });
38259
+ spinner.stop(`Assistant Pro ${result.version} installed`);
38260
+ spinner.start("Configuring Claude Code, Codex, Hermes, and OpenClaw...");
38261
+ await configureAssistantProConsumers({
38262
+ agentsDir,
38263
+ claudeDir,
38264
+ codexDir,
38265
+ hermesDir
38266
+ });
38267
+ spinner.stop("Assistant integrations configured");
38268
+ trackEvent("assistant-pro-setup", {
38269
+ skills: result.skillCount,
38270
+ version: result.version
38271
+ });
38272
+ M2.success("✅ Assistant Pro setup complete!");
38273
+ M2.info(` • ${result.skillCount} skills from assistant-pro-skills ${result.version}`);
38274
+ M2.info(` • Codex source: ${path21.join(agentsDir, "skills")}`);
38275
+ M2.info(` • Claude Code symlinks: ${path21.join(claudeDir, "skills")}`);
38276
+ M2.info(` • Hermes external skills: ${path21.join(hermesDir, "config.yaml")}`);
38277
+ M2.info(" • OpenClaw: native ~/.agents/skills discovery");
38278
+ M2.info(` • Access key saved to: ${getAssistantProTokenInfo().path}`);
38279
+ Se(source_default.green("\uD83D\uDE80 Assistant Pro is ready! Start a new assistant session."));
38280
+ } catch (error) {
38281
+ trackError(error, { command: "assistant-pro-setup" });
38282
+ await flushTelemetry();
38283
+ if (isPremiumActivationError(error)) {
38284
+ M2.error(error.message);
38285
+ M2.info("Get Assistant Pro at: https://codeline.app");
38286
+ } else if (error instanceof Error) {
38287
+ M2.error(error.message);
38288
+ }
38289
+ Se(source_default.red("❌ Assistant Pro setup failed"));
38290
+ process.exit(1);
38291
+ }
38292
+ }
38046
38293
  async function proUpdateCommand(options = {}) {
38047
38294
  Ie(source_default.blue(`\uD83D\uDD04 Update Premium Configs ${source_default.gray(`v${getVersion()}`)}`));
38048
38295
  try {
@@ -39631,6 +39878,11 @@ addConfigFolderOptions(configsBackupsCmd.command("clean").description("Delete ol
39631
39878
  includeManual: options.includeManual
39632
39879
  });
39633
39880
  });
39881
+ var assistantsCmd = program2.command("assistants").description("Configure skills shared by Claude Code, Codex, Hermes, and OpenClaw");
39882
+ var assistantsProCmd = assistantsCmd.command("pro").description("Manage Assistant Pro skills");
39883
+ assistantsProCmd.command("setup").description("Install the latest Assistant Pro skills and configure supported assistants").action(() => {
39884
+ return assistantProSetupCommand();
39885
+ });
39634
39886
  var openclawCmd = program2.command("openclaw").description("OpenClaw configuration commands").option("-f, --folder <path>", "Specify custom OpenClaw folder path (default: ~/.openclaw)");
39635
39887
  var openclawProCmd = openclawCmd.command("pro").description("Manage OpenClaw Pro features");
39636
39888
  openclawProCmd.command("activate [token]").description("Activate OpenClaw Pro with your access token").action((token) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiblueprint-cli",
3
- "version": "1.4.97",
3
+ "version": "1.4.99",
4
4
  "description": "AIBlueprint CLI for setting up AI coding configurations",
5
5
  "author": "AIBlueprint",
6
6
  "license": "MIT",