@mrpatronz/nexusflow 0.1.6 → 0.1.7

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
@@ -18,6 +18,7 @@ NexusFlow combines multiple Git repositories into a single feature workspace and
18
18
 
19
19
  - **Multi-repo workspaces** — group any set of local Git repos under one feature branch using worktrees
20
20
  - **AI context generation** — automatically writes `CLAUDE.md`, `AGENTS.md`, `.github/copilot-instructions.md`, and `.cursor/rules/nexusflow.mdc`
21
+ - **Codebase context packing** — compress an entire multi-repo workspace into a single token-efficient XML file for web-based LLMs using Repomix
21
22
  - **Smart codebase analysis** — detects tech stacks, ports, API endpoints, dependencies, and existing AI configs across all projects
22
23
  - **Session history & resumption** — browse past conversation transcripts from Antigravity, Claude Code, OpenAI Codex, and GitHub Copilot, then resume where you left off
23
24
  - **Service orchestration** — start, stop, and tail logs for all services in a workspace with a single command
@@ -108,6 +109,7 @@ Open this folder in your editor → your AI assistant picks up the context → i
108
109
  | `nexusflow list` | List all existing workspaces (alias: `ls`) |
109
110
  | `nexusflow open` | Re-open a workspace in your editor |
110
111
  | `nexusflow init` | Configure NexusFlow settings |
112
+ | `nexusflow pack` | Pack the workspace codebase into a single token-efficient XML file |
111
113
  | `nexusflow start` | Start all services in a workspace (auto-detected) |
112
114
  | `nexusflow stop` | Stop all running services |
113
115
  | `nexusflow status` | Show running/stopped status and PIDs |
@@ -1 +1 @@
1
- {"version":3,"file":"packer.d.ts","sourceRoot":"","sources":["../../src/core/packer.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,OAAO,CAAC,UAAU,CAAC,CAwFrB"}
1
+ {"version":3,"file":"packer.d.ts","sourceRoot":"","sources":["../../src/core/packer.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAsB,aAAa,CACjC,aAAa,EAAE,MAAM,EACrB,OAAO,GAAE;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAO,GACnC,OAAO,CAAC,UAAU,CAAC,CAsFrB"}
@@ -1,6 +1,8 @@
1
1
  import * as fs from 'node:fs/promises';
2
+ import { createReadStream, createWriteStream } from 'node:fs';
3
+ import { pipeline } from 'node:stream/promises';
2
4
  import * as path from 'node:path';
3
- import { execa } from 'execa';
5
+ import { runCli } from 'repomix';
4
6
  import { loadFeatureConfig } from './workspace.js';
5
7
  /**
6
8
  * Packs all repositories in a workspace into a single, compressed XML file using Repomix.
@@ -11,7 +13,13 @@ export async function packWorkspace(workspacePath, options = {}) {
11
13
  throw new Error(`Workspace not found at ${workspacePath}`);
12
14
  }
13
15
  const compress = options.compress !== false; // default true
14
- const reposXmlData = [];
16
+ const outputPath = path.join(workspacePath, 'nexusflow-context.xml');
17
+ // Use a write stream to avoid buffering huge workspaces in memory
18
+ const outStream = createWriteStream(outputPath, { encoding: 'utf-8' });
19
+ outStream.write('<?xml version="1.0" encoding="UTF-8"?>\n');
20
+ outStream.write(`<workspace id="${feature.id}">\n`);
21
+ outStream.write(` <description><![CDATA[${feature.description}]]></description>\n`);
22
+ outStream.write(' <repositories>\n');
15
23
  let totalFilesCount = 0;
16
24
  let totalCharsCount = 0;
17
25
  for (const repoPath of feature.repos) {
@@ -24,24 +32,22 @@ export async function packWorkspace(workspacePath, options = {}) {
24
32
  continue;
25
33
  }
26
34
  const tempXmlPath = path.join(workspacePath, `temp-repomix-${repoName}.xml`);
27
- // Build repomix arguments
28
- const args = ['repomix', '--style', 'xml', '--output', tempXmlPath];
29
- if (compress) {
30
- args.push('--compress');
31
- }
32
35
  try {
33
- // Run repomix inside the worktree directory
34
- await execa('npx', args, { cwd: worktreePath });
35
- // Read output XML
36
- const xmlContent = await fs.readFile(tempXmlPath, 'utf8');
37
- // Estimate file and character counts
38
- const fileMatches = xmlContent.match(/<file\s+path=/gi) || [];
39
- totalFilesCount += fileMatches.length;
40
- totalCharsCount += xmlContent.length;
41
- reposXmlData.push({
42
- repoName,
43
- xmlContent,
36
+ // Run repomix programmatically inside the worktree directory
37
+ const result = await runCli(['.'], worktreePath, {
38
+ style: 'xml',
39
+ output: tempXmlPath,
40
+ compress,
41
+ quiet: true,
44
42
  });
43
+ if (result && result.packResult) {
44
+ totalFilesCount += result.packResult.totalFiles;
45
+ totalCharsCount += result.packResult.totalCharacters;
46
+ }
47
+ outStream.write(` <repository name="${repoName}">\n`);
48
+ // Stream output XML directly to avoid memory limits
49
+ await pipeline(createReadStream(tempXmlPath, { encoding: 'utf-8' }), outStream, { end: false });
50
+ outStream.write('\n </repository>\n');
45
51
  }
46
52
  catch (error) {
47
53
  console.error(`Error packing repository ${repoName}:`, error.message);
@@ -56,23 +62,14 @@ export async function packWorkspace(workspacePath, options = {}) {
56
62
  }
57
63
  }
58
64
  }
59
- // Combine reposXmlData into a single XML structure
60
- const xmlLines = [];
61
- xmlLines.push('<?xml version="1.0" encoding="UTF-8"?>');
62
- xmlLines.push(`<workspace id="${feature.id}">`);
63
- xmlLines.push(` <description><![CDATA[${feature.description}]]></description>`);
64
- xmlLines.push(' <repositories>');
65
- for (const repo of reposXmlData) {
66
- xmlLines.push(` <repository name="${repo.repoName}">`);
67
- xmlLines.push(repo.xmlContent);
68
- xmlLines.push(' </repository>');
69
- }
70
- xmlLines.push(' </repositories>');
71
- xmlLines.push('</workspace>');
72
- xmlLines.push('');
73
- const outputXmlContent = xmlLines.join('\n');
74
- const outputPath = path.join(workspacePath, 'nexusflow-context.xml');
75
- await fs.writeFile(outputPath, outputXmlContent, 'utf-8');
65
+ outStream.write(' </repositories>\n');
66
+ outStream.write('</workspace>\n');
67
+ outStream.end();
68
+ // Wait for stream to finish writing
69
+ await new Promise((resolve, reject) => {
70
+ outStream.on('finish', resolve);
71
+ outStream.on('error', reject);
72
+ });
76
73
  const stats = await fs.stat(outputPath);
77
74
  return {
78
75
  outputPath,
@@ -1 +1 @@
1
- {"version":3,"file":"packer.js","sourceRoot":"","sources":["../../src/core/packer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"packer.js","sourceRoot":"","sources":["../../src/core/packer.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrpatronz/nexusflow",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Combine multiple repos into a workspace with rich AI assistant context",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -1,6 +1,8 @@
1
1
  import * as fs from 'node:fs/promises';
2
+ import { createReadStream, createWriteStream } from 'node:fs';
3
+ import { pipeline } from 'node:stream/promises';
2
4
  import * as path from 'node:path';
3
- import { execa } from 'execa';
5
+ import { runCli } from 'repomix';
4
6
  import { loadFeatureConfig } from './workspace.js';
5
7
 
6
8
  export interface PackResult {
@@ -23,8 +25,15 @@ export async function packWorkspace(
23
25
  }
24
26
 
25
27
  const compress = options.compress !== false; // default true
28
+ const outputPath = path.join(workspacePath, 'nexusflow-context.xml');
29
+
30
+ // Use a write stream to avoid buffering huge workspaces in memory
31
+ const outStream = createWriteStream(outputPath, { encoding: 'utf-8' });
26
32
 
27
- const reposXmlData: { repoName: string; xmlContent: string }[] = [];
33
+ outStream.write('<?xml version="1.0" encoding="UTF-8"?>\n');
34
+ outStream.write(`<workspace id="${feature.id}">\n`);
35
+ outStream.write(` <description><![CDATA[${feature.description}]]></description>\n`);
36
+ outStream.write(' <repositories>\n');
28
37
 
29
38
  let totalFilesCount = 0;
30
39
  let totalCharsCount = 0;
@@ -41,28 +50,30 @@ export async function packWorkspace(
41
50
 
42
51
  const tempXmlPath = path.join(workspacePath, `temp-repomix-${repoName}.xml`);
43
52
 
44
- // Build repomix arguments
45
- const args = ['repomix', '--style', 'xml', '--output', tempXmlPath];
46
- if (compress) {
47
- args.push('--compress');
48
- }
49
-
50
53
  try {
51
- // Run repomix inside the worktree directory
52
- await execa('npx', args, { cwd: worktreePath });
53
-
54
- // Read output XML
55
- const xmlContent = await fs.readFile(tempXmlPath, 'utf8');
54
+ // Run repomix programmatically inside the worktree directory
55
+ const result = await runCli(['.'], worktreePath, {
56
+ style: 'xml',
57
+ output: tempXmlPath,
58
+ compress,
59
+ quiet: true,
60
+ });
56
61
 
57
- // Estimate file and character counts
58
- const fileMatches = xmlContent.match(/<file\s+path=/gi) || [];
59
- totalFilesCount += fileMatches.length;
60
- totalCharsCount += xmlContent.length;
62
+ if (result && result.packResult) {
63
+ totalFilesCount += result.packResult.totalFiles;
64
+ totalCharsCount += result.packResult.totalCharacters;
65
+ }
61
66
 
62
- reposXmlData.push({
63
- repoName,
64
- xmlContent,
65
- });
67
+ outStream.write(` <repository name="${repoName}">\n`);
68
+
69
+ // Stream output XML directly to avoid memory limits
70
+ await pipeline(
71
+ createReadStream(tempXmlPath, { encoding: 'utf-8' }),
72
+ outStream,
73
+ { end: false }
74
+ );
75
+
76
+ outStream.write('\n </repository>\n');
66
77
  } catch (error: any) {
67
78
  console.error(`Error packing repository ${repoName}:`, error.message);
68
79
  } finally {
@@ -75,26 +86,15 @@ export async function packWorkspace(
75
86
  }
76
87
  }
77
88
 
78
- // Combine reposXmlData into a single XML structure
79
- const xmlLines: string[] = [];
80
- xmlLines.push('<?xml version="1.0" encoding="UTF-8"?>');
81
- xmlLines.push(`<workspace id="${feature.id}">`);
82
- xmlLines.push(` <description><![CDATA[${feature.description}]]></description>`);
83
- xmlLines.push(' <repositories>');
84
-
85
- for (const repo of reposXmlData) {
86
- xmlLines.push(` <repository name="${repo.repoName}">`);
87
- xmlLines.push(repo.xmlContent);
88
- xmlLines.push(' </repository>');
89
- }
90
-
91
- xmlLines.push(' </repositories>');
92
- xmlLines.push('</workspace>');
93
- xmlLines.push('');
89
+ outStream.write(' </repositories>\n');
90
+ outStream.write('</workspace>\n');
91
+ outStream.end();
94
92
 
95
- const outputXmlContent = xmlLines.join('\n');
96
- const outputPath = path.join(workspacePath, 'nexusflow-context.xml');
97
- await fs.writeFile(outputPath, outputXmlContent, 'utf-8');
93
+ // Wait for stream to finish writing
94
+ await new Promise<void>((resolve, reject) => {
95
+ outStream.on('finish', resolve);
96
+ outStream.on('error', reject);
97
+ });
98
98
 
99
99
  const stats = await fs.stat(outputPath);
100
100
 
@@ -105,3 +105,4 @@ export async function packWorkspace(
105
105
  fileSize: stats.size,
106
106
  };
107
107
  }
108
+