Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions bin/coderrr.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,14 @@ const Agent = require('../src/agent');
const configManager = require('../src/configManager');
const { getProviderChoices, getModelChoices, getProvider, validateApiKey } = require('../src/providers');
const { tryExtractJSON } = require('../src/utils');
const { runDiagnostics } = require('../src/doctorUI');
program
.command('doctor')
.description('Check your system for Coderrr compatibility')
.action(async () => {
// This calls our new UI module to run the health checks
await runDiagnostics(process.env.CODERRR_BACKEND);
});
const { displayRecipeList } = require('../src/recipeUI');
const recipeManager = require('../src/recipeManager');
const { displayInsights } = require('../src/insightsUI');
Expand Down
8 changes: 8 additions & 0 deletions docs/doctor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Coderrr Doctor

A built-in diagnostic tool to ensure your environment is ready for AI coding.

## Usage
Run the following to check your setup:
```bash
coderrr doctor
Comment on lines +5 to +8
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The documentation code block is missing a closing triple backtick, which will cause the coderrr doctor snippet to render incorrectly in many Markdown viewers. Please add a terminating code fence on a new line after the coderrr doctor command so the example displays as a proper fenced code block.

Copilot uses AI. Check for mistakes.
36 changes: 36 additions & 0 deletions src/doctor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const fs = require('fs');
const path = require('path');
const { execSync } = require('child_process');

class CoderrrDoctor {
checkEnv() {
return fs.existsSync(path.join(process.cwd(), '.env'));
}

checkPython() {
try {
const version = execSync('python --version').toString().trim();
return { status: true, version };
} catch {
return { status: false, version: 'Not found' };
}
Comment on lines +11 to +16
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

checkPython only attempts to run python --version, which will incorrectly report status: false on systems where only python3 is installed (common on many Linux distros) even though a suitable Python 3 runtime is available for the backend. To avoid false negatives in the diagnostics, consider falling back to python3 --version (and possibly py -3 --version on Windows) if the initial python invocation fails, and include which binary was detected in the version string or result payload.

Suggested change
try {
const version = execSync('python --version').toString().trim();
return { status: true, version };
} catch {
return { status: false, version: 'Not found' };
}
const candidates = ['python --version', 'python3 --version'];
if (process.platform === 'win32') {
candidates.push('py -3 --version');
}
for (const cmd of candidates) {
try {
const output = execSync(cmd).toString().trim();
const binary = cmd.split(' ')[0];
return { status: true, version: `${binary}: ${output}` };
} catch (error) {
// Try next candidate
}
}
return { status: false, version: 'Not found' };

Copilot uses AI. Check for mistakes.
}

checkNode() {
return { status: true, version: process.version };
}

async checkBackend(url) {
try {
const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 3000);
const response = await fetch(url, { signal: controller.signal });
clearTimeout(timeoutId);
return response.ok;
} catch {
return false;
}
}
}

module.exports = new CoderrrDoctor();
26 changes: 26 additions & 0 deletions src/doctorUI.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const chalk = require('chalk');
const doctor = require('./doctor');

async function runDiagnostics(backendUrl) {
console.log('\n' + chalk.blue.bold('🩺 CODERRR DOCTOR - SYSTEM DIAGNOSTICS'));
console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━'));

const python = doctor.checkPython();
const node = doctor.checkNode();
const hasEnv = doctor.checkEnv();

console.log(`${python.status ? chalk.green('✔') : chalk.red('✘')} Python: ${python.version}`);
console.log(`${node.status ? chalk.green('✔') : chalk.red('✘')} Node.js: ${node.version}`);
console.log(`${hasEnv ? chalk.green('✔') : chalk.red('✘')} Local .env file detected`);

console.log(chalk.yellow('\nChecking Backend Connectivity...'));
const backendStatus = await doctor.checkBackend(backendUrl || 'https://coderrr-backend.vercel.app');
console.log(`${backendStatus ? chalk.green('✔') : chalk.red('✘')} Backend: ${backendStatus ? 'Connected' : 'Unreachable'}`);

if (!backendStatus) {
console.log(chalk.red('\n[!] Advice: Check your internet or custom CODERRR_BACKEND variable.'));
}
console.log(chalk.gray('━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n'));
}

module.exports = { runDiagnostics };
9 changes: 9 additions & 0 deletions src/utils/doctorHelpers.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Helps format diagnostic logs for potential export
*/
const generateReport = (results) => {
return `Coderrr Diagnostic Report - ${new Date().toISOString()}\n` +
`Status: ${results.allPassed ? 'HEALTHY' : 'ISSUES DETECTED'}\n`;
};

module.exports = { generateReport };
9 changes: 9 additions & 0 deletions test/doctor.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
const doctor = require('../src/doctor');

describe('Doctor Module', () => {
test('should detect node version', () => {
const node = doctor.checkNode();
expect(node.status).toBe(true);
expect(node.version).toContain('v');
});
});
Comment on lines +3 to +9
Copy link

Copilot AI Jan 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Doctor Module tests only cover checkNode, but the new diagnostics feature also introduces checkEnv, checkPython, checkBackend, the CLI UI in doctorUI.js, and the report helper in utils/doctorHelpers.js, none of which have any tests despite other modules in this project (e.g., insights and CLI commands) having Jest coverage. To keep diagnostics reliable and prevent regressions, consider adding unit tests that exercise these additional checks (including failure paths, e.g., missing .env or unreachable backend) and at least one test around the doctor CLI command wiring.

Copilot uses AI. Check for mistakes.
Loading