@manishbht/helpcode 0.2.2

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 (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +186 -0
  3. package/dist/bin/helpcode.d.ts +5 -0
  4. package/dist/bin/helpcode.js +10 -0
  5. package/dist/bin/helpcode.js.map +1 -0
  6. package/dist/src/commands/apply.d.ts +15 -0
  7. package/dist/src/commands/apply.js +195 -0
  8. package/dist/src/commands/apply.js.map +1 -0
  9. package/dist/src/commands/ask.d.ts +12 -0
  10. package/dist/src/commands/ask.js +93 -0
  11. package/dist/src/commands/ask.js.map +1 -0
  12. package/dist/src/commands/init.d.ts +13 -0
  13. package/dist/src/commands/init.js +91 -0
  14. package/dist/src/commands/init.js.map +1 -0
  15. package/dist/src/commands/reset.d.ts +8 -0
  16. package/dist/src/commands/reset.js +19 -0
  17. package/dist/src/commands/reset.js.map +1 -0
  18. package/dist/src/commands/run.d.ts +15 -0
  19. package/dist/src/commands/run.js +109 -0
  20. package/dist/src/commands/run.js.map +1 -0
  21. package/dist/src/commands/status.d.ts +4 -0
  22. package/dist/src/commands/status.js +53 -0
  23. package/dist/src/commands/status.js.map +1 -0
  24. package/dist/src/core/llmSelector.d.ts +65 -0
  25. package/dist/src/core/llmSelector.js +134 -0
  26. package/dist/src/core/llmSelector.js.map +1 -0
  27. package/dist/src/core/ollama.d.ts +43 -0
  28. package/dist/src/core/ollama.js +128 -0
  29. package/dist/src/core/ollama.js.map +1 -0
  30. package/dist/src/core/parser.d.ts +78 -0
  31. package/dist/src/core/parser.js +273 -0
  32. package/dist/src/core/parser.js.map +1 -0
  33. package/dist/src/core/patcher.d.ts +31 -0
  34. package/dist/src/core/patcher.js +128 -0
  35. package/dist/src/core/patcher.js.map +1 -0
  36. package/dist/src/core/project.d.ts +26 -0
  37. package/dist/src/core/project.js +199 -0
  38. package/dist/src/core/project.js.map +1 -0
  39. package/dist/src/core/prompt.d.ts +19 -0
  40. package/dist/src/core/prompt.js +121 -0
  41. package/dist/src/core/prompt.js.map +1 -0
  42. package/dist/src/core/selector.d.ts +46 -0
  43. package/dist/src/core/selector.js +193 -0
  44. package/dist/src/core/selector.js.map +1 -0
  45. package/dist/src/core/state.d.ts +11 -0
  46. package/dist/src/core/state.js +63 -0
  47. package/dist/src/core/state.js.map +1 -0
  48. package/dist/src/core/tools.d.ts +32 -0
  49. package/dist/src/core/tools.js +67 -0
  50. package/dist/src/core/tools.js.map +1 -0
  51. package/dist/src/core/triage.d.ts +37 -0
  52. package/dist/src/core/triage.js +69 -0
  53. package/dist/src/core/triage.js.map +1 -0
  54. package/dist/src/index.d.ts +12 -0
  55. package/dist/src/index.js +120 -0
  56. package/dist/src/index.js.map +1 -0
  57. package/dist/src/lib/compress.d.ts +14 -0
  58. package/dist/src/lib/compress.js +35 -0
  59. package/dist/src/lib/compress.js.map +1 -0
  60. package/dist/src/lib/errors.d.ts +25 -0
  61. package/dist/src/lib/errors.js +32 -0
  62. package/dist/src/lib/errors.js.map +1 -0
  63. package/dist/src/lib/git.d.ts +7 -0
  64. package/dist/src/lib/git.js +45 -0
  65. package/dist/src/lib/git.js.map +1 -0
  66. package/dist/src/lib/runclass.d.ts +24 -0
  67. package/dist/src/lib/runclass.js +66 -0
  68. package/dist/src/lib/runclass.js.map +1 -0
  69. package/dist/src/lib/ui.d.ts +41 -0
  70. package/dist/src/lib/ui.js +92 -0
  71. package/dist/src/lib/ui.js.map +1 -0
  72. package/dist/src/types.d.ts +70 -0
  73. package/dist/src/types.js +7 -0
  74. package/dist/src/types.js.map +1 -0
  75. package/package.json +53 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 helpcode contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,186 @@
1
+ # helpcode
2
+
3
+ > A local agent that makes Claude.ai conversations efficient enough to ship real projects on a Pro subscription.
4
+
5
+ [![CI](https://github.com/merolaagi/helpcode/actions/workflows/ci.yml/badge.svg)](https://github.com/merolaagi/helpcode/actions/workflows/ci.yml)
6
+ [![npm version](https://img.shields.io/npm/v/helpcode.svg)](https://www.npmjs.com/package/helpcode)
7
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
8
+ [![Node.js](https://img.shields.io/badge/node-%3E%3D20-brightgreen)](https://nodejs.org)
9
+
10
+ helpcode is a small local CLI for developers who use Claude.ai to write code. It does the mechanical work of an AI coding loop — selecting the right files, running tests, applying diffs, capturing errors — so the conversation turns you spend on Claude get used for actual thinking.
11
+
12
+ **It does not call Claude.** You stay in Claude.ai, copy-paste with it as normal, and helpcode handles everything around that conversation. Optionally, it uses a **local model on your own machine** (via [Ollama](https://ollama.com)) to do the cheap reasoning — like working out which files matter for a task — so even that doesn't cost you a Claude turn.
13
+
14
+ ---
15
+
16
+ ## Why this exists
17
+
18
+ A year ago, you could build a real piece of software in a day or two with Claude Code. The tool was new, the usage envelope was generous, and the iteration loop was fast.
19
+
20
+ Today, Claude Code is significantly better — and significantly more in demand. Per-task pricing is fair for what you get, but at the $20/month Pro tier, a few iterations on a real codebase can consume more budget than a casual developer can sustain. Meanwhile, every routine "did the test pass?" or "which files are even relevant?" step burns frontier-model effort on work that doesn't need a frontier model.
21
+
22
+ helpcode addresses both:
23
+
24
+ - **For the developer:** each Claude conversation does more, because helpcode compresses context, structures prompts, and parses replies. One turn produces real progress instead of three turns of setup.
25
+ - **For energy and cost:** routine plumbing runs locally — on a small model on your own hardware, or as plain deterministic code — instead of in a datacenter. Claude is reserved for actual reasoning. The right tool for the right job.
26
+
27
+ This is the **two-layer model**: cheap local intelligence for the plumbing, expensive remote intelligence (Claude) for the thinking.
28
+
29
+ ---
30
+
31
+ ## What it does
32
+
33
+ Six commands. No daemons, no watchers, no background processes.
34
+
35
+ | Command | What it does |
36
+ |---|---|
37
+ | `helpcode init` | Detect your project — language, framework, test runner, and any local Ollama model — and write `.helpcode/project.json` |
38
+ | `helpcode ask "..."` | Compose a structured prompt for Claude.ai. Picks the relevant files (with a local model if available), includes last test output, and a response-format spec |
39
+ | `helpcode apply` | Paste Claude's reply; helpcode parses it, shows the planned changes, applies the diffs, runs tests |
40
+ | `helpcode run "..."` | Run any shell command, get the output in compact form (perfect for pasting back to Claude) |
41
+ | `helpcode status` | What does helpcode think the current state is? |
42
+ | `helpcode reset` | Clear state and start fresh (your code is never touched) |
43
+
44
+ ---
45
+
46
+ ## The local-model layer (optional)
47
+
48
+ If you have [Ollama](https://ollama.com) installed with a coding model pulled (e.g. `qwen2.5-coder`), `helpcode init` detects it automatically and `helpcode ask` will use it to **reason about which files are relevant** to your task — not just keyword-match them.
49
+
50
+ The difference, on a real task:
51
+
52
+ ```bash
53
+ $ helpcode ask "add a glucose variability calculation" --explain-selection
54
+ selecting files (local model: qwen2.5-coder:7b)...
55
+ ✓ selected 2 file(s) via local model
56
+ src/analyze.py — contains the time-in-range function a variability calc would extend
57
+ tests/test_analyze.py — where the new calculation's tests belong
58
+ ```
59
+
60
+ A plain keyword search would match files that literally contain "glucose." A local model understands that a *variability* calculation naturally extends the *time-in-range* function already in `analyze.py` — reasoning the keyword approach can't do.
61
+
62
+ **It never gets in the way.** If Ollama isn't installed, isn't running, times out, or returns nothing useful, helpcode silently falls back to a fast keyword heuristic. The local model is a free upgrade when present, never a dependency.
63
+
64
+ Useful flags:
65
+ - `--no-llm` — force the keyword heuristic for this run
66
+ - `--explain-selection` — show why each file was chosen
67
+
68
+ Configure the model in `.helpcode/project.json`:
69
+
70
+ ```jsonc
71
+ "ollama": {
72
+ "enabled": true,
73
+ "model": "qwen2.5-coder:7b", // or 14b / deepseek-coder-v2 for more reasoning
74
+ "host": "http://localhost:11434",
75
+ "timeoutMs": 20000
76
+ }
77
+ ```
78
+
79
+ ---
80
+
81
+ ## Install
82
+
83
+ ```bash
84
+ npm install -g helpcode
85
+ ```
86
+
87
+ Requires Node.js 20 or later. Tested on macOS, Linux, and Windows.
88
+
89
+ You don't need an API key. You don't need to sign up for anything. helpcode never calls Claude or any other remote AI service — it just helps you talk to Claude.ai more efficiently. The only optional integration is a local Ollama server on your own machine.
90
+
91
+ ---
92
+
93
+ ## A typical session
94
+
95
+ ```bash
96
+ # In your project, once:
97
+ $ helpcode init
98
+ ✓ Initialised .helpcode/project.json
99
+
100
+ Detected:
101
+ language: python
102
+ framework: Flask
103
+ source dirs: app, tests
104
+ test cmd: pytest -q --tb=short
105
+ ollama: enabled, model: qwen2.5-coder:7b
106
+
107
+ # Start a task:
108
+ $ helpcode ask "fix the login bug where uppercase emails fail"
109
+ selecting files (local model: qwen2.5-coder:7b)...
110
+ ✓ selected 2 file(s) via local model
111
+
112
+ ────────────────────────────────────────────────────────────
113
+ COPY EVERYTHING BELOW INTO CLAUDE.AI
114
+ ────────────────────────────────────────────────────────────
115
+ ## Project context
116
+ - Language: python
117
+ - Framework: Flask
118
+
119
+ ## Files (2)
120
+ ### `app/auth.py`
121
+ ... (relevant code)
122
+
123
+ ## My task
124
+ fix the login bug where uppercase emails fail
125
+
126
+ ## Please respond in this format
127
+ ...
128
+ ```
129
+
130
+ You paste that into Claude.ai. Claude replies in the structured format. You paste the reply back:
131
+
132
+ ```bash
133
+ $ helpcode apply
134
+ # (paste Claude's reply, press Ctrl-D)
135
+
136
+ Plan:
137
+ Lowercase the email before lookup in USERS.
138
+
139
+ Files to change:
140
+ • app/auth.py
141
+
142
+ Apply these changes? [y/N] y
143
+ ✓ patched app/auth.py
144
+ running: pytest tests/test_auth.py -v
145
+ Exit: 0 Time: 0.32s
146
+ 3 passed in 0.32s
147
+
148
+ ✓ Tests pass. Ready to commit when you are.
149
+ ```
150
+
151
+ Each turn with Claude does real work — no re-pasting the test output, the imports, and your Python version every time.
152
+
153
+ ---
154
+
155
+ ## What it is not
156
+
157
+ - **Not an agent that calls Claude.** No API key, no surprise costs. You stay in the loop.
158
+ - **Not a replacement for Claude Code** — which is excellent at autonomous, multi-step work. helpcode is for people who'd rather stay inside their Pro subscription.
159
+ - **Not a sandbox.** It runs your code with your normal permissions. Don't run code you don't trust.
160
+ - **Not multi-provider orchestration — yet.** Routing across several models with budget caps is the v0.3 horizon. See [`docs/ROADMAP.md`](docs/ROADMAP.md).
161
+
162
+ ---
163
+
164
+ ## Privacy
165
+
166
+ Everything stays on your machine. helpcode makes no network calls except to npm (once, during install) and — if you enable it — to a local Ollama server on `localhost`. It never sends your code to any remote service. Read [`docs/PRIVACY.md`](docs/PRIVACY.md) for the full breakdown.
167
+
168
+ The only thing that leaves your machine is whatever **you** paste into Claude.ai, which is your existing relationship with Anthropic.
169
+
170
+ ---
171
+
172
+ ## Contributing
173
+
174
+ Yes please. helpcode is small enough that the entire CLI is readable in an evening, and the architecture is explicitly designed for community evolution. Start with:
175
+
176
+ - [`CONTRIBUTING.md`](CONTRIBUTING.md) — how to set up and where to start
177
+ - [`ARCHITECTURE.md`](ARCHITECTURE.md) — the design doc this is built from
178
+ - [`docs/ROADMAP.md`](docs/ROADMAP.md) — what's planned and why
179
+
180
+ Good first issues are labelled [`good first issue`](https://github.com/merolaagi/helpcode/issues?q=label%3A%22good+first+issue%22) on the issue tracker.
181
+
182
+ ---
183
+
184
+ ## License
185
+
186
+ MIT. See [`LICENSE`](LICENSE).
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry shim for the published `helpcode` command.
4
+ */
5
+ export {};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Entry shim for the published `helpcode` command.
4
+ */
5
+ import { run } from '../src/index.js';
6
+ run(process.argv.slice(2)).then(code => process.exit(code), err => {
7
+ console.error(err);
8
+ process.exit(1);
9
+ });
10
+ //# sourceMappingURL=helpcode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpcode.js","sourceRoot":"","sources":["../../bin/helpcode.ts"],"names":[],"mappings":";AACA;;GAEG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAEtC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAC7B,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAC1B,GAAG,CAAC,EAAE;IACJ,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CACF,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `helpcode apply` — parse Claude's reply (from stdin), apply diffs,
3
+ * run the test command. Updates state with the verdict.
4
+ *
5
+ * v0.1 is intentionally conservative:
6
+ * - Shows planned changes before applying
7
+ * - Asks for confirmation (unless --yes)
8
+ * - On any diff failure, stops and reports — does NOT roll back yet
9
+ * (v0.2 will add rollback via core/rollback.ts)
10
+ */
11
+ export interface ApplyOptions {
12
+ yes?: boolean;
13
+ dryRun?: boolean;
14
+ }
15
+ export declare function handleApply(opts?: ApplyOptions): Promise<number>;
@@ -0,0 +1,195 @@
1
+ /**
2
+ * `helpcode apply` — parse Claude's reply (from stdin), apply diffs,
3
+ * run the test command. Updates state with the verdict.
4
+ *
5
+ * v0.1 is intentionally conservative:
6
+ * - Shows planned changes before applying
7
+ * - Asks for confirmation (unless --yes)
8
+ * - On any diff failure, stops and reports — does NOT roll back yet
9
+ * (v0.2 will add rollback via core/rollback.ts)
10
+ */
11
+ import * as fs from 'fs';
12
+ import * as path from 'path';
13
+ import { loadState, saveState } from '../core/state.js';
14
+ import { loadProjectConfig } from '../core/project.js';
15
+ import { parseClaudeResponse, validateParsedResponse } from '../core/parser.js';
16
+ import { applyLinePatch } from '../core/patcher.js';
17
+ import { runShellCommand } from '../core/tools.js';
18
+ import { classifyRunFailure } from '../lib/runclass.js';
19
+ import { truncateLines, extractTraceback } from '../lib/compress.js';
20
+ import { readStdin, confirm, c, log } from '../lib/ui.js';
21
+ import { HelpcodeError } from '../lib/errors.js';
22
+ export async function handleApply(opts = {}) {
23
+ const state = loadState();
24
+ if (!state.currentTask) {
25
+ log.err('No current task. Run `helpcode ask "<task>"` first.');
26
+ return 1;
27
+ }
28
+ const task = state.currentTask;
29
+ // Get Claude's response. Prefer stdin; fall back to .helpcode/response.txt.
30
+ const raw = await getResponseText();
31
+ if (!raw.trim()) {
32
+ log.err('No input received.');
33
+ log.dim('Paste Claude\'s reply and press Ctrl-D, or save it to .helpcode/response.txt first.');
34
+ return 1;
35
+ }
36
+ task.lastResponseRaw = raw;
37
+ const parsed = parseClaudeResponse(raw);
38
+ if (parsed.parseWarning) {
39
+ log.warn('Claude\'s reply doesn\'t match the expected format.');
40
+ log.dim('Helpcode expects sections like `## PLAN`, `## DIFF: <file>`, `## TEST`.');
41
+ log.dim('Save the reply, fix the format, and re-run `helpcode apply`.');
42
+ task.status = 'failed';
43
+ saveState(state);
44
+ return 1;
45
+ }
46
+ if (parsed.repairsApplied) {
47
+ log.dim('(auto-repaired copy-paste corruption in Claude\'s reply — review the plan below carefully)');
48
+ }
49
+ const issues = validateParsedResponse(parsed);
50
+ if (issues.length > 0) {
51
+ log.err('Response failed validation:');
52
+ for (const i of issues)
53
+ log.err(' ' + i);
54
+ task.status = 'failed';
55
+ saveState(state);
56
+ return 1;
57
+ }
58
+ showPlan(parsed);
59
+ if (opts.dryRun) {
60
+ log.dim('--dry-run: not applying anything.');
61
+ return 0;
62
+ }
63
+ if (!opts.yes) {
64
+ const ok = await confirm('Apply these changes?');
65
+ if (!ok) {
66
+ log.dim('Cancelled.');
67
+ return 0;
68
+ }
69
+ }
70
+ task.status = 'applying';
71
+ saveState(state);
72
+ const applied = [];
73
+ let allOk = true;
74
+ for (const diff of parsed.diffs) {
75
+ try {
76
+ const r = applyLinePatch(diff.filepath, diff.patchLines);
77
+ applied.push({
78
+ filepath: r.filepath,
79
+ hunks: r.hunksApplied,
80
+ ok: true,
81
+ created: r.created,
82
+ });
83
+ log.ok(`patched ${r.filepath}${r.created ? ' (new file)' : ''}`);
84
+ }
85
+ catch (e) {
86
+ const msg = e instanceof HelpcodeError ? e.message : e.message;
87
+ const hint = e instanceof HelpcodeError ? e.hint : '';
88
+ log.err(`failed: ${diff.filepath} — ${msg}`);
89
+ if (hint)
90
+ log.dim(' ' + hint);
91
+ applied.push({
92
+ filepath: diff.filepath,
93
+ hunks: 0,
94
+ ok: false,
95
+ created: false,
96
+ });
97
+ allOk = false;
98
+ break; // stop on first failure for v0.1
99
+ }
100
+ }
101
+ task.lastDiffsApplied = applied;
102
+ if (!allOk) {
103
+ task.status = 'failed';
104
+ saveState(state);
105
+ log.warn('Some patches failed. Files written before the failure are still on disk.');
106
+ log.dim('v0.2 will add automatic rollback. For now, use `git checkout -- <file>` or your editor\'s undo.');
107
+ return 1;
108
+ }
109
+ // Run the test command Claude suggested, or the project default
110
+ const config = loadProjectConfig();
111
+ const testCmd = parsed.testCommand ?? config.testCommand;
112
+ if (!testCmd) {
113
+ log.dim('No test command available — skipping test run.');
114
+ task.status = 'resolved';
115
+ saveState(state);
116
+ log.ok('Done.');
117
+ return 0;
118
+ }
119
+ task.status = 'testing';
120
+ saveState(state);
121
+ log.dim(`running: ${testCmd}`);
122
+ const result = await runShellCommand(testCmd, { timeoutSecs: 120 });
123
+ const testReport = formatTestReport(testCmd, result);
124
+ task.lastTestOutput = testReport;
125
+ console.log();
126
+ console.log(testReport);
127
+ if (result.exitCode === 0) {
128
+ task.status = 'resolved';
129
+ saveState(state);
130
+ console.log();
131
+ log.ok('Tests pass. Ready to commit when you are.');
132
+ return 0;
133
+ }
134
+ else {
135
+ task.status = 'failed';
136
+ saveState(state);
137
+ console.log();
138
+ const classification = classifyRunFailure(result);
139
+ if (classification.kind === 'test') {
140
+ log.warn(classification.message);
141
+ log.dim(classification.hint);
142
+ }
143
+ else {
144
+ // setup or timeout: not a Claude problem
145
+ log.warn(classification.message);
146
+ if (classification.hint)
147
+ log.dim(classification.hint);
148
+ }
149
+ return result.exitCode;
150
+ }
151
+ }
152
+ async function getResponseText() {
153
+ // If stdin is a TTY and there's a saved response, prefer that
154
+ const savedPath = path.join('.helpcode', 'response.txt');
155
+ if (process.stdin.isTTY && fs.existsSync(savedPath)) {
156
+ log.dim(`using saved response from ${savedPath}`);
157
+ return fs.readFileSync(savedPath, 'utf-8');
158
+ }
159
+ return readStdin();
160
+ }
161
+ function showPlan(parsed) {
162
+ console.log();
163
+ console.log(c.bold('Plan:'));
164
+ console.log(' ' + parsed.plan.split('\n').join('\n '));
165
+ console.log();
166
+ console.log(c.bold('Files to change:'));
167
+ for (const d of parsed.diffs) {
168
+ console.log(` ${c.cyan('•')} ${d.filepath}`);
169
+ }
170
+ if (parsed.testCommand) {
171
+ console.log();
172
+ console.log(c.bold('Test command:'));
173
+ console.log(` ${parsed.testCommand}`);
174
+ }
175
+ if (parsed.notes) {
176
+ console.log();
177
+ console.log(c.bold('Notes from Claude:'));
178
+ console.log(' ' + parsed.notes.split('\n').join('\n '));
179
+ }
180
+ }
181
+ function formatTestReport(cmd, result) {
182
+ const parts = [];
183
+ parts.push(`$ ${cmd}`);
184
+ parts.push(`Exit: ${result.exitCode} Time: ${(result.durationMs / 1000).toFixed(2)}s`);
185
+ if (result.stdout.trim()) {
186
+ parts.push('--- stdout ---');
187
+ parts.push(truncateLines(result.stdout.trimEnd(), 40, 'stdout lines'));
188
+ }
189
+ if (result.stderr.trim()) {
190
+ parts.push('--- stderr ---');
191
+ parts.push(extractTraceback(result.stderr));
192
+ }
193
+ return parts.join('\n');
194
+ }
195
+ //# sourceMappingURL=apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/commands/apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * `helpcode ask "<task>"` — assemble a structured prompt for Claude.ai
3
+ * based on the project state and selected files. Prints a paste block.
4
+ */
5
+ export interface AskOptions {
6
+ files?: string[];
7
+ /** Force the heuristic selector even if Ollama is enabled. */
8
+ noLlm?: boolean;
9
+ /** Print the reason each file was selected. */
10
+ explainSelection?: boolean;
11
+ }
12
+ export declare function handleAsk(taskDescription: string, opts?: AskOptions): Promise<number>;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * `helpcode ask "<task>"` — assemble a structured prompt for Claude.ai
3
+ * based on the project state and selected files. Prints a paste block.
4
+ */
5
+ import * as fs from 'fs';
6
+ import * as path from 'path';
7
+ import { loadProjectConfig } from '../core/project.js';
8
+ import { loadState, saveState, createTask } from '../core/state.js';
9
+ import { selectFilesWithStrategy } from '../core/selector.js';
10
+ import { buildPrompt } from '../core/prompt.js';
11
+ import { printPasteBlock, log, c } from '../lib/ui.js';
12
+ const STATE_DIR = '.helpcode';
13
+ export async function handleAsk(taskDescription, opts = {}) {
14
+ if (!taskDescription || !taskDescription.trim()) {
15
+ log.err('Usage: helpcode ask "<task description>"');
16
+ return 1;
17
+ }
18
+ const config = loadProjectConfig();
19
+ const state = loadState();
20
+ // If there's no current task, or the user is starting fresh, create one
21
+ let task = state.currentTask;
22
+ if (!task || task.status === 'resolved' || task.status === 'failed') {
23
+ task = createTask(taskDescription);
24
+ state.currentTask = task;
25
+ }
26
+ else {
27
+ task.iterations += 1;
28
+ }
29
+ // Resolve files: explicit override, else LLM-or-heuristic strategy
30
+ let selectedFiles;
31
+ if (opts.files && opts.files.length > 0) {
32
+ selectedFiles = opts.files
33
+ .map(f => path.resolve(f))
34
+ .filter(f => {
35
+ if (!fs.existsSync(f)) {
36
+ log.warn(`File not found, skipping: ${f}`);
37
+ return false;
38
+ }
39
+ return true;
40
+ });
41
+ if (opts.explainSelection) {
42
+ for (const f of selectedFiles) {
43
+ log.dim(` ${path.relative(config.root, f)} — explicitly provided via --files`);
44
+ }
45
+ }
46
+ }
47
+ else {
48
+ if (config.ollama?.enabled && !opts.noLlm) {
49
+ log.dim(`selecting files (local model: ${config.ollama.model})...`);
50
+ }
51
+ const result = await selectFilesWithStrategy(taskDescription, config, {
52
+ forceHeuristic: opts.noLlm,
53
+ });
54
+ selectedFiles = result.files.map(f => f.filepath);
55
+ if (result.strategy === 'llm') {
56
+ log.ok(`selected ${result.files.length} file(s) via local model`);
57
+ }
58
+ else if (result.fallbackReason) {
59
+ log.dim(`local-model selection unavailable (${result.fallbackReason}) — used keyword heuristic`);
60
+ }
61
+ if (opts.explainSelection) {
62
+ for (const f of result.files) {
63
+ log.dim(` ${path.relative(config.root, f.filepath)} — ${f.reason}`);
64
+ }
65
+ }
66
+ }
67
+ if (selectedFiles.length === 0) {
68
+ log.warn('No relevant files found. The prompt will contain context only.');
69
+ log.dim('Tip: pass --files <paths> to include specific files.');
70
+ }
71
+ const prompt = buildPrompt({
72
+ taskDescription,
73
+ selectedFiles,
74
+ lastTestOutput: task.lastTestOutput,
75
+ config,
76
+ });
77
+ // Persist
78
+ task.lastPrompt = prompt;
79
+ task.status = 'awaiting_paste';
80
+ saveState(state);
81
+ // Also save the prompt to a file the user can re-copy from
82
+ const pendingPath = path.join(STATE_DIR, 'pending.txt');
83
+ fs.writeFileSync(pendingPath, prompt, 'utf-8');
84
+ printPasteBlock(prompt);
85
+ console.log();
86
+ log.dim(`(saved a copy at ${pendingPath})`);
87
+ log.dim(`(~${Math.round(prompt.length / 4)} tokens approx)`);
88
+ console.log();
89
+ console.log(`${c.bold('Next:')} paste this into Claude.ai, copy the reply, then run:`);
90
+ console.log(` ${c.cyan('helpcode apply')}`);
91
+ return 0;
92
+ }
93
+ //# sourceMappingURL=ask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ask.js","sourceRoot":"","sources":["../../../src/commands/ask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `helpcode init` — detect the project, write .helpcode/project.json,
3
+ * make sure .helpcode/ is gitignored.
4
+ */
5
+ export interface InitOptions {
6
+ force?: boolean;
7
+ /**
8
+ * Skip the Ollama liveness probe. Used by tests so they never do real
9
+ * network I/O. In normal use this is always false.
10
+ */
11
+ skipOllamaDetection?: boolean;
12
+ }
13
+ export declare function handleInit(opts?: InitOptions): Promise<number>;