codehere 0.8.0 → 1.0.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.
- package/README.md +37 -184
- package/dist/application/use-cases/check-claimed-tests.js +81 -0
- package/dist/application/use-cases/detect-test-weakening.js +237 -0
- package/dist/application/use-cases/rerun-tests.js +329 -0
- package/dist/index.js +74 -1004
- package/dist/infrastructure/orchestration/artifacts-extractor.js +2 -265
- package/dist/presentation/cli/commands/check-command.js +251 -0
- package/dist/presentation/cli/commands/help-command.js +22 -286
- package/dist/ui.js +19 -438
- package/dist/utils/version.js +0 -12
- package/package.json +18 -27
- package/dist/application/use-cases/domain-trust.js +0 -110
- package/dist/application/use-cases/generate-final-report.js +0 -134
- package/dist/application/use-cases/generate-narration.js +0 -128
- package/dist/application/use-cases/generate-thread-title.js +0 -178
- package/dist/application/use-cases/narrator-prompt-template.js +0 -158
- package/dist/application/use-cases/thread-export.js +0 -155
- package/dist/application/use-cases/verify-claim.js +0 -274
- package/dist/application/use-cases/write-pass.js +0 -277
- package/dist/domain/entities/task.js +0 -61
- package/dist/domain/services/codebase-detector.js +0 -91
- package/dist/error-handler.js +0 -251
- package/dist/infrastructure/completion/bash-completion.js +0 -25
- package/dist/infrastructure/completion/fish-completion.js +0 -22
- package/dist/infrastructure/completion/zsh-completion.js +0 -30
- package/dist/infrastructure/config/config-manager.js +0 -173
- package/dist/infrastructure/config/product-context.js +0 -67
- package/dist/infrastructure/context/adapters/drawio-source.js +0 -157
- package/dist/infrastructure/context/adapters/figma-source.js +0 -163
- package/dist/infrastructure/context/adapters/github-issue-source.js +0 -159
- package/dist/infrastructure/context/adapters/linear-source.js +0 -190
- package/dist/infrastructure/context/context-resolver.js +0 -144
- package/dist/infrastructure/context/context-source.js +0 -114
- package/dist/infrastructure/context/oauth-flow.js +0 -207
- package/dist/infrastructure/context/oauth-store.js +0 -119
- package/dist/infrastructure/context/registry-bootstrap.js +0 -99
- package/dist/infrastructure/context/write-pass-resolver.js +0 -106
- package/dist/infrastructure/cost/budget-config.js +0 -113
- package/dist/infrastructure/cost/cost-router.js +0 -104
- package/dist/infrastructure/cost/spend-aggregator.js +0 -147
- package/dist/infrastructure/hooks/claude-sdk-hook.js +0 -888
- package/dist/infrastructure/hooks/hook-mode.js +0 -71
- package/dist/infrastructure/hooks/mirror-tool-call-to-audit.js +0 -43
- package/dist/infrastructure/hooks/pre-prompt-scan.js +0 -122
- package/dist/infrastructure/hooks/session-analyzer.js +0 -177
- package/dist/infrastructure/observability/execution-tracer.js +0 -227
- package/dist/infrastructure/orchestration/agent-adapter.js +0 -13
- package/dist/infrastructure/orchestration/agent-installer.js +0 -101
- package/dist/infrastructure/orchestration/agents-config-seed.js +0 -56
- package/dist/infrastructure/orchestration/aider-adapter.js +0 -447
- package/dist/infrastructure/orchestration/cassette-recorder.js +0 -120
- package/dist/infrastructure/orchestration/claude-code-adapter.js +0 -478
- package/dist/infrastructure/orchestration/codex-adapter.js +0 -538
- package/dist/infrastructure/orchestration/conductor-adapter.js +0 -377
- package/dist/infrastructure/orchestration/context-handoff.js +0 -144
- package/dist/infrastructure/orchestration/control/codex-control-surface.js +0 -99
- package/dist/infrastructure/orchestration/control/control-surface.js +0 -15
- package/dist/infrastructure/orchestration/failover-classifier.js +0 -151
- package/dist/infrastructure/orchestration/failover-config.js +0 -77
- package/dist/infrastructure/orchestration/failover-policy.js +0 -106
- package/dist/infrastructure/orchestration/gemini-adapter.js +0 -583
- package/dist/infrastructure/orchestration/generic-cli-adapter.js +0 -558
- package/dist/infrastructure/orchestration/graphify-context.js +0 -254
- package/dist/infrastructure/orchestration/memory-injector.js +0 -380
- package/dist/infrastructure/orchestration/mocks/mock-agent-repl.js +0 -233
- package/dist/infrastructure/orchestration/mocks/mock-codex-app-server.js +0 -73
- package/dist/infrastructure/orchestration/mocks/mock-synthesis.js +0 -83
- package/dist/infrastructure/orchestration/mocks/resolve-agent-spawn.js +0 -37
- package/dist/infrastructure/orchestration/opencode-adapter.js +0 -510
- package/dist/infrastructure/orchestration/progress-aggregator.js +0 -689
- package/dist/infrastructure/orchestration/readiness.js +0 -103
- package/dist/infrastructure/orchestration/session-manager.js +0 -1091
- package/dist/infrastructure/orchestration/session-persistence.js +0 -258
- package/dist/infrastructure/orchestration/thread-key-store.js +0 -127
- package/dist/infrastructure/orchestration/write-pass-store.js +0 -46
- package/dist/infrastructure/protocols/cloud-sync.js +0 -207
- package/dist/infrastructure/protocols/mcp-helpers.js +0 -25
- package/dist/infrastructure/protocols/mcp-server-impl.js +0 -2853
- package/dist/infrastructure/protocols/probe-port.js +0 -36
- package/dist/infrastructure/protocols/thread-phase.js +0 -105
- package/dist/infrastructure/protocols/ui-page-v2.js +0 -4418
- package/dist/infrastructure/protocols/ui-page.js +0 -2377
- package/dist/infrastructure/protocols/verify-page.js +0 -983
- package/dist/infrastructure/security/file-collection.js +0 -118
- package/dist/infrastructure/security/input-validator.js +0 -152
- package/dist/infrastructure/security/permissions-config.js +0 -234
- package/dist/infrastructure/security/trust-scorer.js +0 -657
- package/dist/infrastructure/storage/cross-tool-agents.js +0 -268
- package/dist/infrastructure/storage/embeddings-path.js +0 -37
- package/dist/infrastructure/storage/project-thread-migration.js +0 -237
- package/dist/infrastructure/storage/project-thread-mirror.js +0 -524
- package/dist/infrastructure/storage/project-thread-reader.js +0 -172
- package/dist/infrastructure/storage/project-thread-title-backfill.js +0 -214
- package/dist/infrastructure/storage/task-repository.js +0 -206
- package/dist/monitoring.js +0 -212
- package/dist/presentation/cli/commands/audit-command.js +0 -126
- package/dist/presentation/cli/commands/budget-command.js +0 -79
- package/dist/presentation/cli/commands/config-command.js +0 -125
- package/dist/presentation/cli/commands/context-source-command.js +0 -198
- package/dist/presentation/cli/commands/hook-command.js +0 -265
- package/dist/presentation/cli/commands/init-command.js +0 -578
- package/dist/presentation/cli/commands/memory-command.js +0 -1031
- package/dist/presentation/cli/commands/narrator-command.js +0 -101
- package/dist/presentation/cli/commands/permission-command.js +0 -116
- package/dist/presentation/cli/commands/protocols-builder.js +0 -254
- package/dist/presentation/cli/commands/protocols-command.js +0 -84
- package/dist/presentation/cli/commands/repo-map-builder.js +0 -247
- package/dist/presentation/cli/commands/report-command.js +0 -387
- package/dist/presentation/cli/commands/scan-tool-command.js +0 -94
- package/dist/presentation/cli/commands/setup-command.js +0 -307
- package/dist/presentation/cli/commands/status-command.js +0 -661
- package/dist/presentation/cli/commands/thread-command.js +0 -288
- package/dist/presentation/cli/commands/trust-command.js +0 -306
- package/dist/presentation/cli/commands/verify-command.js +0 -233
- package/dist/presentation/cli/error-display.js +0 -336
- package/dist/presentation/cli/repl.js +0 -797
- package/dist/presentation/cli/task-deliverable.js +0 -127
- package/dist/testing/cassette.js +0 -125
- package/dist/testing/replay-adapter.js +0 -166
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* CLI Command: scan-tool
|
|
3
|
-
*
|
|
4
|
-
* Reads a Claude Code PreToolUse hook event from stdin (JSON),
|
|
5
|
-
* runs Layer 0 security scan, and outputs a block/allow decision.
|
|
6
|
-
*
|
|
7
|
-
* This is the actual binary that Claude Code's hook system invokes.
|
|
8
|
-
* It must be fast (<100ms) and never crash — any failure falls through to allow.
|
|
9
|
-
*
|
|
10
|
-
* Trust-override audit (added 2026-05-06 per CC frontier Q1 — auditable
|
|
11
|
-
* permission trails): every fail-open path now writes an `overrideReason`
|
|
12
|
-
* audit entry so the audit log captures EVERY tool call, not just the ones
|
|
13
|
-
* the scanner could evaluate. Reviewers can `codehere audit --override-only`
|
|
14
|
-
* to see all cases where the safety policy didn't run normally.
|
|
15
|
-
*
|
|
16
|
-
* Usage (by hook system, not user):
|
|
17
|
-
* echo '{"hook_event_name":"PreToolUse","tool_name":"Bash","tool_input":{"command":"rm -rf /"}}' | codehere scan-tool
|
|
18
|
-
*/
|
|
19
|
-
import { processHookEvent, appendOverrideAudit, } from '../../../infrastructure/hooks/claude-sdk-hook.js';
|
|
20
|
-
export async function executeScanToolCommand(options) {
|
|
21
|
-
// Read all stdin
|
|
22
|
-
let raw = '';
|
|
23
|
-
try {
|
|
24
|
-
for await (const chunk of process.stdin) {
|
|
25
|
-
raw += chunk;
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
// If stdin read fails, allow the tool call — but log the override so
|
|
30
|
-
// the audit trail records that the scanner didn't get a chance to run.
|
|
31
|
-
appendOverrideAudit('stdin_read_failure');
|
|
32
|
-
process.exit(0);
|
|
33
|
-
}
|
|
34
|
-
if (!raw.trim()) {
|
|
35
|
-
process.exit(0);
|
|
36
|
-
}
|
|
37
|
-
// Parse event JSON
|
|
38
|
-
let event;
|
|
39
|
-
try {
|
|
40
|
-
event = JSON.parse(raw);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
// Malformed JSON — allow by default (fail open for dev experience).
|
|
44
|
-
// We still record the override with a truncated copy of the raw payload
|
|
45
|
-
// so reviewers can see what arrived (helps diagnose hook misconfiguration).
|
|
46
|
-
appendOverrideAudit('event_parse_failure', {
|
|
47
|
-
toolInput: raw.substring(0, 500),
|
|
48
|
-
});
|
|
49
|
-
if (options.debug) {
|
|
50
|
-
process.stderr.write('[codehere] Warning: could not parse hook event JSON\n');
|
|
51
|
-
}
|
|
52
|
-
process.exit(0);
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
const decision = processHookEvent(event);
|
|
56
|
-
if (options.logOnly) {
|
|
57
|
-
// Log-only mode: never block, but log everything. If the scanner WOULD
|
|
58
|
-
// have blocked, record the override so the audit shows scanner intent
|
|
59
|
-
// vs actual outcome. Without this, --log-only mode produces an audit
|
|
60
|
-
// trail indistinguishable from a clean session.
|
|
61
|
-
if (decision?.decision === 'block') {
|
|
62
|
-
appendOverrideAudit('log_only_mode', {
|
|
63
|
-
sessionId: event.session_id,
|
|
64
|
-
toolName: event.tool_name,
|
|
65
|
-
});
|
|
66
|
-
if (options.debug) {
|
|
67
|
-
process.stderr.write(`[codehere] Would block: ${decision.reason}\n`);
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
process.exit(0);
|
|
71
|
-
}
|
|
72
|
-
if (decision?.decision === 'block') {
|
|
73
|
-
// Output block decision as JSON (Claude Code hook contract)
|
|
74
|
-
process.stdout.write(JSON.stringify(decision) + '\n');
|
|
75
|
-
// Also write to stderr for user visibility
|
|
76
|
-
process.stderr.write(`\n${decision.reason}\n`);
|
|
77
|
-
process.exit(2); // non-zero exit = Claude Code treats as block signal
|
|
78
|
-
}
|
|
79
|
-
// Allow — exit 0 with no output
|
|
80
|
-
process.exit(0);
|
|
81
|
-
}
|
|
82
|
-
catch {
|
|
83
|
-
// Any scan failure: fail open (allow), never break developer workflow.
|
|
84
|
-
// Record the override so the audit trail shows the scanner crashed for
|
|
85
|
-
// this tool call — reviewers can correlate with the timestamp to find
|
|
86
|
-
// the underlying error.
|
|
87
|
-
appendOverrideAudit('scan_exception', {
|
|
88
|
-
sessionId: event.session_id,
|
|
89
|
-
toolName: event.tool_name,
|
|
90
|
-
});
|
|
91
|
-
process.exit(0);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
//# sourceMappingURL=scan-tool-command.js.map
|
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Setup Wizard Command
|
|
3
|
-
* Interactive first-time setup for Codehere
|
|
4
|
-
* Checks environment, API keys, and guides users through configuration
|
|
5
|
-
*/
|
|
6
|
-
import { readFileSync, existsSync, writeFileSync, mkdirSync } from 'fs';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
import { getConfigManager } from '../../../infrastructure/config/config-manager.js';
|
|
9
|
-
import { colors, separator, newline, sectionHeader, success, error, warning, info } from '../../../ui.js';
|
|
10
|
-
import { executionTracer } from '../../../infrastructure/observability/execution-tracer.js';
|
|
11
|
-
import { findCodebaseRoot } from '../../../domain/services/codebase-detector.js';
|
|
12
|
-
import { readinessForAllAgents } from '../../../infrastructure/orchestration/session-manager.js';
|
|
13
|
-
/**
|
|
14
|
-
* What codehere actually needs to run a task: at least one coding-agent CLI
|
|
15
|
-
* that's installed AND signed in. Most engineers have `claude` or `codex`
|
|
16
|
-
* logged in by subscription with no API key set, so framing setup around
|
|
17
|
-
* `ANTHROPIC_API_KEY` told them they were blocked when they weren't. This
|
|
18
|
-
* reuses the same readiness check that powers the web dashboard's squad bar.
|
|
19
|
-
*/
|
|
20
|
-
function summarizeAgents() {
|
|
21
|
-
let all;
|
|
22
|
-
try {
|
|
23
|
-
all = readinessForAllAgents();
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
all = [];
|
|
27
|
-
}
|
|
28
|
-
return { ready: all.filter((a) => a.state === 'ready'), all };
|
|
29
|
-
}
|
|
30
|
-
/** One status line per agent, plain English. Used by both the TTY wizard and
|
|
31
|
-
* the non-TTY summary so they say the same thing. */
|
|
32
|
-
function printAgentLines(all) {
|
|
33
|
-
for (const a of all) {
|
|
34
|
-
if (a.state === 'ready') {
|
|
35
|
-
console.log(success(`${a.label}: ready`));
|
|
36
|
-
}
|
|
37
|
-
else if (a.state === 'needs_auth') {
|
|
38
|
-
const hint = a.authHint?.command ? colors.dim(` (sign in: ${a.authHint.command})`) : '';
|
|
39
|
-
console.log(warning(`${a.label}: installed, needs sign-in`) + hint);
|
|
40
|
-
}
|
|
41
|
-
else if (a.state === 'billed_key_required') {
|
|
42
|
-
console.log(colors.dim(`○ ${a.label}: needs a billed API key (paid)`));
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
const hint = a.installHint?.command ? colors.dim(` (install: ${a.installHint.command})`) : '';
|
|
46
|
-
console.log(colors.dim(`○ ${a.label}: not installed`) + hint);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Check if any API key is configured
|
|
52
|
-
*/
|
|
53
|
-
function checkAPIKey() {
|
|
54
|
-
const providers = [
|
|
55
|
-
{ env: 'ANTHROPIC_API_KEY', name: 'Anthropic' },
|
|
56
|
-
{ env: 'OPENAI_API_KEY', name: 'OpenAI' },
|
|
57
|
-
{ env: 'COHERE_API_KEY', name: 'Cohere' },
|
|
58
|
-
{ env: 'OPENROUTER_API_KEY', name: 'OpenRouter' },
|
|
59
|
-
];
|
|
60
|
-
for (const { env, name } of providers) {
|
|
61
|
-
const key = process.env[env];
|
|
62
|
-
if (key && key.trim() && !key.includes('your_key_here') && key.length > 10) {
|
|
63
|
-
return { configured: true, provider: name, key };
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
return { configured: false };
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Detect codebase type and root
|
|
70
|
-
*/
|
|
71
|
-
function detectCodebase() {
|
|
72
|
-
const cwd = process.cwd();
|
|
73
|
-
// Check for common project indicators
|
|
74
|
-
const indicators = {
|
|
75
|
-
node: ['package.json'],
|
|
76
|
-
python: ['requirements.txt', 'setup.py', 'pyproject.toml'],
|
|
77
|
-
rust: ['Cargo.toml'],
|
|
78
|
-
go: ['go.mod'],
|
|
79
|
-
java: ['pom.xml', 'build.gradle'],
|
|
80
|
-
};
|
|
81
|
-
for (const [type, files] of Object.entries(indicators)) {
|
|
82
|
-
for (const file of files) {
|
|
83
|
-
if (existsSync(join(cwd, file))) {
|
|
84
|
-
return { detected: true, type, root: cwd };
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
return { detected: false, root: cwd };
|
|
89
|
-
}
|
|
90
|
-
/**
|
|
91
|
-
* Detect preferred model from config
|
|
92
|
-
*/
|
|
93
|
-
function detectModel() {
|
|
94
|
-
try {
|
|
95
|
-
const configPath = join(process.cwd(), 'data', 'model-config.json');
|
|
96
|
-
if (existsSync(configPath)) {
|
|
97
|
-
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
98
|
-
return config.preferredModel || config.modelFamily || null;
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
// Ignore errors
|
|
103
|
-
}
|
|
104
|
-
return null;
|
|
105
|
-
}
|
|
106
|
-
/**
|
|
107
|
-
* Create config directory if needed
|
|
108
|
-
*/
|
|
109
|
-
function ensureConfigDir() {
|
|
110
|
-
const configDir = join(process.cwd(), 'data');
|
|
111
|
-
if (!existsSync(configDir)) {
|
|
112
|
-
mkdirSync(configDir, { recursive: true });
|
|
113
|
-
}
|
|
114
|
-
return configDir;
|
|
115
|
-
}
|
|
116
|
-
/**
|
|
117
|
-
* Save setup configuration
|
|
118
|
-
*/
|
|
119
|
-
function saveSetupConfig(result) {
|
|
120
|
-
const configDir = ensureConfigDir();
|
|
121
|
-
const configPath = join(configDir, 'setup-config.json');
|
|
122
|
-
const config = {
|
|
123
|
-
setupComplete: true,
|
|
124
|
-
setupDate: new Date().toISOString(),
|
|
125
|
-
apiKeyConfigured: result.apiKeyConfigured,
|
|
126
|
-
modelDetected: result.modelDetected,
|
|
127
|
-
codebaseDetected: result.codebaseDetected,
|
|
128
|
-
};
|
|
129
|
-
writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
130
|
-
}
|
|
131
|
-
/**
|
|
132
|
-
* Check if setup has been completed before
|
|
133
|
-
*/
|
|
134
|
-
function isSetupComplete() {
|
|
135
|
-
try {
|
|
136
|
-
const configPath = join(process.cwd(), 'data', 'setup-config.json');
|
|
137
|
-
if (existsSync(configPath)) {
|
|
138
|
-
const config = JSON.parse(readFileSync(configPath, 'utf-8'));
|
|
139
|
-
return config.setupComplete === true;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
catch {
|
|
143
|
-
// Ignore errors
|
|
144
|
-
}
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
/**
|
|
148
|
-
* Execute setup wizard
|
|
149
|
-
*/
|
|
150
|
-
export async function executeSetupCommand(force = false) {
|
|
151
|
-
// Check for interactive terminal
|
|
152
|
-
const isTTY = process.stdin.isTTY && process.stdout.isTTY;
|
|
153
|
-
if (!isTTY) {
|
|
154
|
-
const { ready, all } = summarizeAgents();
|
|
155
|
-
console.log(colors.bold('Setup'));
|
|
156
|
-
console.log();
|
|
157
|
-
if (all.length)
|
|
158
|
-
printAgentLines(all);
|
|
159
|
-
console.log();
|
|
160
|
-
if (ready.length) {
|
|
161
|
-
console.log(success(`You're ready. ${ready[0].label} is set up.`));
|
|
162
|
-
console.log(colors.dim(' Next: codehere start (open the dashboard)'));
|
|
163
|
-
}
|
|
164
|
-
else {
|
|
165
|
-
console.log(warning('No coding agent is set up yet. Install or sign in to one:'));
|
|
166
|
-
console.log(colors.cyan(' npm i -g @anthropic-ai/claude-code') + colors.dim(' then run: claude (sign in)'));
|
|
167
|
-
console.log(colors.dim(' Already use one by API key? export ANTHROPIC_API_KEY=sk-ant-...'));
|
|
168
|
-
}
|
|
169
|
-
return;
|
|
170
|
-
}
|
|
171
|
-
// Start execution tracing
|
|
172
|
-
const codebaseInfo = findCodebaseRoot(process.cwd());
|
|
173
|
-
executionTracer.startRun('setup', {
|
|
174
|
-
codebaseId: codebaseInfo?.rootPath || process.cwd(),
|
|
175
|
-
});
|
|
176
|
-
try {
|
|
177
|
-
const isFirstTime = !isSetupComplete() || force;
|
|
178
|
-
newline();
|
|
179
|
-
console.log(colors.bold('Setup'));
|
|
180
|
-
newline();
|
|
181
|
-
// Check if already set up
|
|
182
|
-
if (!force && isSetupComplete()) {
|
|
183
|
-
console.log(info('Setup has already been completed.'));
|
|
184
|
-
newline();
|
|
185
|
-
console.log(colors.dim('Run with --force to reconfigure.'));
|
|
186
|
-
newline();
|
|
187
|
-
return;
|
|
188
|
-
}
|
|
189
|
-
const result = {
|
|
190
|
-
apiKeyConfigured: false,
|
|
191
|
-
modelDetected: null,
|
|
192
|
-
codebaseDetected: false,
|
|
193
|
-
configPath: join(process.cwd(), 'data'),
|
|
194
|
-
};
|
|
195
|
-
// Step 1: Coding agents — codehere drives agent CLIs, not raw API keys.
|
|
196
|
-
sectionHeader('Step 1: Your coding agents');
|
|
197
|
-
const { ready, all } = summarizeAgents();
|
|
198
|
-
if (all.length)
|
|
199
|
-
printAgentLines(all);
|
|
200
|
-
newline();
|
|
201
|
-
const apiKeyCheck = checkAPIKey();
|
|
202
|
-
if (ready.length) {
|
|
203
|
-
console.log(success(`You're ready. ${ready[0].label} is set up.`));
|
|
204
|
-
result.apiKeyConfigured = true; // at least one agent can spawn right now
|
|
205
|
-
}
|
|
206
|
-
else if (apiKeyCheck.configured) {
|
|
207
|
-
// No agent CLI ready, but a key is present — some adapters (e.g. Aider) run off it.
|
|
208
|
-
console.log(success(`${apiKeyCheck.provider} API key found.`));
|
|
209
|
-
console.log(colors.dim(' No agent CLI detected yet — install one for the full experience.'));
|
|
210
|
-
result.apiKeyConfigured = true;
|
|
211
|
-
}
|
|
212
|
-
else {
|
|
213
|
-
console.log(warning('No coding agent is set up yet.'));
|
|
214
|
-
newline();
|
|
215
|
-
console.log(colors.bold('Install or sign in to at least one:'));
|
|
216
|
-
console.log(colors.cyan(' npm i -g @anthropic-ai/claude-code') + colors.dim(' then run: claude (sign in)'));
|
|
217
|
-
console.log(colors.dim(' Already use one by API key? export ANTHROPIC_API_KEY=sk-ant-...'));
|
|
218
|
-
newline();
|
|
219
|
-
}
|
|
220
|
-
newline();
|
|
221
|
-
// Step 2: Model Detection
|
|
222
|
-
sectionHeader('Step 2: Model Configuration');
|
|
223
|
-
const model = detectModel();
|
|
224
|
-
if (model) {
|
|
225
|
-
console.log(success(`Preferred Model: ${model}`));
|
|
226
|
-
result.modelDetected = model;
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
console.log(info('Model: Using default (Claude Sonnet)'));
|
|
230
|
-
console.log(colors.dim(' Configurable via .codehere/providers.json'));
|
|
231
|
-
result.modelDetected = 'Claude Sonnet (default)';
|
|
232
|
-
}
|
|
233
|
-
newline();
|
|
234
|
-
// Step 3: Codebase Detection
|
|
235
|
-
sectionHeader('Step 3: Codebase Detection');
|
|
236
|
-
const codebase = detectCodebase();
|
|
237
|
-
if (codebase.detected) {
|
|
238
|
-
console.log(success(`Codebase: Detected (${codebase.type})`));
|
|
239
|
-
console.log(colors.dim(` Root: ${codebase.root}`));
|
|
240
|
-
result.codebaseDetected = true;
|
|
241
|
-
}
|
|
242
|
-
else {
|
|
243
|
-
console.log(warning('Codebase: Not detected'));
|
|
244
|
-
console.log(colors.dim(" Make sure you're in your project directory."));
|
|
245
|
-
result.codebaseDetected = false;
|
|
246
|
-
}
|
|
247
|
-
newline();
|
|
248
|
-
// Step 4: Summary
|
|
249
|
-
sectionHeader('Setup Summary');
|
|
250
|
-
const summaryItems = [
|
|
251
|
-
['API Key', result.apiKeyConfigured ? success('Configured') : error('Not Configured')],
|
|
252
|
-
['Model', result.modelDetected || info('Default')],
|
|
253
|
-
['Codebase', result.codebaseDetected ? success('Detected') : warning('Not Detected')],
|
|
254
|
-
];
|
|
255
|
-
summaryItems.forEach(([label, status]) => {
|
|
256
|
-
console.log(` ${label.padEnd(15)} ${status}`);
|
|
257
|
-
});
|
|
258
|
-
newline();
|
|
259
|
-
// Step 5: Save Configuration
|
|
260
|
-
if (result.apiKeyConfigured) {
|
|
261
|
-
const configManager = getConfigManager();
|
|
262
|
-
// Update codebase info if detected
|
|
263
|
-
if (codebase.detected) {
|
|
264
|
-
configManager.updateCodebase(codebase.root);
|
|
265
|
-
}
|
|
266
|
-
// Update model preference if detected
|
|
267
|
-
if (model) {
|
|
268
|
-
configManager.setPreference('defaultModel', model.replace(' (default)', ''));
|
|
269
|
-
}
|
|
270
|
-
// Save configuration
|
|
271
|
-
configManager.saveConfig();
|
|
272
|
-
result.configPath = configManager.getConfigPath();
|
|
273
|
-
newline();
|
|
274
|
-
console.log(success('Done.'));
|
|
275
|
-
newline();
|
|
276
|
-
console.log(colors.bold('Next steps:'));
|
|
277
|
-
console.log(colors.dim(` 1. ${colors.cyan('codehere start')} Open the task intake at :3773`));
|
|
278
|
-
console.log(colors.dim(` 2. ${colors.cyan('codehere hook install')} Audit every Claude Code action`));
|
|
279
|
-
console.log(colors.dim(` 3. ${colors.cyan('codehere trust .')} Scan your project (no API key)`));
|
|
280
|
-
newline();
|
|
281
|
-
saveSetupConfig(result);
|
|
282
|
-
// Track onboarding completion for first-time users
|
|
283
|
-
if (isFirstTime) {
|
|
284
|
-
const onboardingConfig = {
|
|
285
|
-
onboardingComplete: true,
|
|
286
|
-
onboardingDate: new Date().toISOString(),
|
|
287
|
-
commandCount: 0, // Will be tracked by feature discovery
|
|
288
|
-
};
|
|
289
|
-
const onboardingPath = join(ensureConfigDir(), 'onboarding.json');
|
|
290
|
-
writeFileSync(onboardingPath, JSON.stringify(onboardingConfig, null, 2));
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
else {
|
|
294
|
-
console.log(separator('═', 80));
|
|
295
|
-
console.log(warning('Setup Incomplete'));
|
|
296
|
-
console.log(separator('═', 80));
|
|
297
|
-
newline();
|
|
298
|
-
console.log(colors.bold('Please configure your API key to continue.'));
|
|
299
|
-
console.log(colors.dim('Run this command again after setting up your API key.'));
|
|
300
|
-
newline();
|
|
301
|
-
}
|
|
302
|
-
}
|
|
303
|
-
finally {
|
|
304
|
-
executionTracer.endRun();
|
|
305
|
-
}
|
|
306
|
-
}
|
|
307
|
-
//# sourceMappingURL=setup-command.js.map
|