argustack 0.1.7 → 0.1.9

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 (89) hide show
  1. package/README.md +58 -398
  2. package/dist/adapters/db/client.d.ts +13 -0
  3. package/dist/adapters/db/client.d.ts.map +1 -0
  4. package/dist/adapters/db/client.js +70 -0
  5. package/dist/adapters/db/client.js.map +1 -0
  6. package/dist/adapters/db/index.d.ts +4 -0
  7. package/dist/adapters/db/index.d.ts.map +1 -0
  8. package/dist/adapters/db/index.js +3 -0
  9. package/dist/adapters/db/index.js.map +1 -0
  10. package/dist/adapters/db/mapper.d.ts +31 -0
  11. package/dist/adapters/db/mapper.d.ts.map +1 -0
  12. package/dist/adapters/db/mapper.js +55 -0
  13. package/dist/adapters/db/mapper.js.map +1 -0
  14. package/dist/adapters/db/provider.d.ts +24 -0
  15. package/dist/adapters/db/provider.d.ts.map +1 -0
  16. package/dist/adapters/db/provider.js +159 -0
  17. package/dist/adapters/db/provider.js.map +1 -0
  18. package/dist/adapters/db/sql-validator.d.ts +10 -0
  19. package/dist/adapters/db/sql-validator.d.ts.map +1 -0
  20. package/dist/adapters/db/sql-validator.js +41 -0
  21. package/dist/adapters/db/sql-validator.js.map +1 -0
  22. package/dist/adapters/postgres/schema.d.ts.map +1 -1
  23. package/dist/adapters/postgres/schema.js +55 -0
  24. package/dist/adapters/postgres/schema.js.map +1 -1
  25. package/dist/adapters/postgres/storage.d.ts +3 -0
  26. package/dist/adapters/postgres/storage.d.ts.map +1 -1
  27. package/dist/adapters/postgres/storage.js +51 -0
  28. package/dist/adapters/postgres/storage.js.map +1 -1
  29. package/dist/cli/index.js +2 -1
  30. package/dist/cli/index.js.map +1 -1
  31. package/dist/cli/init/generators.d.ts.map +1 -1
  32. package/dist/cli/init/generators.js +1 -1
  33. package/dist/cli/init/generators.js.map +1 -1
  34. package/dist/cli/init/index.d.ts.map +1 -1
  35. package/dist/cli/init/index.js +13 -2
  36. package/dist/cli/init/index.js.map +1 -1
  37. package/dist/cli/init/setup-db.d.ts.map +1 -1
  38. package/dist/cli/init/setup-db.js +128 -12
  39. package/dist/cli/init/setup-db.js.map +1 -1
  40. package/dist/cli/init/setup-git.d.ts.map +1 -1
  41. package/dist/cli/init/setup-git.js +5 -1
  42. package/dist/cli/init/setup-git.js.map +1 -1
  43. package/dist/cli/init/setup-jira.d.ts.map +1 -1
  44. package/dist/cli/init/setup-jira.js +5 -2
  45. package/dist/cli/init/setup-jira.js.map +1 -1
  46. package/dist/cli/init/types.d.ts +2 -0
  47. package/dist/cli/init/types.d.ts.map +1 -1
  48. package/dist/cli/init/types.js.map +1 -1
  49. package/dist/cli/sync.d.ts +1 -0
  50. package/dist/cli/sync.d.ts.map +1 -1
  51. package/dist/cli/sync.js +48 -1
  52. package/dist/cli/sync.js.map +1 -1
  53. package/dist/core/ports/db-provider.d.ts +33 -0
  54. package/dist/core/ports/db-provider.d.ts.map +1 -0
  55. package/dist/core/ports/db-provider.js +2 -0
  56. package/dist/core/ports/db-provider.js.map +1 -0
  57. package/dist/core/ports/index.d.ts +1 -0
  58. package/dist/core/ports/index.d.ts.map +1 -1
  59. package/dist/core/ports/storage.d.ts +5 -0
  60. package/dist/core/ports/storage.d.ts.map +1 -1
  61. package/dist/core/types/config.d.ts.map +1 -1
  62. package/dist/core/types/config.js +5 -2
  63. package/dist/core/types/config.js.map +1 -1
  64. package/dist/core/types/database.d.ts +37 -0
  65. package/dist/core/types/database.d.ts.map +1 -0
  66. package/dist/core/types/database.js +2 -0
  67. package/dist/core/types/database.js.map +1 -0
  68. package/dist/core/types/index.d.ts +1 -0
  69. package/dist/core/types/index.d.ts.map +1 -1
  70. package/dist/mcp/server.d.ts.map +1 -1
  71. package/dist/mcp/server.js +2 -0
  72. package/dist/mcp/server.js.map +1 -1
  73. package/dist/mcp/tools/database.d.ts +4 -0
  74. package/dist/mcp/tools/database.d.ts.map +1 -0
  75. package/dist/mcp/tools/database.js +254 -0
  76. package/dist/mcp/tools/database.js.map +1 -0
  77. package/dist/mcp/tools/estimate.d.ts +10 -0
  78. package/dist/mcp/tools/estimate.d.ts.map +1 -1
  79. package/dist/mcp/tools/estimate.js +3 -3
  80. package/dist/mcp/tools/estimate.js.map +1 -1
  81. package/dist/use-cases/pull-db.d.ts +25 -0
  82. package/dist/use-cases/pull-db.d.ts.map +1 -0
  83. package/dist/use-cases/pull-db.js +59 -0
  84. package/dist/use-cases/pull-db.js.map +1 -0
  85. package/package.json +2 -1
  86. package/dist/cli/init.d.ts +0 -24
  87. package/dist/cli/init.d.ts.map +0 -1
  88. package/dist/cli/init.js +0 -957
  89. package/dist/cli/init.js.map +0 -1
package/README.md CHANGED
@@ -1,445 +1,105 @@
1
1
  # Argustack
2
2
 
3
- **RAG engine for project intelligence — ask AI about your Jira, Git, and databases**
3
+ [![npm version](https://img.shields.io/npm/v/argustack.svg)](https://www.npmjs.com/package/argustack)
4
+ [![npm downloads](https://img.shields.io/npm/dm/argustack.svg)](https://www.npmjs.com/package/argustack)
5
+ [![license](https://img.shields.io/npm/l/argustack.svg)](LICENSE)
4
6
 
5
- [RAG](https://en.wikipedia.org/wiki/Retrieval-augmented_generation) (Retrieval-Augmented Generation) an architecture where AI answers questions based on **your** data, not its training set:
7
+ **Ask AI about your Jira, Git, and GitHub powered by local data, not cloud APIs.**
6
8
 
7
- 1. **Retrieval** pull and index your project data locally (PostgreSQL + pgvector)
8
- 2. **Augmentation** — inject relevant context into the AI prompt
9
- 3. **Generation** — LLM generates answers grounded in your actual Jira tickets, code, and databases
9
+ Argustack downloads your project data into local PostgreSQL, cross-references everything, and gives Claude direct access via 15 MCP tools. All data stays on your machine.
10
10
 
11
- Argustack builds this knowledge base from your project's sources of truth:
11
+ > *Was ticket PROJ-123 implemented as described?*
12
+ > *Who reviewed the PR and what was the feedback?*
13
+ > *How long will it take Sarah to fix this bug?*
12
14
 
13
- ```
14
- YOUR SOURCES YOUR MACHINE
15
- ┌──────────────────────┐ ┌─────────────────────────────────────┐
16
- │ Jira Cloud / Server │ │ │
17
- │ (issues, comments, │ pull │ PostgreSQL (Docker, localhost) │
18
- │ changelogs, etc.) │ ──────►│ ├── issues (all fields) │
19
- └──────────────────────┘ │ ├── issue_comments (discussions) │
20
- │ ├── issue_changelogs (history) │
21
- ┌──────────────────────┐ │ ├── issue_worklogs (time logs) │
22
- │ Git repository │ pull │ ├── issue_links (relations) │
23
- │ (commits, files, │ ──────►│ ├── commits (history) │
24
- │ diffs, authors) │ │ ├── commit_files (per-file Δ) │
25
- └──────────────────────┘ │ ├── commit_issue_refs (cross-ref)│
26
- │ │ │
27
- ┌──────────────────────┐ │ │ GitHub (optional, via token) │
28
- │ GitHub API │ pull │ ├── pull_requests (PRs + meta) │
29
- │ (PRs, reviews, │ ──────►│ ├── pr_reviews (approvals) │
30
- │ releases) │ │ ├── pr_comments (discussions) │
31
- └──────────────────────┘ │ ├── pr_issue_refs (PR↔Jira) │
32
- │ └── releases (tags) │
33
- ┌──────────────────────┐ │ │
34
- │ Database (planned) │ │ MCP Server (localhost, stdio) │
35
- └──────────────────────┘ │ └── queries DB ──► Claude / LLM │
36
- │ │
37
- │ .env (credentials — never leaves) │
38
- └─────────────────────────────────────┘
39
- ```
40
-
41
- > *Is this bug still relevant or already fixed in code?*
42
- > *Was the feature implemented as described in the ticket?*
43
- > *Who worked on this module and what changed last month?*
44
- > *Which commits and PRs reference ticket PROJ-123?*
45
- > *Who approved the PR and what was the review feedback?*
46
-
47
- ## How it works
15
+ ## Features
48
16
 
49
- **Retrieval** — pulls all data from Jira, Git, and GitHub into local PostgreSQL with pgvector. Every field, every comment, every changelog entry, every commit with per-file diffs, every PR with reviews and approvals. Raw JSON preserved as-is. Nothing is filtered or lost.
50
-
51
- **Augmentation** — MCP server gives Claude Desktop / Claude Code direct access to your local database. Full-text search, semantic search (pgvector embeddings), filters, raw SQL, aggregate statistics, cross-source timeline, cross-reference between Jira issues, Git commits, and GitHub PRs — all without leaving your machine.
52
-
53
- **Generation** — ask questions in natural language. Claude queries your local data and answers with full project context.
17
+ - **Jira** — issues, comments, changelogs, worklogs, links, all custom fields
18
+ - **Git** — commits, per-file diffs, automatic issue cross-references
19
+ - **GitHub** — PRs, reviews, comments, releases, automatic issue cross-references
20
+ - **CSV import** — Jira CSV export for teams without API access
21
+ - **Cross-source timeline** — Jira + Git + GitHub events in chronological order
22
+ - **Semantic search** — find issues by meaning, not just keywords (pgvector)
23
+ - **Task estimation** — predict duration per developer based on actual history
24
+ - **15 MCP tools** — Claude queries your data directly via SQL
25
+ - **100% local** — no cloud, no accounts, no telemetry
54
26
 
55
27
  ## Quick Start
56
28
 
57
- ### Prerequisites
58
-
59
- - [Node.js](https://nodejs.org/) >= 20
60
- - [Docker](https://www.docker.com/) (or [OrbStack](https://orbstack.dev/) / Podman)
61
-
62
- ### Install & setup
63
-
64
29
  ```bash
65
30
  npm i -g argustack
66
- argustack init
67
- ```
68
-
69
- Argustack supports **two modes** of initialization:
70
-
71
- #### Interactive mode (default)
72
-
73
- Run `argustack init` and follow the prompts:
74
-
31
+ argustack init # interactive setup — sources, credentials, Docker
32
+ argustack sync # pull all data
33
+ argustack mcp install # connect to Claude Desktop
75
34
  ```
76
- ? Workspace directory: ~/projects/my-team
77
- ? Sources: ✔ Jira — issues, comments, changelogs
78
- ✔ Git — commits, diffs, authors
79
- ✔ GitHub — PRs, reviews, releases
80
- ? Jira URL: https://your-team.atlassian.net
81
- ? Email: you@company.com
82
- ? API Token: ****
83
-
84
- Testing connection... Connected! Found 3 projects: MKT, BRAND, WEB
85
-
86
- ? Projects to pull: ✔ MKT ✔ BRAND
87
- ? Where is your Git repository?
88
- ● Clone from GitHub — select repos using your token
89
- ? GitHub token (PAT): ****
90
-
91
- Fetching repositories... Found 12 repos.
92
35
 
93
- ? Repositories to clone: your-org/frontend ✔ your-org/backend
94
- ? GitHub source: Auto-configured from clone step
95
-
96
- ? Start database and sync now? Yes
97
-
98
- ✔ Database running!
99
- ✔ Jira sync complete!
100
- MKT: 506 issues (150/506 ████░░░░ 30% → 506/506 done)
101
- ✔ Git sync complete!
102
- your-org/frontend: 735 commits (400/735 ██████░░ 54% → 735/735 done)
103
- ✔ GitHub sync complete!
104
- 66 PRs (30/66 ██████░░ 45% → 66/66 done), 124 reviews, 3 releases
105
- ```
36
+ That's it. Ask Claude about your project.
106
37
 
107
- The interactive setup will:
38
+ ### Non-interactive mode
108
39
 
109
- 1. Ask which sources you have (Jira, Git, GitHub, Database)
110
- 2. Collect credentials and test connections
111
- 3. For Git — choose local path, clone from GitHub (multi-select repos), or clone from URL
112
- 4. For GitHub — auto-configured if you cloned from GitHub in the previous step, or enter a Personal Access Token (see [GitHub token setup](#github-token-setup))
113
- 5. Create a workspace with Docker config
114
- 6. Start PostgreSQL + pgweb automatically
115
- 7. Pull all your data
116
-
117
- #### Non-interactive mode (for AI agents and CI/CD)
118
-
119
- Pass `--no-interactive` with all values as CLI flags — no prompts, no terminal needed:
40
+ For AI agents and CI/CD pass everything as flags:
120
41
 
121
42
  ```bash
122
- argustack init \
123
- --no-interactive \
124
- --dir ~/projects/my-team \
43
+ argustack init --no-interactive \
125
44
  --source jira,git,github \
126
45
  --jira-url "https://your-team.atlassian.net" \
127
46
  --jira-email "you@company.com" \
128
47
  --jira-token "ATATT3x..." \
129
- --jira-projects PAP,MKT \
130
- --git-repo /path/to/repo1,/path/to/repo2 \
48
+ --jira-projects PROJ,MKT \
49
+ --git-repo /path/to/repo \
131
50
  --github-token "github_pat_..." \
132
51
  --github-owner your-org \
133
52
  --github-repo your-repo
134
53
  ```
135
54
 
136
- Then start the database and sync:
137
-
138
- ```bash
139
- cd ~/projects/my-team
140
- docker compose up -d
141
- argustack sync
142
- ```
143
-
144
- All available flags:
145
-
146
- | Flag | Description |
147
- |------|-------------|
148
- | `--no-interactive` | Run without prompts — all values from flags |
149
- | `-d, --dir <path>` | Workspace directory (default: current) |
150
- | `-s, --source <list>` | Comma-separated: `jira,git,github,csv,db` |
151
- | `--jira-url <url>` | Jira instance URL |
152
- | `--jira-email <email>` | Jira user email |
153
- | `--jira-token <token>` | Jira API token |
154
- | `--jira-projects <keys>` | Comma-separated project keys, or `all` |
155
- | `--git-repo <paths>` | Git repo paths, comma-separated |
156
- | `--github-token <token>` | GitHub Personal Access Token |
157
- | `--github-owner <owner>` | GitHub repo owner |
158
- | `--github-repo <repo>` | GitHub repo name |
159
- | `--csv-file <path>` | Path to Jira CSV export file |
160
- | `--db-port <port>` | Argustack PostgreSQL port (default: `5434`) |
161
- | `--pgweb-port <port>` | pgweb UI port (default: `8086`) |
162
-
163
- This mode is ideal for:
164
- - **AI agents** — a project manager tells their AI agent "set up argustack" and it runs everything autonomously
165
- - **CI/CD pipelines** — automated workspace provisioning
166
- - **Scripted setups** — reproducible environment creation
167
-
168
- Browse your data at [localhost:8086](http://localhost:8086) — pgweb UI for running SQL queries and exploring tables in your browser.
169
-
170
- ### Connect to Claude
171
-
172
- ```bash
173
- argustack mcp install
174
- ```
175
-
176
- Adds Argustack as an MCP server to Claude Desktop. Now you can ask Claude questions about your project data directly.
177
-
178
55
  ## Commands
179
56
 
180
57
  ```bash
181
- argustack init # create workspace (interactive prompts)
182
- argustack init --no-interactive ... # create workspace from CLI flags (no prompts)
183
- argustack sync # pull data from all configured sources
184
- argustack sync jira # pull Jira only
185
- argustack sync git # pull Git commits only
186
- argustack sync github # pull GitHub PRs, reviews, releases
187
- argustack sync csv # import from Jira CSV export
188
- argustack sync csv -f /path/to.csv # import specific CSV file
189
- argustack sync -p PROJ # pull specific Jira project
190
- argustack sync --since 2025-01-01 # incremental pull (only new/updated)
58
+ argustack init # create workspace
59
+ argustack sync # pull all sources
60
+ argustack sync jira|git|github|csv # pull specific source
61
+ argustack sync --since 2025-01-01 # incremental pull
62
+ argustack embed # generate embeddings (requires OpenAI key)
63
+ argustack mcp install # connect to Claude Desktop
191
64
  argustack sources # list configured sources
192
65
  argustack status # workspace info
193
- argustack embed # generate embeddings for semantic search
194
- argustack mcp install # connect to Claude Desktop
195
66
  ```
196
67
 
197
- ## What gets stored
198
-
199
- All data goes into local PostgreSQL in Docker on your machine (nothing leaves `localhost`):
200
-
201
- ### Jira tables
202
-
203
- | Table | Content |
204
- |-------|---------|
205
- | `issues` | All issues — typed columns + `custom_fields` JSONB + full `raw_json` |
206
- | `issue_comments` | Comments with authors and timestamps |
207
- | `issue_changelogs` | Every field change in history |
208
- | `issue_worklogs` | Time tracking entries |
209
- | `issue_links` | Issue-to-issue relationships |
210
-
211
- Every custom field is preserved exactly as Jira returns it. 500 custom fields? All stored. Zero filtering, zero data loss.
212
-
213
- ### Git tables
214
-
215
- | Table | Content |
216
- |-------|---------|
217
- | `commits` | Commit hash, message, author, email, date, full-text search |
218
- | `commit_files` | Per-file changes — path, status, additions, deletions |
219
- | `commit_issue_refs` | Cross-reference: commit ↔ Jira issue (extracted from commit messages) |
220
-
221
- Commit messages mentioning issue keys like `PROJ-123` or `PROJ-45` are automatically linked to Jira issues.
222
-
223
- ### GitHub tables
224
-
225
- Select "GitHub" during `argustack init` or add later with `argustack source add github`:
226
-
227
- | Table | Content |
228
- |-------|---------|
229
- | `pull_requests` | PRs — state, author, reviewers, additions/deletions, merge info, full-text search |
230
- | `pr_reviews` | Review approvals and change requests |
231
- | `pr_comments` | Inline review comments with file paths and line numbers |
232
- | `pr_files` | Per-file changes in each PR |
233
- | `pr_issue_refs` | Cross-reference: PR ↔ Jira issue (extracted from PR title and body) |
234
- | `releases` | GitHub releases with tags, notes, and full-text search |
235
-
236
- PR titles and bodies mentioning issue keys like `PROJ-123` are automatically linked to Jira issues — just like commits.
237
-
238
68
  ## MCP Tools
239
69
 
240
- When connected to Claude, these tools are available:
70
+ After sync, Claude queries your data through these tools:
241
71
 
242
- ### Jira tools
243
-
244
- | Tool | What it does |
245
- |------|-------------|
246
- | `query_issues` | Search issues — full-text, filters, or raw SQL |
247
- | `get_issue` | Full issue details with comments, changelogs, custom fields |
248
- | `issue_stats` | Aggregate stats — by status, type, assignee, project |
72
+ | Tool | Purpose |
73
+ |------|---------|
74
+ | `query_issues` | Search issues full-text, filters, raw SQL |
75
+ | `get_issue` | Full issue details with comments and changelogs |
76
+ | `issue_stats` | Aggregates by status, type, assignee |
249
77
  | `pull_jira` | Sync latest data from Jira |
250
- | `list_projects` | List available Jira projects |
251
-
252
- ### Git tools
253
-
254
- | Tool | What it does |
255
- |------|-------------|
256
- | `query_commits` | Search commits by text, author, date, file path, or raw SQL. Optional `repo_path` filter for multi-repo workspaces |
257
- | `issue_commits` | Cross-reference: find all commits mentioning a Jira issue key. Optional `repo_path` filter |
258
- | `commit_stats` | Aggregate stats — top authors, most changed files, linked issues. Optional `repo_path` filter |
259
-
260
- ### GitHub tools
261
-
262
- | Tool | What it does |
263
- |------|-------------|
264
- | `query_prs` | Search PRs — full-text, state, author, base branch, or raw SQL |
265
- | `issue_prs` | Cross-reference: find all PRs mentioning a Jira issue key with reviews |
266
- | `query_releases` | List releases with full-text search |
267
-
268
- ### Cross-source tools
269
-
270
- | Tool | What it does |
271
- |------|-------------|
272
- | `issue_timeline` | Chronological timeline — changelogs + commits + PRs for one issue |
273
- | `semantic_search` | Find similar issues by meaning (pgvector embeddings) |
274
- | `estimate` | Predict task duration per developer. With effort data: "without bugs" / "with bugs" predictions. With CSV only: resolution timeline in business days (lead time, not active dev) |
275
-
276
- ### System tools
277
-
278
- | Tool | What it does |
279
- |------|-------------|
78
+ | `list_projects` | Available Jira projects |
79
+ | `query_commits` | Search commits by text, author, date, file |
80
+ | `issue_commits` | All commits mentioning a Jira issue key |
81
+ | `commit_stats` | Top authors, most changed files |
82
+ | `query_prs` | Search PRs by text, state, author |
83
+ | `issue_prs` | All PRs mentioning a Jira issue key |
84
+ | `query_releases` | List releases with search |
85
+ | `issue_timeline` | Full chronological timeline: Jira + Git + GitHub |
86
+ | `semantic_search` | Find similar issues by meaning (pgvector) |
87
+ | `estimate` | Predict task duration per developer |
280
88
  | `workspace_info` | Current workspace configuration |
281
89
 
282
- ## Embeddings & Semantic Search
283
-
284
- **Embeddings** turn issue text into numerical vectors that capture meaning. Two issues about "login not working" and "SSO authentication fails" will have similar vectors — even though they share zero keywords.
285
-
286
- How it works:
287
-
288
- 1. `argustack embed` sends each issue's `summary + description` to OpenAI API (`text-embedding-3-small` model)
289
- 2. Returns a 1536-dimensional vector per issue, stored in PostgreSQL via pgvector
290
- 3. `semantic_search` MCP tool embeds your question, then finds issues with the closest vectors using cosine similarity
291
-
292
- ```bash
293
- # Generate embeddings for all issues (requires OPENAI_API_KEY in .env)
294
- argustack embed
295
- ```
296
-
297
- After embedding, ask Claude: *"Find issues similar to payment timeout errors"* — it will search by meaning, not keywords.
298
-
299
- **Costs:** text-embedding-3-small costs ~$0.02 per 1M tokens. 10,000 issues ≈ $0.05-0.10.
300
-
301
- **Optional:** Embeddings require an OpenAI API key. All other features work without it.
302
-
303
- ## GitHub token setup
304
-
305
- Argustack only reads data from GitHub — it never writes anything. You need a **fine-grained Personal Access Token** with read-only permissions.
306
-
307
- 1. Go to [github.com/settings/personal-access-tokens/new](https://github.com/settings/personal-access-tokens/new)
308
- 2. **Token name** — anything (e.g. `argustack`)
309
- 3. **Description** — optional, can leave empty
310
- 4. **Resource owner** — your account, or the organization that owns the repo
311
- 5. **Expiration** — "No expiration" recommended. Token is read-only and stays in your local `.env`
312
- 6. **Repository access** — pick one:
313
- - **Only select repositories** (recommended) — pick specific repos, max 50
314
- - **All repositories** — all your current and future repos
315
- - **Public repositories** — read-only access to public repos only
316
- 5. **Permissions** → Repository permissions (3 total):
317
-
318
- | Permission | Access | Why |
319
- |---|---|---|
320
- | **Contents** | Read-only | Releases, downloads, tags |
321
- | **Metadata** | Read-only | Repository info (auto-selected, required) |
322
- | **Pull requests** | Read-only | PRs, reviews, comments, files |
323
-
324
- 7. Click "Generate token" and copy it
325
-
326
- During `argustack init`, select "GitHub" as a source and paste the token when asked. Or add to `.env` manually:
327
-
328
- ```bash
329
- GITHUB_TOKEN=github_pat_...
330
- GITHUB_OWNER=your-org
331
- GITHUB_REPO=your-repo
332
- ```
333
-
334
- Then run `argustack source add github` and `argustack sync github`.
335
-
336
- ## Multiple workspaces
337
-
338
- Each data source = separate workspace (like git repos):
339
-
340
- ```
341
- ~/projects/
342
- ├── client-alpha/ # argustack init → Alpha's Jira + Git
343
- │ ├── .argustack/
344
- │ ├── .env # Alpha credentials
345
- │ └── docker-compose.yml
346
-
347
- ├── client-beta/ # argustack init → Beta's Jira + Git
348
- │ ├── .argustack/
349
- │ ├── .env # Beta credentials
350
- │ └── docker-compose.yml
351
- ```
352
-
353
- ## Security & Credentials
354
-
355
- **Argustack is a CLI tool. It has no backend, no cloud, no accounts.** Everything runs on your machine.
356
-
357
- When you run `argustack init`, it creates a `.env` file in your workspace with your credentials:
358
-
359
- ```bash
360
- # .env — YOUR file, on YOUR machine, never uploaded anywhere
361
-
362
- # === Jira ===
363
- JIRA_URL=https://your-team.atlassian.net
364
- JIRA_EMAIL=you@company.com
365
- JIRA_API_TOKEN=your-api-token-here
366
- JIRA_PROJECTS=PROJ,OTHER
367
-
368
- # === Git ===
369
- GIT_REPO_PATHS=/path/to/repo1,/path/to/repo2
370
-
371
- # === GitHub ===
372
- GITHUB_TOKEN=github_pat_...
373
- GITHUB_OWNER=your-org
374
- GITHUB_REPO=your-repo
375
-
376
- # === Argustack internal PostgreSQL (match docker-compose.yml) ===
377
- DB_HOST=localhost
378
- DB_PORT=5434
379
- DB_USER=argustack
380
- DB_PASSWORD=argustack_local
381
- DB_NAME=argustack
382
-
383
- # === OpenAI embeddings (optional, for semantic search) ===
384
- # OPENAI_API_KEY=sk-...
385
- ```
386
-
387
- **Where credentials go:**
388
-
389
- | What | Where | Who can see |
390
- |------|-------|-------------|
391
- | Jira token | `.env` on your disk | Only you |
392
- | GitHub token | `.env` on your disk | Only you |
393
- | Jira data | PostgreSQL in Docker on `localhost:5434` | Only you |
394
- | Git + GitHub data | PostgreSQL in Docker on `localhost:5434` | Only you |
395
- | Database password | `.env` on your disk | Only you |
396
- | Source code (this repo) | GitHub | Everyone — **no secrets here** |
397
-
398
- **What Argustack does NOT do:**
399
- - Does not send your data to any external server
400
- - Does not have analytics, telemetry, or tracking
401
- - Does not store credentials anywhere except your local `.env`
402
- - Does not require registration or accounts
403
-
404
- **`.env` is in `.gitignore`** — if you accidentally run `git add .`, your credentials won't be committed.
405
-
406
- ## Architecture — Hexagonal (Ports & Adapters)
407
-
408
- ```
409
- Driving adapters (entries): cli/, mcp/
410
- Driven adapters (external systems): adapters/jira/, adapters/git/, adapters/github/, adapters/postgres/
411
-
412
- Dependency Rule: cli/,mcp/ → use-cases/ → core/ports ← adapters/
413
- ```
414
-
415
- Core has zero dependencies — only pure TypeScript types and interfaces. Adapters implement core ports and are independently replaceable.
90
+ ## Security
416
91
 
417
- ## Tech Stack
92
+ Argustack is a CLI tool with no backend, no cloud, no accounts. Credentials stay in `.env` on your machine. Data stays in PostgreSQL on `localhost`. Nothing is uploaded anywhere.
418
93
 
419
- - TypeScript / Node.js — Hexagonal Architecture
420
- - Commander.js — CLI (driving adapter)
421
- - MCP SDK — Claude integration (driving adapter)
422
- - jira.js — Jira REST API (driven adapter)
423
- - Octokit — GitHub REST API (driven adapter)
424
- - es-git — native Git bindings, N-API, powered by libgit2 (driven adapter)
425
- - csv-parse — streaming RFC 4180 CSV parser (driven adapter)
426
- - PostgreSQL 16 + pgvector — storage + vector search (driven adapter)
427
- - Docker — database infrastructure
94
+ ## Documentation
428
95
 
429
- ## Roadmap
96
+ Full documentation available at **[Argustack DataRoom](https://app.paperlink.online/s/0aa7d2d6/argustack)**:
430
97
 
431
- - [x] Jira pull (all fields, comments, changelogs, worklogs, links)
432
- - [x] Git pull (commits, per-file diffs, issue cross-references)
433
- - [x] GitHub pull (PRs, reviews, comments, files, releases, Jira cross-references)
434
- - [x] MCP server for Claude Desktop / Claude Code (15 tools)
435
- - [x] Embeddings + semantic search (OpenAI text-embedding-3-small, pgvector)
436
- - [x] Cross-source timeline (issue_timeline: changelogs + commits + PRs)
437
- - [x] Multi-repo Git support (multiple repos per workspace, `GIT_REPO_PATHS`)
438
- - [x] Progress indicators during sync (e.g. `150/506 issues (30%)`)
439
- - [x] CSV import (Jira export without API token)
440
- - [x] Estimate tool — task duration prediction with data-source awareness
441
- - [ ] Database adapter (schema, sample data)
442
- - [ ] Cross-source analysis (Jira ticket vs actual code vs DB state)
98
+ - **Quick Start Guide** from zero to first query in 5 minutes
99
+ - **Use Cases & Examples** — real scenarios for PMs, team leads, developers, CTOs
100
+ - **MCP Tools Reference** all 15 tools with parameters and examples
101
+ - **Estimate Tool Deep Dive** algorithm, scoring, data sources
102
+ - **Architecture Guide** hexagonal architecture, directory structure, extending
443
103
 
444
104
  ## License
445
105
 
@@ -0,0 +1,13 @@
1
+ import type { Knex } from 'knex';
2
+ import type { DbEngine } from '../../core/types/database.js';
3
+ export interface DbConnectionConfig {
4
+ engine: DbEngine;
5
+ host: string;
6
+ port: number;
7
+ user: string;
8
+ password: string;
9
+ database: string;
10
+ name: string;
11
+ }
12
+ export declare function createKnexClient(config: DbConnectionConfig): Knex;
13
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAEjC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAK7D,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,QAAQ,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;CACd;AAyCD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI,CA+BjE"}
@@ -0,0 +1,70 @@
1
+ import knex from 'knex';
2
+ const STATEMENT_TIMEOUT_MS = 30_000;
3
+ const POOL_IDLE_TIMEOUT_MS = 10_000;
4
+ const ENGINE_TO_KNEX_CLIENT = {
5
+ postgresql: 'pg',
6
+ mysql: 'mysql2',
7
+ mssql: 'tedious',
8
+ sqlite: 'better-sqlite3',
9
+ oracledb: 'oracledb',
10
+ };
11
+ function buildAfterCreate(engine) {
12
+ return function afterCreate(conn, done) {
13
+ if (engine === 'postgresql') {
14
+ conn.query('SET default_transaction_read_only = true', (err) => {
15
+ if (err) {
16
+ done(err, conn);
17
+ return;
18
+ }
19
+ conn.query(`SET statement_timeout = '${String(STATEMENT_TIMEOUT_MS)}'`, (err2) => {
20
+ done(err2, conn);
21
+ });
22
+ });
23
+ }
24
+ else if (engine === 'mysql') {
25
+ conn.query('SET SESSION TRANSACTION READ ONLY', (err) => {
26
+ if (err) {
27
+ done(err, conn);
28
+ return;
29
+ }
30
+ conn.query(`SET SESSION max_execution_time = ${String(STATEMENT_TIMEOUT_MS)}`, (err2) => {
31
+ done(err2, conn);
32
+ });
33
+ });
34
+ }
35
+ else {
36
+ done(null, conn);
37
+ }
38
+ };
39
+ }
40
+ export function createKnexClient(config) {
41
+ const client = ENGINE_TO_KNEX_CLIENT[config.engine];
42
+ if (config.engine === 'sqlite') {
43
+ return knex({
44
+ client,
45
+ connection: { filename: config.database, options: { readonly: true } },
46
+ useNullAsDefault: true,
47
+ pool: { min: 0, max: 1 },
48
+ });
49
+ }
50
+ return knex({
51
+ client,
52
+ connection: {
53
+ host: config.host,
54
+ port: config.port,
55
+ user: config.user,
56
+ password: config.password,
57
+ database: config.database,
58
+ ssl: config.host !== 'localhost' && config.host !== '127.0.0.1'
59
+ ? { rejectUnauthorized: false }
60
+ : false,
61
+ },
62
+ pool: {
63
+ min: 0,
64
+ max: 2,
65
+ idleTimeoutMillis: POOL_IDLE_TIMEOUT_MS,
66
+ afterCreate: buildAfterCreate(config.engine),
67
+ },
68
+ });
69
+ }
70
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/adapters/db/client.ts"],"names":[],"mappings":"AACA,OAAO,IAAI,MAAM,MAAM,CAAC;AAGxB,MAAM,oBAAoB,GAAG,MAAM,CAAC;AACpC,MAAM,oBAAoB,GAAG,MAAM,CAAC;AAYpC,MAAM,qBAAqB,GAA6B;IACtD,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,QAAQ;IACf,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,gBAAgB;IACxB,QAAQ,EAAE,UAAU;CACrB,CAAC;AAEF,SAAS,gBAAgB,CAAC,MAAgB;IACxC,OAAO,SAAS,WAAW,CACzB,IAAkE,EAClE,IAA2C;QAE3C,IAAI,MAAM,KAAK,YAAY,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,0CAA0C,EAAE,CAAC,GAAG,EAAE,EAAE;gBAC7D,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,4BAA4B,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,EAAE;oBAC/E,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,IAAI,CAAC,KAAK,CAAC,mCAAmC,EAAE,CAAC,GAAG,EAAE,EAAE;gBACtD,IAAI,GAAG,EAAE,CAAC;oBACR,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;oBAChB,OAAO;gBACT,CAAC;gBACD,IAAI,CAAC,KAAK,CAAC,oCAAoC,MAAM,CAAC,oBAAoB,CAAC,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE;oBACtF,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;gBACnB,CAAC,CAAC,CAAC;YACL,CAAC,CAAC,CAAC;QACL,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAA0B;IACzD,MAAM,MAAM,GAAG,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEpD,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;YACV,MAAM;YACN,UAAU,EAAE,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE;YACtE,gBAAgB,EAAE,IAAI;YACtB,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;SACzB,CAAC,CAAC;IACL,CAAC;IAED,OAAO,IAAI,CAAC;QACV,MAAM;QACN,UAAU,EAAE;YACV,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,IAAI,EAAE,MAAM,CAAC,IAAI;YACjB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,GAAG,EAAE,MAAM,CAAC,IAAI,KAAK,WAAW,IAAI,MAAM,CAAC,IAAI,KAAK,WAAW;gBAC7D,CAAC,CAAC,EAAE,kBAAkB,EAAE,KAAK,EAAE;gBAC/B,CAAC,CAAC,KAAK;SACV;QACD,IAAI,EAAE;YACJ,GAAG,EAAE,CAAC;YACN,GAAG,EAAE,CAAC;YACN,iBAAiB,EAAE,oBAAoB;YACvC,WAAW,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;SAC7C;KACF,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ export { DbProvider } from './provider.js';
2
+ export { type DbConnectionConfig } from './client.js';
3
+ export { validateSql, type SqlValidationResult } from './sql-validator.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAC3C,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,KAAK,mBAAmB,EAAE,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export { DbProvider } from './provider.js';
2
+ export { validateSql } from './sql-validator.js';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/adapters/db/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,OAAO,EAAE,WAAW,EAA4B,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,31 @@
1
+ import type { DbTable, DbColumn, DbForeignKey, DbIndex } from '../../core/types/database.js';
2
+ export interface RawTableRow {
3
+ table_schema: string;
4
+ table_name: string;
5
+ }
6
+ export interface RawColumnRow {
7
+ table_name: string;
8
+ column_name: string;
9
+ data_type: string;
10
+ is_nullable: string;
11
+ column_default: string | null;
12
+ ordinal_position: number;
13
+ }
14
+ export interface RawForeignKeyRow {
15
+ table_name: string;
16
+ column_name: string;
17
+ referenced_table: string;
18
+ referenced_column: string;
19
+ }
20
+ export interface RawIndexRow {
21
+ table_name: string;
22
+ index_name: string;
23
+ column_name: string;
24
+ is_unique: boolean;
25
+ is_primary: boolean;
26
+ }
27
+ export declare function mapTableRow(row: RawTableRow, sourceName: string): Omit<DbTable, 'columns'>;
28
+ export declare function mapColumnRow(row: RawColumnRow, primaryKeys: Set<string>): DbColumn;
29
+ export declare function mapForeignKeyRow(row: RawForeignKeyRow): DbForeignKey;
30
+ export declare function mapIndexRows(rows: RawIndexRow[]): DbIndex[];
31
+ //# sourceMappingURL=mapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mapper.d.ts","sourceRoot":"","sources":["../../../src/adapters/db/mapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,OAAO,EAAE,MAAM,8BAA8B,CAAC;AAE7F,MAAM,WAAW,WAAW;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,SAAS,CAAC,CAQ1F;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,QAAQ,CAWlF;AAED,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,gBAAgB,GAAG,YAAY,CAOpE;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,OAAO,EAAE,CAyB3D"}