argustack 0.1.9 → 0.1.11
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 +5 -2
- package/dist/cli/index.js +9 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/init/generators.d.ts +2 -2
- package/dist/cli/init/generators.d.ts.map +1 -1
- package/dist/cli/init/generators.js +14 -12
- package/dist/cli/init/generators.js.map +1 -1
- package/dist/cli/init/index.d.ts +10 -0
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/index.js +205 -72
- package/dist/cli/init/index.js.map +1 -1
- package/dist/cli/init/setup-db.d.ts.map +1 -1
- package/dist/cli/init/setup-db.js +5 -3
- package/dist/cli/init/setup-db.js.map +1 -1
- package/dist/cli/init/setup-git.d.ts.map +1 -1
- package/dist/cli/init/setup-git.js +10 -4
- package/dist/cli/init/setup-git.js.map +1 -1
- package/dist/cli/init/setup-github.js +5 -5
- package/dist/cli/init/setup-github.js.map +1 -1
- package/dist/cli/init/setup-jira.d.ts.map +1 -1
- package/dist/cli/init/setup-jira.js +5 -3
- package/dist/cli/init/setup-jira.js.map +1 -1
- package/dist/cli/init/types.d.ts +9 -1
- package/dist/cli/init/types.d.ts.map +1 -1
- package/dist/cli/init/types.js +54 -0
- package/dist/cli/init/types.js.map +1 -1
- package/dist/cli/sync.d.ts.map +1 -1
- package/dist/cli/sync.js +2 -1
- package/dist/cli/sync.js.map +1 -1
- package/dist/core/types/config.d.ts +2 -0
- package/dist/core/types/config.d.ts.map +1 -1
- package/dist/core/types/config.js.map +1 -1
- package/dist/mcp/helpers.d.ts +18 -1
- package/dist/mcp/helpers.d.ts.map +1 -1
- package/dist/mcp/helpers.js +92 -0
- package/dist/mcp/helpers.js.map +1 -1
- package/dist/mcp/tools/workspace.d.ts.map +1 -1
- package/dist/mcp/tools/workspace.js +35 -2
- package/dist/mcp/tools/workspace.js.map +1 -1
- package/dist/workspace/config.d.ts +1 -1
- package/dist/workspace/config.d.ts.map +1 -1
- package/dist/workspace/config.js +2 -1
- package/dist/workspace/config.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
[](https://www.npmjs.com/package/argustack)
|
|
4
4
|
[](https://www.npmjs.com/package/argustack)
|
|
5
5
|
[](LICENSE)
|
|
6
|
+
[](https://app.paperlink.online/s/0aa7d2d6/argustack)
|
|
6
7
|
|
|
7
8
|
**Ask AI about your Jira, Git, and GitHub — powered by local data, not cloud APIs.**
|
|
8
9
|
|
|
9
|
-
|
|
10
|
+
[**Documentation & Examples →**](https://app.paperlink.online/s/0aa7d2d6/argustack)
|
|
11
|
+
|
|
12
|
+
Argustack downloads your project data into local PostgreSQL, cross-references everything, and gives Claude direct access via 20 MCP tools. All data stays on your machine.
|
|
10
13
|
|
|
11
14
|
> *Was ticket PROJ-123 implemented as described?*
|
|
12
15
|
> *Who reviewed the PR and what was the feedback?*
|
|
@@ -21,7 +24,7 @@ Argustack downloads your project data into local PostgreSQL, cross-references ev
|
|
|
21
24
|
- **Cross-source timeline** — Jira + Git + GitHub events in chronological order
|
|
22
25
|
- **Semantic search** — find issues by meaning, not just keywords (pgvector)
|
|
23
26
|
- **Task estimation** — predict duration per developer based on actual history
|
|
24
|
-
- **
|
|
27
|
+
- **20 MCP tools** — Claude queries your data directly via SQL
|
|
25
28
|
- **100% local** — no cloud, no accounts, no telemetry
|
|
26
29
|
|
|
27
30
|
## Quick Start
|
package/dist/cli/index.js
CHANGED
|
@@ -17,7 +17,7 @@ program
|
|
|
17
17
|
program
|
|
18
18
|
.command('init')
|
|
19
19
|
.description('Create a new Argustack workspace')
|
|
20
|
-
.
|
|
20
|
+
.argument('[name]', 'Workspace name (creates subdirectory)')
|
|
21
21
|
.option('-s, --source <sources>', 'Comma-separated sources: jira,git,github,db')
|
|
22
22
|
.option('--jira-url <url>', 'Jira instance URL')
|
|
23
23
|
.option('--jira-email <email>', 'Jira user email')
|
|
@@ -34,12 +34,16 @@ program
|
|
|
34
34
|
.option('--target-db-password <password>', 'Target DB password')
|
|
35
35
|
.option('--target-db-name <name>', 'Target DB name')
|
|
36
36
|
.option('--csv-file <path>', 'Path to Jira CSV export file')
|
|
37
|
-
.option('--db-port <port>', 'Argustack PostgreSQL port'
|
|
38
|
-
.option('--pgweb-port <port>', 'pgweb UI port'
|
|
37
|
+
.option('--db-port <port>', 'Argustack PostgreSQL port')
|
|
38
|
+
.option('--pgweb-port <port>', 'pgweb UI port')
|
|
39
39
|
.option('--no-interactive', 'Run without prompts (all values from flags)')
|
|
40
|
-
.action(async (options) => {
|
|
40
|
+
.action(async (name, options) => {
|
|
41
41
|
try {
|
|
42
|
-
|
|
42
|
+
const flags = options;
|
|
43
|
+
if (name) {
|
|
44
|
+
flags.name = name;
|
|
45
|
+
}
|
|
46
|
+
await runInit(flags);
|
|
43
47
|
}
|
|
44
48
|
catch (err) {
|
|
45
49
|
if (err instanceof Error && err.name === 'ExitPromptError') {
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG1C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,oBAAoB,CAAwB,CAAC;AAEzE,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,WAAW,CAAC;KACjB,WAAW,CAAC,6CAA6C,CAAC;KAC1D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,kCAAkC,CAAC;KAC/C,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { JiraSetupResult, GitSetupResult, GitHubSetupResult, CsvSetupResult, DbSetupResult } from './types.js';
|
|
2
2
|
export declare function generateEnv(jira: JiraSetupResult | null, git: GitSetupResult | null, github: GitHubSetupResult | null, csv: CsvSetupResult | null, db: DbSetupResult | null, argustackDbPort: number): string;
|
|
3
|
-
export declare function generateDockerCompose(dbPort: number, pgwebPort: number): string;
|
|
4
|
-
export declare function createWorkspaceFiles(workspaceDir: string, jira: JiraSetupResult | null, git: GitSetupResult | null, github: GitHubSetupResult | null, csv: CsvSetupResult | null, db: DbSetupResult | null, dbPort: number, pgwebPort: number): void;
|
|
3
|
+
export declare function generateDockerCompose(dbPort: number, pgwebPort: number, workspaceName?: string): string;
|
|
4
|
+
export declare function createWorkspaceFiles(workspaceDir: string, jira: JiraSetupResult | null, git: GitSetupResult | null, github: GitHubSetupResult | null, csv: CsvSetupResult | null, db: DbSetupResult | null, dbPort: number, pgwebPort: number, workspaceName?: string): void;
|
|
5
5
|
export declare function printSummary(workspaceDir: string, jira: JiraSetupResult | null, git: GitSetupResult | null, github: GitHubSetupResult | null, csv: CsvSetupResult | null, db: DbSetupResult | null, pgwebPort: number, willAutoStart: boolean): void;
|
|
6
6
|
//# sourceMappingURL=generators.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../src/cli/init/generators.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,aAAa,EACd,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"generators.d.ts","sourceRoot":"","sources":["../../../src/cli/init/generators.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,cAAc,EACd,aAAa,EACd,MAAM,YAAY,CAAC;AAapB,wBAAgB,WAAW,CACzB,IAAI,EAAE,eAAe,GAAG,IAAI,EAC5B,GAAG,EAAE,cAAc,GAAG,IAAI,EAC1B,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,GAAG,EAAE,cAAc,GAAG,IAAI,EAC1B,EAAE,EAAE,aAAa,GAAG,IAAI,EACxB,eAAe,EAAE,MAAM,GACtB,MAAM,CAkER;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,MAAM,CAoCvG;AAED,wBAAgB,oBAAoB,CAClC,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,eAAe,GAAG,IAAI,EAC5B,GAAG,EAAE,cAAc,GAAG,IAAI,EAC1B,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,GAAG,EAAE,cAAc,GAAG,IAAI,EAC1B,EAAE,EAAE,aAAa,GAAG,IAAI,EACxB,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,MAAM,EACjB,aAAa,CAAC,EAAE,MAAM,GACrB,IAAI,CAiDN;AAED,wBAAgB,YAAY,CAC1B,YAAY,EAAE,MAAM,EACpB,IAAI,EAAE,eAAe,GAAG,IAAI,EAC5B,GAAG,EAAE,cAAc,GAAG,IAAI,EAC1B,MAAM,EAAE,iBAAiB,GAAG,IAAI,EAChC,GAAG,EAAE,cAAc,GAAG,IAAI,EAC1B,EAAE,EAAE,aAAa,GAAG,IAAI,EACxB,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,OAAO,GACrB,IAAI,CA4CN"}
|
|
@@ -4,6 +4,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
import { createEmptyConfig, addSource, writeConfig } from '../../workspace/config.js';
|
|
6
6
|
import { resolveServerPath } from '../mcp-install.js';
|
|
7
|
+
import { maskHost, maskOrgRepo, maskPath } from './types.js';
|
|
7
8
|
const currentDir = fileURLToPath(new URL('.', import.meta.url));
|
|
8
9
|
function getTemplatesDir() {
|
|
9
10
|
const templatesDir = resolve(currentDir, '..', '..', '..', 'templates');
|
|
@@ -32,11 +33,12 @@ export function generateEnv(jira, git, github, csv, db, argustackDbPort) {
|
|
|
32
33
|
lines.push('# === Argustack internal PostgreSQL (match docker-compose.yml) ===', 'DB_HOST=localhost', `DB_PORT=${argustackDbPort}`, 'DB_USER=argustack', 'DB_PASSWORD=argustack_local', 'DB_NAME=argustack', '', '# === OpenAI embeddings (optional, for semantic search) ===', '# OPENAI_API_KEY=sk-...');
|
|
33
34
|
return lines.join('\n') + '\n';
|
|
34
35
|
}
|
|
35
|
-
export function generateDockerCompose(dbPort, pgwebPort) {
|
|
36
|
+
export function generateDockerCompose(dbPort, pgwebPort, workspaceName) {
|
|
37
|
+
const prefix = workspaceName ? `argustack-${workspaceName}` : 'argustack';
|
|
36
38
|
return `services:
|
|
37
39
|
db:
|
|
38
40
|
image: pgvector/pgvector:pg16
|
|
39
|
-
container_name:
|
|
41
|
+
container_name: ${prefix}-db
|
|
40
42
|
ports:
|
|
41
43
|
- "${dbPort}:5432"
|
|
42
44
|
environment:
|
|
@@ -44,7 +46,7 @@ export function generateDockerCompose(dbPort, pgwebPort) {
|
|
|
44
46
|
POSTGRES_PASSWORD: argustack_local
|
|
45
47
|
POSTGRES_DB: argustack
|
|
46
48
|
volumes:
|
|
47
|
-
-
|
|
49
|
+
- ${prefix}-data:/var/lib/postgresql/data
|
|
48
50
|
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
|
|
49
51
|
healthcheck:
|
|
50
52
|
test: ["CMD-SHELL", "pg_isready -U argustack"]
|
|
@@ -54,7 +56,7 @@ export function generateDockerCompose(dbPort, pgwebPort) {
|
|
|
54
56
|
|
|
55
57
|
pgweb:
|
|
56
58
|
image: sosedoff/pgweb
|
|
57
|
-
container_name:
|
|
59
|
+
container_name: ${prefix}-pgweb
|
|
58
60
|
ports:
|
|
59
61
|
- "${pgwebPort}:8081"
|
|
60
62
|
environment:
|
|
@@ -65,16 +67,16 @@ export function generateDockerCompose(dbPort, pgwebPort) {
|
|
|
65
67
|
restart: on-failure
|
|
66
68
|
|
|
67
69
|
volumes:
|
|
68
|
-
|
|
70
|
+
${prefix}-data:
|
|
69
71
|
`;
|
|
70
72
|
}
|
|
71
|
-
export function createWorkspaceFiles(workspaceDir, jira, git, github, csv, db, dbPort, pgwebPort) {
|
|
73
|
+
export function createWorkspaceFiles(workspaceDir, jira, git, github, csv, db, dbPort, pgwebPort, workspaceName) {
|
|
72
74
|
const templatesDir = getTemplatesDir();
|
|
73
75
|
mkdirSync(workspaceDir, { recursive: true });
|
|
74
76
|
mkdirSync(join(workspaceDir, '.argustack'), { recursive: true });
|
|
75
77
|
mkdirSync(join(workspaceDir, 'db'), { recursive: true });
|
|
76
78
|
mkdirSync(join(workspaceDir, 'data'), { recursive: true });
|
|
77
|
-
let config = createEmptyConfig();
|
|
79
|
+
let config = createEmptyConfig(workspaceName);
|
|
78
80
|
if (jira) {
|
|
79
81
|
config = addSource(config, 'jira');
|
|
80
82
|
}
|
|
@@ -92,7 +94,7 @@ export function createWorkspaceFiles(workspaceDir, jira, git, github, csv, db, d
|
|
|
92
94
|
}
|
|
93
95
|
writeConfig(workspaceDir, config);
|
|
94
96
|
writeFileSync(join(workspaceDir, '.env'), generateEnv(jira, git, github, csv, db, dbPort));
|
|
95
|
-
writeFileSync(join(workspaceDir, 'docker-compose.yml'), generateDockerCompose(dbPort, pgwebPort));
|
|
97
|
+
writeFileSync(join(workspaceDir, 'docker-compose.yml'), generateDockerCompose(dbPort, pgwebPort, workspaceName));
|
|
96
98
|
copyFileSync(join(templatesDir, 'init.sql'), join(workspaceDir, 'db', 'init.sql'));
|
|
97
99
|
copyFileSync(join(templatesDir, 'gitignore'), join(workspaceDir, '.gitignore'));
|
|
98
100
|
try {
|
|
@@ -115,21 +117,21 @@ export function printSummary(workspaceDir, jira, git, github, csv, db, pgwebPort
|
|
|
115
117
|
console.log('');
|
|
116
118
|
console.log(chalk.dim(' Sources configured:'));
|
|
117
119
|
if (jira) {
|
|
118
|
-
console.log(` ${chalk.green('✓')} Jira — ${jira.jiraUrl}`);
|
|
120
|
+
console.log(` ${chalk.green('✓')} Jira — ${maskHost(jira.jiraUrl.replace(/^https?:\/\//, ''))}`);
|
|
119
121
|
}
|
|
120
122
|
if (git) {
|
|
121
123
|
for (const p of git.gitRepoPaths) {
|
|
122
|
-
console.log(` ${chalk.green('✓')} Git — ${p}`);
|
|
124
|
+
console.log(` ${chalk.green('✓')} Git — ${maskPath(p)}`);
|
|
123
125
|
}
|
|
124
126
|
}
|
|
125
127
|
if (github) {
|
|
126
|
-
console.log(` ${chalk.green('✓')} GitHub — ${github.githubOwner
|
|
128
|
+
console.log(` ${chalk.green('✓')} GitHub — ${maskOrgRepo(github.githubOwner, github.githubRepo)}`);
|
|
127
129
|
}
|
|
128
130
|
if (csv) {
|
|
129
131
|
console.log(` ${chalk.green('✓')} Jira CSV — ${csv.csvFilePath}`);
|
|
130
132
|
}
|
|
131
133
|
if (db) {
|
|
132
|
-
console.log(` ${chalk.green('✓')} Database — ${db.targetDbHost}:${db.targetDbPort}`);
|
|
134
|
+
console.log(` ${chalk.green('✓')} Database — ${maskHost(db.targetDbHost)}:${db.targetDbPort}`);
|
|
133
135
|
}
|
|
134
136
|
if (!jira && !git && !github && !csv && !db) {
|
|
135
137
|
console.log(` ${chalk.yellow('—')} None yet. Use ${chalk.cyan('argustack source add <type>')}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generators.js","sourceRoot":"","sources":["../../../src/cli/init/generators.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"generators.js","sourceRoot":"","sources":["../../../src/cli/init/generators.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/init/index.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
+
import type { WorkspaceConfig } from '../../core/types/index.js';
|
|
1
2
|
import type { InitFlags } from './types.js';
|
|
2
3
|
export type { InitFlags } from './types.js';
|
|
4
|
+
interface WorkspaceInfo {
|
|
5
|
+
name: string;
|
|
6
|
+
path: string;
|
|
7
|
+
config: WorkspaceConfig;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Scan directory for existing workspace subdirectories.
|
|
11
|
+
*/
|
|
12
|
+
export declare function scanWorkspaces(dir: string): WorkspaceInfo[];
|
|
3
13
|
export declare function runInit(flags?: InitFlags): Promise<void>;
|
|
4
14
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/init/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/cli/init/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAc,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAE7E,OAAO,KAAK,EACV,SAAS,EAMV,MAAM,YAAY,CAAC;AASpB,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,eAAe,CAAC;CACzB;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,EAAE,CA8B3D;AAkYD,wBAAsB,OAAO,CAAC,KAAK,GAAE,SAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlE"}
|
package/dist/cli/init/index.js
CHANGED
|
@@ -1,16 +1,70 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { readdirSync } from 'node:fs';
|
|
2
|
+
import { join, resolve, basename } from 'node:path';
|
|
3
|
+
import { input, confirm, checkbox, select } from '@inquirer/prompts';
|
|
2
4
|
import { execSync } from 'node:child_process';
|
|
3
5
|
import chalk from 'chalk';
|
|
4
6
|
import ora from 'ora';
|
|
5
7
|
import { isWorkspace } from '../../workspace/resolver.js';
|
|
8
|
+
import { readConfig } from '../../workspace/config.js';
|
|
6
9
|
import { ALL_SOURCES, SOURCE_META } from '../../core/types/index.js';
|
|
7
|
-
import { DEFAULT_DB_PORT, DEFAULT_PGWEB_PORT,
|
|
10
|
+
import { DEFAULT_DB_PORT, DEFAULT_PGWEB_PORT, validatePort, getErrorMsg } from './types.js';
|
|
8
11
|
import { setupJiraInteractive, setupJiraFromFlags } from './setup-jira.js';
|
|
9
12
|
import { setupGitInteractive, setupGitFromFlags } from './setup-git.js';
|
|
10
13
|
import { setupGithubInteractive, setupGithubFromFlags } from './setup-github.js';
|
|
11
14
|
import { setupCsvInteractive, setupCsvFromFlags } from './setup-csv.js';
|
|
12
15
|
import { setupDbInteractive, setupDbFromFlags } from './setup-db.js';
|
|
13
16
|
import { createWorkspaceFiles, printSummary } from './generators.js';
|
|
17
|
+
/**
|
|
18
|
+
* Scan directory for existing workspace subdirectories.
|
|
19
|
+
*/
|
|
20
|
+
export function scanWorkspaces(dir) {
|
|
21
|
+
const resolved = resolve(dir);
|
|
22
|
+
const workspaces = [];
|
|
23
|
+
let entries;
|
|
24
|
+
try {
|
|
25
|
+
entries = readdirSync(resolved);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
for (const name of entries) {
|
|
31
|
+
if (name.startsWith('.')) {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const subdir = join(resolved, name);
|
|
35
|
+
if (isWorkspace(subdir)) {
|
|
36
|
+
const config = readConfig(subdir);
|
|
37
|
+
if (config) {
|
|
38
|
+
workspaces.push({
|
|
39
|
+
name: config.name ?? name,
|
|
40
|
+
path: subdir,
|
|
41
|
+
config,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return workspaces;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Sanitize workspace name to kebab-case directory name.
|
|
50
|
+
*/
|
|
51
|
+
function sanitizeName(raw) {
|
|
52
|
+
return raw
|
|
53
|
+
.toLowerCase()
|
|
54
|
+
.trim()
|
|
55
|
+
.replace(/[^a-z0-9-]/g, '-')
|
|
56
|
+
.replace(/-+/g, '-')
|
|
57
|
+
.replace(/^-|-$/g, '');
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Find next available port by checking existing docker-compose files.
|
|
61
|
+
*/
|
|
62
|
+
function findNextPort(workspaces, basePort) {
|
|
63
|
+
if (workspaces.length === 0) {
|
|
64
|
+
return basePort;
|
|
65
|
+
}
|
|
66
|
+
return basePort + workspaces.length;
|
|
67
|
+
}
|
|
14
68
|
async function startAndSync(workspaceDir, hasJira, hasGit, hasGithub, csv, db, pgwebPort) {
|
|
15
69
|
const spinnerDb = ora('Starting Docker containers...').start();
|
|
16
70
|
try {
|
|
@@ -104,9 +158,64 @@ async function startAndSync(workspaceDir, hasJira, hasGit, hasGithub, csv, db, p
|
|
|
104
158
|
console.log(` Claude Desktop: ${chalk.cyan('argustack mcp install')}`);
|
|
105
159
|
console.log('');
|
|
106
160
|
}
|
|
161
|
+
async function setupSources(flags) {
|
|
162
|
+
console.log('');
|
|
163
|
+
const selectedSources = await checkbox({
|
|
164
|
+
message: 'Which sources do you have access to?',
|
|
165
|
+
choices: ALL_SOURCES.map((s) => ({
|
|
166
|
+
value: s,
|
|
167
|
+
name: SOURCE_META[s].label,
|
|
168
|
+
description: SOURCE_META[s].description,
|
|
169
|
+
})),
|
|
170
|
+
});
|
|
171
|
+
if (selectedSources.length === 0) {
|
|
172
|
+
console.log(chalk.yellow('\n No sources selected. You can add them later with:'));
|
|
173
|
+
console.log(chalk.cyan(' argustack source add jira'));
|
|
174
|
+
const continueAnyway = await confirm({
|
|
175
|
+
message: 'Create workspace without sources?',
|
|
176
|
+
default: true,
|
|
177
|
+
});
|
|
178
|
+
if (!continueAnyway) {
|
|
179
|
+
throw new Error('Cancelled');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
let jira = null;
|
|
183
|
+
let git = null;
|
|
184
|
+
let github = null;
|
|
185
|
+
let csv = null;
|
|
186
|
+
let db = null;
|
|
187
|
+
for (const source of selectedSources) {
|
|
188
|
+
switch (source) {
|
|
189
|
+
case 'jira':
|
|
190
|
+
jira = await setupJiraInteractive();
|
|
191
|
+
break;
|
|
192
|
+
case 'git':
|
|
193
|
+
git = await setupGitInteractive();
|
|
194
|
+
break;
|
|
195
|
+
case 'github':
|
|
196
|
+
github = await setupGithubInteractive(git?.githubToken, git?.githubRepos);
|
|
197
|
+
break;
|
|
198
|
+
case 'csv':
|
|
199
|
+
csv = await setupCsvInteractive();
|
|
200
|
+
break;
|
|
201
|
+
case 'db':
|
|
202
|
+
db = await setupDbInteractive();
|
|
203
|
+
break;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
void flags;
|
|
207
|
+
return { jira, git, github, csv, db };
|
|
208
|
+
}
|
|
107
209
|
async function runInitNonInteractive(flags) {
|
|
108
210
|
console.log(chalk.bold('\n Argustack — non-interactive setup\n'));
|
|
109
|
-
|
|
211
|
+
if (!flags.name) {
|
|
212
|
+
throw new Error('Workspace name is required. Usage: argustack init <name>');
|
|
213
|
+
}
|
|
214
|
+
const workspaceName = sanitizeName(flags.name);
|
|
215
|
+
const workspaceDir = resolve(process.cwd(), workspaceName);
|
|
216
|
+
if (isWorkspace(workspaceDir)) {
|
|
217
|
+
throw new Error(`Workspace '${workspaceName}' already exists at ${workspaceDir}`);
|
|
218
|
+
}
|
|
110
219
|
const selectedSources = flags.source
|
|
111
220
|
? flags.source.split(',').map((s) => s.trim().toLowerCase())
|
|
112
221
|
: [];
|
|
@@ -139,12 +248,13 @@ async function runInitNonInteractive(flags) {
|
|
|
139
248
|
break;
|
|
140
249
|
}
|
|
141
250
|
}
|
|
142
|
-
const
|
|
143
|
-
const
|
|
251
|
+
const existing = scanWorkspaces(process.cwd());
|
|
252
|
+
const dbPort = parseInt(flags.dbPort ?? String(findNextPort(existing, DEFAULT_DB_PORT)), 10);
|
|
253
|
+
const pgwebPort = parseInt(flags.pgwebPort ?? String(findNextPort(existing, DEFAULT_PGWEB_PORT)), 10);
|
|
144
254
|
const spinner = ora('Creating workspace...').start();
|
|
145
255
|
try {
|
|
146
|
-
createWorkspaceFiles(workspaceDir, jiraResult, gitResult, githubResult, csvResult, dbResult, dbPort, pgwebPort);
|
|
147
|
-
spinner.succeed(
|
|
256
|
+
createWorkspaceFiles(workspaceDir, jiraResult, gitResult, githubResult, csvResult, dbResult, dbPort, pgwebPort, workspaceName);
|
|
257
|
+
spinner.succeed(`Workspace '${workspaceName}' created!`);
|
|
148
258
|
}
|
|
149
259
|
catch (err) {
|
|
150
260
|
spinner.fail('Failed');
|
|
@@ -156,89 +266,112 @@ async function runInitInteractive(flags) {
|
|
|
156
266
|
console.log('');
|
|
157
267
|
console.log(chalk.bold(' Argustack — workspace setup'));
|
|
158
268
|
console.log(chalk.dim(' Cross-reference Jira + Git + DB to analyze your project.\n'));
|
|
159
|
-
const
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
269
|
+
const cwd = process.cwd();
|
|
270
|
+
const existing = scanWorkspaces(cwd);
|
|
271
|
+
let workspaceName;
|
|
272
|
+
let workspaceDir;
|
|
273
|
+
if (existing.length > 0) {
|
|
274
|
+
console.log(chalk.dim(` Found ${String(existing.length)} workspace(s) in ${basename(cwd)}:`));
|
|
275
|
+
for (const ws of existing) {
|
|
276
|
+
const sources = ws.config.order.length > 0
|
|
277
|
+
? ws.config.order.map((s) => SOURCE_META[s].label).join(', ')
|
|
278
|
+
: 'no sources';
|
|
279
|
+
console.log(` ${chalk.green('●')} ${chalk.bold(ws.name)} — ${chalk.dim(sources)}`);
|
|
280
|
+
}
|
|
281
|
+
console.log('');
|
|
282
|
+
const action = await select({
|
|
283
|
+
message: 'What would you like to do?',
|
|
284
|
+
choices: [
|
|
285
|
+
{ value: 'new', name: 'Create new workspace' },
|
|
286
|
+
...existing.map((ws) => ({
|
|
287
|
+
value: `update:${ws.name}`,
|
|
288
|
+
name: `Update ${ws.name}`,
|
|
289
|
+
})),
|
|
290
|
+
],
|
|
291
|
+
});
|
|
292
|
+
if (action.startsWith('update:')) {
|
|
293
|
+
const updateName = action.slice('update:'.length);
|
|
294
|
+
const ws = existing.find((w) => w.name === updateName);
|
|
295
|
+
if (!ws) {
|
|
296
|
+
throw new Error(`Workspace '${updateName}' not found`);
|
|
165
297
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
298
|
+
console.log(chalk.dim(`\n Updating workspace: ${updateName}\n`));
|
|
299
|
+
workspaceName = updateName;
|
|
300
|
+
workspaceDir = ws.path;
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
const rawName = flags.name ?? await input({
|
|
304
|
+
message: 'Workspace name:',
|
|
305
|
+
validate: (val) => {
|
|
306
|
+
if (val.includes('://') || val.includes('.') || val.includes('/')) {
|
|
307
|
+
return 'This looks like a URL. Enter a short project name (e.g. "paperlink", "my-project")';
|
|
308
|
+
}
|
|
309
|
+
const sanitized = sanitizeName(val);
|
|
310
|
+
if (!sanitized) {
|
|
311
|
+
return 'Name is required (letters, numbers, hyphens)';
|
|
312
|
+
}
|
|
313
|
+
if (sanitized.length > 30) {
|
|
314
|
+
return 'Name too long — keep it under 30 characters';
|
|
315
|
+
}
|
|
316
|
+
if (existing.some((ws) => ws.name === sanitized)) {
|
|
317
|
+
return `Workspace '${sanitized}' already exists`;
|
|
318
|
+
}
|
|
319
|
+
return true;
|
|
320
|
+
},
|
|
321
|
+
});
|
|
322
|
+
workspaceName = sanitizeName(rawName);
|
|
323
|
+
workspaceDir = join(cwd, workspaceName);
|
|
176
324
|
}
|
|
177
325
|
}
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
message: 'Create workspace without sources?',
|
|
195
|
-
default: true,
|
|
326
|
+
else {
|
|
327
|
+
const rawName = flags.name ?? await input({
|
|
328
|
+
message: 'Workspace name:',
|
|
329
|
+
validate: (val) => {
|
|
330
|
+
if (val.includes('://') || val.includes('.') || val.includes('/')) {
|
|
331
|
+
return 'This looks like a URL. Enter a short project name (e.g. "paperlink", "my-project")';
|
|
332
|
+
}
|
|
333
|
+
const sanitized = sanitizeName(val);
|
|
334
|
+
if (!sanitized) {
|
|
335
|
+
return 'Name is required (letters, numbers, hyphens)';
|
|
336
|
+
}
|
|
337
|
+
if (sanitized.length > 30) {
|
|
338
|
+
return 'Name too long — keep it under 30 characters';
|
|
339
|
+
}
|
|
340
|
+
return true;
|
|
341
|
+
},
|
|
196
342
|
});
|
|
197
|
-
|
|
343
|
+
workspaceName = sanitizeName(rawName);
|
|
344
|
+
workspaceDir = join(cwd, workspaceName);
|
|
345
|
+
}
|
|
346
|
+
if (isWorkspace(workspaceDir)) {
|
|
347
|
+
console.log(chalk.yellow(`\n Workspace '${workspaceName}' already exists.`));
|
|
348
|
+
const proceed = await confirm({ message: 'Reinitialize this workspace?', default: false });
|
|
349
|
+
if (!proceed) {
|
|
198
350
|
console.log(chalk.dim(' Cancelled.'));
|
|
199
351
|
return;
|
|
200
352
|
}
|
|
201
353
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
let csvResult = null;
|
|
206
|
-
let dbResult = null;
|
|
207
|
-
for (const source of selectedSources) {
|
|
208
|
-
switch (source) {
|
|
209
|
-
case 'jira':
|
|
210
|
-
jiraResult = await setupJiraInteractive();
|
|
211
|
-
break;
|
|
212
|
-
case 'git':
|
|
213
|
-
gitResult = await setupGitInteractive();
|
|
214
|
-
break;
|
|
215
|
-
case 'github':
|
|
216
|
-
githubResult = await setupGithubInteractive(gitResult?.githubToken, gitResult?.githubRepos);
|
|
217
|
-
break;
|
|
218
|
-
case 'csv':
|
|
219
|
-
csvResult = await setupCsvInteractive();
|
|
220
|
-
break;
|
|
221
|
-
case 'db':
|
|
222
|
-
dbResult = await setupDbInteractive();
|
|
223
|
-
break;
|
|
224
|
-
}
|
|
225
|
-
}
|
|
354
|
+
process.env['ARGUSTACK_INIT_WORKSPACE'] = workspaceName;
|
|
355
|
+
const { jira, git, github, csv, db } = await setupSources(flags);
|
|
356
|
+
delete process.env['ARGUSTACK_INIT_WORKSPACE'];
|
|
226
357
|
console.log('');
|
|
227
358
|
console.log(chalk.dim(' Argustack internal database (Docker):'));
|
|
359
|
+
const defaultDbPort = findNextPort(existing, DEFAULT_DB_PORT);
|
|
360
|
+
const defaultPgwebPort = findNextPort(existing, DEFAULT_PGWEB_PORT);
|
|
228
361
|
const dbPortStr = await input({
|
|
229
|
-
message: 'PostgreSQL port:', default: flags.dbPort ?? String(
|
|
362
|
+
message: 'PostgreSQL port:', default: flags.dbPort ?? String(defaultDbPort),
|
|
230
363
|
validate: (val) => validatePort(val, 1024),
|
|
231
364
|
});
|
|
232
365
|
const pgwebPortStr = await input({
|
|
233
|
-
message: 'pgweb UI port:', default: flags.pgwebPort ?? String(
|
|
366
|
+
message: 'pgweb UI port:', default: flags.pgwebPort ?? String(defaultPgwebPort),
|
|
234
367
|
validate: (val) => validatePort(val, 1024),
|
|
235
368
|
});
|
|
236
369
|
const dbPort = parseInt(dbPortStr, 10);
|
|
237
370
|
const pgwebPort = parseInt(pgwebPortStr, 10);
|
|
238
371
|
const spinner = ora('Creating workspace...').start();
|
|
239
372
|
try {
|
|
240
|
-
createWorkspaceFiles(workspaceDir,
|
|
241
|
-
spinner.succeed(
|
|
373
|
+
createWorkspaceFiles(workspaceDir, jira, git, github, csv, db, dbPort, pgwebPort, workspaceName);
|
|
374
|
+
spinner.succeed(`Workspace '${workspaceName}' created!`);
|
|
242
375
|
}
|
|
243
376
|
catch (err) {
|
|
244
377
|
spinner.fail('Failed to create workspace');
|
|
@@ -249,9 +382,9 @@ async function runInitInteractive(flags) {
|
|
|
249
382
|
message: 'Start database and sync now?',
|
|
250
383
|
default: true,
|
|
251
384
|
});
|
|
252
|
-
printSummary(workspaceDir,
|
|
385
|
+
printSummary(workspaceDir, jira, git, github, csv, db, pgwebPort, autoStart);
|
|
253
386
|
if (autoStart) {
|
|
254
|
-
await startAndSync(workspaceDir,
|
|
387
|
+
await startAndSync(workspaceDir, jira !== null, git !== null, github !== null, csv, db, pgwebPort);
|
|
255
388
|
}
|
|
256
389
|
}
|
|
257
390
|
export async function runInit(flags = {}) {
|