@ghl-ai/aw 0.1.70-beta.3 → 0.1.70-beta.5

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
@@ -35,7 +35,7 @@ import { loadConfig as ensureTelemetryConfig } from '../telemetry.mjs';
35
35
  import { installAwEcc, AW_ECC_TAG } from '../ecc.mjs';
36
36
  import { removeWorkspaceHookDefaults } from '../codex.mjs';
37
37
  import { readHookManifest, pruneStaleHooks, writeHookManifest } from '../hook-cleanup.mjs';
38
- import { installIntegration, autoInstallIntegrations } from '../integrations.mjs';
38
+ import { installIntegration, autoInstallIntegrations, getSuggestedIntegrationStatuses } from '../integrations.mjs';
39
39
  import {
40
40
  initPersistentClone,
41
41
  isValidClone,
@@ -77,6 +77,30 @@ function writeHookManifestBestEffort(manifest, context) {
77
77
  }
78
78
  }
79
79
 
80
+ function formatIntegrationStatusSummary(statuses, installedNow = []) {
81
+ if (!statuses || statuses.length === 0) return null;
82
+
83
+ const installedNowSet = new Set(installedNow);
84
+ const lines = statuses.map((entry) => {
85
+ if (entry.status === 'installed') {
86
+ const note = installedNowSet.has(entry.label) ? '(installed now)' : '(installed)';
87
+ return ` ${chalk.green('✓')} ${entry.label} ${chalk.dim(note)}`;
88
+ }
89
+
90
+ if (entry.status === 'skipped') {
91
+ const note = entry.reason ? `(skipped: ${entry.reason})` : '(skipped)';
92
+ return ` ${chalk.yellow('!')} ${entry.label} ${chalk.dim(note)}`;
93
+ }
94
+
95
+ return ` ${chalk.dim('○')} ${entry.label} ${chalk.dim('(not installed)')}`;
96
+ });
97
+
98
+ return [
99
+ ` ${chalk.green('✓')} Integrations:`,
100
+ ...lines,
101
+ ].join('\n');
102
+ }
103
+
80
104
  export async function syncEccAfterAwUpdate(updateResult, cwd, { silent = false } = {}) {
81
105
  if (updateResult?.status !== 'upgraded' || !updateResult.packageRoot) {
82
106
  return { synced: false, reason: updateResult?.reason || updateResult?.status || 'not-upgraded' };
@@ -487,8 +511,10 @@ export async function initCommand(args) {
487
511
 
488
512
  // Auto-install suggested integrations (Codex, Caveman, Graphify, etc) - unless --no-integrations
489
513
  let installedIntegrations = [];
514
+ let integrationStatuses = [];
490
515
  if (!silent && !skipIntegrations && !isNewSubTeam) {
491
516
  installedIntegrations = await autoInstallIntegrations(effectiveNamespace, { silent });
517
+ integrationStatuses = getSuggestedIntegrationStatuses(effectiveNamespace, { home: HOME });
492
518
  }
493
519
 
494
520
  if (silent) {
@@ -511,7 +537,7 @@ export async function initCommand(args) {
511
537
  ? ` ${chalk.green('✓')} Removed ${removedLegacyStartupFiles.length} legacy repo startup file${removedLegacyStartupFiles.length > 1 ? 's' : ''}`
512
538
  : null,
513
539
  cwd !== HOME && isWorktree(join(cwd, '.aw')) ? ` ${chalk.green('✓')} Project linked` : null,
514
- installedIntegrations.length > 0 ? ` ${chalk.green('✓')} Integrations: ${installedIntegrations.join(', ')}` : null,
540
+ formatIntegrationStatusSummary(integrationStatuses, installedIntegrations),
515
541
  ].filter(Boolean).join('\n'));
516
542
  }
517
543
  return;
@@ -680,8 +706,10 @@ export async function initCommand(args) {
680
706
 
681
707
  // Auto-install suggested integrations (Codex, Caveman, Graphify, etc) - unless --no-integrations
682
708
  let installedIntegrations = [];
709
+ let integrationStatuses = [];
683
710
  if (!silent && !skipIntegrations) {
684
711
  installedIntegrations = await autoInstallIntegrations(activeNamespace(), { silent });
712
+ integrationStatuses = getSuggestedIntegrationStatuses(activeNamespace(), { home: HOME });
685
713
  }
686
714
 
687
715
  // Offer to update if a newer version is available
@@ -704,7 +732,7 @@ export async function initCommand(args) {
704
732
  awUsageHooksReport ? ` ${chalk.green('✓')} ${awUsageHooksReport}` : null,
705
733
  ` ${chalk.green('✓')} IDE task: auto-sync on workspace open`,
706
734
  cwd !== HOME && isWorktree(join(cwd, '.aw')) ? ` ${chalk.green('✓')} Linked in current project` : null,
707
- installedIntegrations.length > 0 ? ` ${chalk.green('✓')} Integrations: ${installedIntegrations.join(', ')}` : null,
735
+ formatIntegrationStatusSummary(integrationStatuses, installedIntegrations),
708
736
  '',
709
737
  ` ${chalk.dim('Existing repos:')} ${chalk.bold('cd <project> && aw link')}`,
710
738
  ` ${chalk.dim('New clones:')} auto-linked via git hook`,
package/integrations.mjs CHANGED
@@ -15,7 +15,7 @@ import {
15
15
  mkdirSync,
16
16
  rmSync,
17
17
  } from 'node:fs';
18
- import { join, basename } from 'node:path';
18
+ import { join, basename, delimiter } from 'node:path';
19
19
  import { homedir } from 'node:os';
20
20
  import * as fmt from './fmt.mjs';
21
21
  import { chalk } from './fmt.mjs';
@@ -36,6 +36,29 @@ function getErrorMessage(error) {
36
36
  return error instanceof Error ? error.message : String(error);
37
37
  }
38
38
 
39
+ function shellQuote(value) {
40
+ return `'${String(value).replaceAll("'", "'\\''")}'`;
41
+ }
42
+
43
+ function installerEnv(home = HOME) {
44
+ const pathEntries = [
45
+ join(home, '.local', 'bin'),
46
+ join(home, '.cargo', 'bin'),
47
+ join(home, 'bin'),
48
+ process.env.PATH || '',
49
+ ].filter(Boolean);
50
+
51
+ return {
52
+ ...process.env,
53
+ HOME: home,
54
+ PATH: pathEntries.join(delimiter),
55
+ };
56
+ }
57
+
58
+ function posixInstallerCommand(url, runner = 'bash') {
59
+ return `bash -o pipefail -c ${shellQuote(`curl -fsSL ${shellQuote(url)} | ${runner}`)}`;
60
+ }
61
+
39
62
  // ────────────────────────────────────────────────────────────────────────────────
40
63
  // INTEGRATION REGISTRY
41
64
  // ────────────────────────────────────────────────────────────────────────────────
@@ -76,7 +99,7 @@ export const INTEGRATIONS = {
76
99
  description: 'CLI proxy that filters/compresses shell output (git, tests, logs) by 60-90%',
77
100
  scripts: {
78
101
  win32: null, // use WSL fallback
79
- posix: 'https://raw.githubusercontent.com/rtk-ai/rtk/main/install.sh',
102
+ posix: 'https://raw.githubusercontent.com/rtk-ai/rtk/refs/heads/master/install.sh',
80
103
  },
81
104
  postInstall: [
82
105
  'rtk init -g', // Claude Code
@@ -110,11 +133,11 @@ export const INTEGRATIONS = {
110
133
  posix: null, // no binary — installed entirely via npx below
111
134
  },
112
135
  postInstall: [
113
- 'npx skills@latest add mattpocock/skills',
136
+ 'npx skills@latest add mattpocock/skills --global --all',
114
137
  ],
115
138
  teams: [],
116
139
  requiresAuth: false,
117
- authNote: 'Interactive install pick which skills + agents you want. Then run /setup-matt-pocock-skills once per repo.',
140
+ authNote: 'Installs all bundled skills and agents globally. Then run /setup-matt-pocock-skills once per repo.',
118
141
  },
119
142
 
120
143
  // PYTHON CLIs (installed via uv / pipx / pip, then runs post-install hooks)
@@ -601,6 +624,7 @@ async function runClaudePlugin(installCmd, { silent = false, marketplaceSource =
601
624
 
602
625
  async function runUniversalInstaller(integration, key, { silent = false, home = HOME } = {}) {
603
626
  const spinner = silent ? null : fmt.spinner();
627
+ const env = installerEnv(home);
604
628
 
605
629
  if (!silent) spinner.start(`Installing ${integration.label} for all detected IDEs...`);
606
630
 
@@ -633,7 +657,7 @@ async function runUniversalInstaller(integration, key, { silent = false, home =
633
657
  }
634
658
 
635
659
  if (wslOk) {
636
- cmd = `wsl -- bash -c "curl -fsSL '${integration.scripts.posix}' | sh"`;
660
+ cmd = `wsl -- ${posixInstallerCommand(integration.scripts.posix, 'sh')}`;
637
661
  } else if (integration.npmPackage) {
638
662
  if (!silent) fmt.logWarn('WSL/bash not available — installing via npm instead');
639
663
  cmd = `npm install -g ${integration.npmPackage}`;
@@ -651,13 +675,14 @@ async function runUniversalInstaller(integration, key, { silent = false, home =
651
675
  }
652
676
  }
653
677
  } else {
654
- cmd = `curl -fsSL '${integration.scripts.posix}' | bash`;
678
+ cmd = posixInstallerCommand(integration.scripts.posix);
655
679
  }
656
680
 
657
681
  if (cmd) {
658
682
  await execAsync(cmd, {
659
683
  timeout: 5 * 60 * 1000,
660
684
  maxBuffer: 20 * 1024 * 1024,
685
+ env,
661
686
  });
662
687
  }
663
688
 
@@ -673,7 +698,11 @@ async function runUniversalInstaller(integration, key, { silent = false, home =
673
698
  }
674
699
 
675
700
  try {
676
- await execAsync(finalPostCmd, { timeout: 60 * 1000, maxBuffer: 10 * 1024 * 1024 });
701
+ await execAsync(finalPostCmd, {
702
+ timeout: 60 * 1000,
703
+ maxBuffer: 10 * 1024 * 1024,
704
+ env,
705
+ });
677
706
  } catch (e) {
678
707
  failedPostInstalls.push(finalPostCmd);
679
708
  if (!silent) fmt.logWarn(`Post-install step failed: ${finalPostCmd} — ${getErrorMessage(e)}`);
@@ -1028,6 +1057,52 @@ export function suggestForTeam(namespace) {
1028
1057
  .map(([key]) => key);
1029
1058
  }
1030
1059
 
1060
+ export function getSuggestedIntegrationStatuses(namespace, options = {}) {
1061
+ const manifest = readManifest(options.home);
1062
+
1063
+ return suggestForTeam(namespace).map((key) => {
1064
+ const integration = INTEGRATIONS[key];
1065
+ const entry = manifest.installed[key];
1066
+
1067
+ if (entry && entry.status !== 'skipped') {
1068
+ return {
1069
+ key,
1070
+ label: integration.label,
1071
+ type: integration.type,
1072
+ status: 'installed',
1073
+ installedAt: entry.installedAt || null,
1074
+ };
1075
+ }
1076
+
1077
+ if (entry?.status === 'skipped') {
1078
+ return {
1079
+ key,
1080
+ label: integration.label,
1081
+ type: integration.type,
1082
+ status: 'skipped',
1083
+ reason: entry.reason || 'previous setup skipped',
1084
+ };
1085
+ }
1086
+
1087
+ if (integration.requiresGitSubmodule && !hasGitSubmoduleSupport()) {
1088
+ return {
1089
+ key,
1090
+ label: integration.label,
1091
+ type: integration.type,
1092
+ status: 'skipped',
1093
+ reason: 'Git submodule support unavailable',
1094
+ };
1095
+ }
1096
+
1097
+ return {
1098
+ key,
1099
+ label: integration.label,
1100
+ type: integration.type,
1101
+ status: 'pending',
1102
+ };
1103
+ });
1104
+ }
1105
+
1031
1106
  // ────────────────────────────────────────────────────────────────────────────────
1032
1107
  // AUTO-INSTALL (called from init.mjs - installs suggested integrations)
1033
1108
  // ────────────────────────────────────────────────────────────────────────────────
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ghl-ai/aw",
3
- "version": "0.1.70-beta.3",
3
+ "version": "0.1.70-beta.5",
4
4
  "description": "Agentic Workspace CLI — pull, push & manage agents, skills and commands from the registry",
5
5
  "type": "module",
6
6
  "bin": {