@axiomatic-labs/claudeflow 2.12.86 → 2.12.87

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/lib/install.js +68 -43
  2. package/package.json +1 -1
package/lib/install.js CHANGED
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const { execSync } = require('child_process');
3
+ const { execSync, execFileSync } = require('child_process');
4
4
  const { requireAuth } = require('./auth.js');
5
5
  const { getLatestRelease, downloadReleaseAsset } = require('./download.js');
6
6
  const { writeLocalVersion, readLocalVersion } = require('./version.js');
@@ -14,6 +14,7 @@ const TEMPLATE_MANAGED_MANIFEST = path.join('.claudeflow', 'config', 'template-m
14
14
  const CLAUDE_BACKUP_ROOT = '.claudeflow-backups';
15
15
  const REQUIRED_TEMPLATE_RULES = ['claudeflow-implementation.md'];
16
16
  const TEMPLATE_MANAGED_SETTINGS_KEYS = ['$schema', 'enabledMcpjsonServers', 'env', 'permissions', 'hooks'];
17
+ const SERENA_REPO = 'git+https://github.com/oraios/serena';
17
18
  const TEMPLATE_SEEDED_SETTINGS_KEYS = new Set(['statusLine']);
18
19
 
19
20
  async function run() {
@@ -457,6 +458,11 @@ function installAnalysisTools() {
457
458
 
458
459
  // 3. Write MCP servers directly to .mcp.json (more reliable than claude mcp add)
459
460
  configureMcpServers(hasUv);
461
+
462
+ // 4. Prime Serena for the current project when possible.
463
+ if (hasUv) {
464
+ indexSerenaProject(process.cwd());
465
+ }
460
466
  }
461
467
 
462
468
  // Write Serena and context7 MCP configs directly to .mcp.json.
@@ -479,41 +485,40 @@ function configureMcpServers(hasUv) {
479
485
 
480
486
  // Serena MCP (requires uv)
481
487
  if (hasUv) {
482
- if (mcpConfig.mcpServers.serena) {
483
- ui.success('Serena MCP already configured');
484
- } else {
485
- ui.step('Adding Serena MCP for semantic code analysis...');
486
- const uvBin = resolveUvBin();
487
- mcpConfig.mcpServers.serena = {
488
- type: 'stdio',
489
- command: 'uvx',
490
- args: [
491
- '--python', '3.13',
492
- '--from', 'git+https://github.com/oraios/serena',
493
- 'serena', 'start-mcp-server',
494
- '--context', 'claude-code',
495
- '--project', cwd,
496
- ],
497
- };
498
- changed = true;
499
- ui.success('Serena MCP configured');
500
- }
501
- }
502
-
503
- // context7 MCP
504
- if (mcpConfig.mcpServers.context7) {
505
- ui.success('context7 MCP already configured');
506
- } else {
507
- ui.step('Adding context7 MCP for library documentation...');
508
- mcpConfig.mcpServers.context7 = {
488
+ const serenaCommand = commandExists('uvx') ? 'uvx' : 'uv';
489
+ const serenaArgs = serenaCommand === 'uvx'
490
+ ? [
491
+ '--from', SERENA_REPO,
492
+ 'serena', 'start-mcp-server',
493
+ '--context', 'claude-code',
494
+ '--project-from-cwd',
495
+ ]
496
+ : [
497
+ 'run', '--with', SERENA_REPO,
498
+ 'serena', 'start-mcp-server',
499
+ '--context', 'claude-code',
500
+ '--project-from-cwd',
501
+ ];
502
+ ui.step(mcpConfig.mcpServers.serena ? 'Refreshing Serena MCP configuration...' : 'Adding Serena MCP for semantic code analysis...');
503
+ mcpConfig.mcpServers.serena = {
509
504
  type: 'stdio',
510
- command: 'npx',
511
- args: ['-y', '@upstash/context7-mcp@latest'],
505
+ command: serenaCommand,
506
+ args: serenaArgs,
512
507
  };
513
508
  changed = true;
514
- ui.success('context7 MCP configured');
509
+ ui.success('Serena MCP configured');
515
510
  }
516
511
 
512
+ // context7 MCP
513
+ ui.step(mcpConfig.mcpServers.context7 ? 'Refreshing context7 MCP configuration...' : 'Adding context7 MCP for library documentation...');
514
+ mcpConfig.mcpServers.context7 = {
515
+ type: 'stdio',
516
+ command: 'npx',
517
+ args: ['-y', '@upstash/context7-mcp@latest'],
518
+ };
519
+ changed = true;
520
+ ui.success('context7 MCP configured');
521
+
517
522
  // Write .mcp.json if anything changed
518
523
  if (changed) {
519
524
  try {
@@ -535,21 +540,41 @@ function commandExists(cmd) {
535
540
  }
536
541
  }
537
542
 
538
- // Resolve uv binary path — may be in PATH or in common install locations
539
- function resolveUvBin() {
540
- if (commandExists('uv')) return 'uv';
541
- const candidates = [
542
- path.join(homedir(), '.local', 'bin', 'uv'),
543
- path.join(homedir(), '.cargo', 'bin', 'uv'),
543
+ function indexSerenaProject(projectRoot) {
544
+ ui.step('Indexing project for Serena...');
545
+ const statusPath = path.join(projectRoot, '.claudeflow', 'tmp', 'tooling', 'serena-status.json');
546
+ const attempts = [
547
+ { command: 'uvx', args: ['--from', SERENA_REPO, 'serena', 'project', 'index', projectRoot] },
548
+ { command: 'uv', args: ['run', '--with', SERENA_REPO, 'serena', 'project', 'index', projectRoot] },
544
549
  ];
545
- for (const p of candidates) {
546
- if (fs.existsSync(p)) return p;
550
+
551
+ let failureReason = 'uv/uvx not available';
552
+ let indexed = false;
553
+ for (const attempt of attempts) {
554
+ if (!commandExists(attempt.command)) continue;
555
+ try {
556
+ execFileSync(attempt.command, attempt.args, { cwd: projectRoot, stdio: 'pipe', timeout: 120000 });
557
+ indexed = true;
558
+ failureReason = null;
559
+ break;
560
+ } catch (error) {
561
+ failureReason = error.stderr ? String(error.stderr).trim() : error.message;
562
+ }
547
563
  }
548
- return 'uv'; // fallback — let it fail with a clear error
549
- }
550
564
 
551
- function homedir() {
552
- return require('os').homedir();
565
+ fs.mkdirSync(path.dirname(statusPath), { recursive: true });
566
+ fs.writeFileSync(statusPath, `${JSON.stringify({
567
+ configured: true,
568
+ indexed,
569
+ last_attempt_at: new Date().toISOString(),
570
+ failure_reason: failureReason,
571
+ }, null, 2)}\n`);
572
+
573
+ if (indexed) {
574
+ ui.success('Serena project index ready');
575
+ } else {
576
+ ui.warn('Serena indexing failed — semantic navigation may need a manual retry');
577
+ }
553
578
  }
554
579
 
555
580
  function createPreInstallBackup(projectRoot, options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axiomatic-labs/claudeflow",
3
- "version": "2.12.86",
3
+ "version": "2.12.87",
4
4
  "description": "Claudeflow — AI-powered development toolkit for Claude Code. Skills, agents, hooks, and quality gates that ship production apps.",
5
5
  "bin": {
6
6
  "claudeflow": "./bin/cli.js"