Skip to content

feat: add Coderrr Insights dashboard for productivity tracking and Skills for better workflow#123

Merged
Akash-nath29 merged 6 commits intodevfrom
feature
Jan 30, 2026
Merged

feat: add Coderrr Insights dashboard for productivity tracking and Skills for better workflow#123
Akash-nath29 merged 6 commits intodevfrom
feature

Conversation

@Akash-nath29
Copy link
Owner

This pull request introduces several major improvements to Coderrr, focusing on enhanced command execution, robust file operation rules, and expanded documentation for project customization and insights. The most significant updates include running shell commands in separate terminal windows to keep Coderrr responsive, enforcing strict rules for file patching (especially to protect critical configuration files), and providing detailed user documentation for customizing project behavior and tracking coding insights.

Command Execution and Process Management

  • Shell commands are now executed in separate terminal windows using executeInSeparateTerminal, preventing long-running or blocking commands from freezing Coderrr. The agent tracks running processes and ensures they are properly cleaned up on exit, improving stability and user experience. (src/agent.js [1] [2]
  • The agent now maintains a list of completed steps during plan execution, passing this context to the self-healing logic to avoid repeating actions or referencing deleted files. (src/agent.js [1] [2] [3] [4]

File Operation Safety and Rules

  • Strict protection is added for configuration files: Coderrr.md, Skills.md, and the .coderrr/ directory—these can never be deleted, even if the user requests a full cleanup. (backend/main.py [1] [2]
  • The rules for patch_file actions are clarified and enforced: the old content must be an exact match from the file, and the agent must always read the file before patching. Guidance is provided on when to use update_file versus patch_file to preserve user code. (backend/main.py [1] [2]

Documentation and User Guidance

  • A new Project Customization section is added to the README, explaining how to use Skills.md and Coderrr.md for persistent and task-specific instructions, as well as how cross-session memory works. (README.md [1] [2] [3]
  • A new docs/insights-guide.md document is introduced, detailing how users can view analytics and productivity statistics for their Coderrr sessions. (docs/insights-guide.md docs/insights-guide.mdR1-R14)

User Experience Improvements

  • The README and execution flow are updated to clarify that command execution happens in separate terminals, and the agent remains responsive during long-running commands. (README.md [1] [2]
  • The file patching method in src/fileOps.js is documented to support fuzzy matching and normalization, reducing errors due to line ending or whitespace differences. (src/fileOps.js src/fileOps.jsR140-R145)

These changes collectively make Coderrr safer, more robust, and easier to customize for advanced users, while also improving the reliability of file operations and command execution.

Copilot AI review requested due to automatic review settings January 30, 2026 19:23
@vercel
Copy link

vercel bot commented Jan 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
coderrr-backend Ready Ready Preview, Comment Jan 30, 2026 7:23pm

@github-actions
Copy link

🚀 Thanks for opening a Pull Request!

A maintainer will review this soon.

Meanwhile:
✔ Ensure tests are passing
✔ Link related issues
✔ Code follows the project guidelines

Your contribution helps make this project better!

@Akash-nath29 Akash-nath29 merged commit fe0831c into dev Jan 30, 2026
35 checks passed
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adds an Insights dashboard and metrics plumbing, strengthens file operation safety and backend planning rules, and updates command execution to run in separate terminals so Coderrr stays responsive. It also introduces project customization docs (Skills.md, Coderrr.md, and memory) and wires a new coderrr insights CLI command plus a basic Jest test for the insights module.

Changes:

  • Implemented an InsightsManager with insightsUI and a new coderrr insights CLI subcommand, plus a Jest test for recording sessions.
  • Enhanced command execution via executeInSeparateTerminal (Windows/macOS/Linux) and added process tracking/cleanup in Agent, while tightening file patching semantics and documentation in both the backend system prompt and fileOps.
  • Expanded README and added docs/insights-guide.md to document project customization, cross-session memory, and how to view insights; bumped package version to 1.1.1.

Reviewed changes

Copilot reviewed 11 out of 13 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
test/test-custom-prompt.js Fixes the Agent require path so the custom prompt test imports the correct module.
test/insights.test.js Adds a Jest test that exercises insights.recordSession/getStats but currently writes to the real ~/.coderrr/insights.json.
src/utils/metrics.js Introduces a calculateSavings helper for estimating time saved from sessions, though it is not yet used anywhere.
src/insightsUI.js Implements a Chalk-based terminal dashboard to display totals and recent sessions from the insights store.
src/insights.js Adds InsightsManager that persists sessions and aggregate totals to ~/.coderrr/insights.json with basic rotation.
src/fileOps.js Documents and implements more flexible patching (line-ending normalization and fuzzy line-by-line matching) while enforcing protected paths for Coderrr config.
src/executor.js Extends the command executor with executeInSeparateTerminal plus OS-specific terminal spawners and monitoring/termination utilities, and keeps legacy plan execution helpers.
src/agent.js Tracks processes started in separate terminals for cleanup on exit and passes completed step context into self-healing prompts, updating validation for fixed steps.
package-lock.json Updates the lockfile to version 1.1.1 and syncs dependency metadata with package.json.
docs/insights-guide.md New guide describing Coderrr Insights features and instructing users to run coderrr insights to open the dashboard.
bin/coderrr.js Wires a new insights subcommand that invokes displayInsights, leaving existing CLI commands untouched.
backend/main.py Strengthens system instructions with protected file rules, explicit patch_file guidance, and an expanded JSON schema including oldContent/newContent.
README.md Documents separate terminal execution, Skills/Coderrr customization, and cross-session memory behaviors to align with the new functionality.

end tell
`;

exec(`osascript -e '${appleScript}'`, (error, stdout, stderr) => {
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 AppleScript command construction here is likely to break on macOS because the script is passed to osascript inside single quotes, but the script itself contains single-quoted path values (e.g. '${shellScript}', '${pidFile}'). When expanded, this results in unescaped single quotes inside a single-quoted shell string, causing the osascript -e '...' invocation to fail. To make this robust, either avoid single quotes inside the AppleScript string (use escaped double quotes for paths) or change how the script is passed to osascript so that path values are properly escaped for the surrounding shell quoting.

Suggested change
exec(`osascript -e '${appleScript}'`, (error, stdout, stderr) => {
const osaCommand = `osascript -e ${JSON.stringify(appleScript)}`;
exec(osaCommand, (error, stdout, stderr) => {

Copilot uses AI. Check for mistakes.
Comment on lines +12 to +36
const calculateSavings = (sessions) => {
if (!sessions || sessions.length === 0) return "0 minutes";

// We estimate that each file operation or self-healing fix
// saves a developer roughly 10 minutes of manual work.
const ESTIMATED_MINS_SAVED_PER_ACTION = 10;

const totalActions = sessions.reduce((acc, session) => {
const fileOps = session.filesChanged || 0;
const healings = session.healings || 0;
return acc + fileOps + healings;
}, 0);

const totalMinutes = totalActions * ESTIMATED_MINS_SAVED_PER_ACTION;

if (totalMinutes >= 60) {
const hours = (totalMinutes / 60).toFixed(1);
return `${hours} hours`;
}

return `${totalMinutes} minutes`;
};

module.exports = {
calculateSavings
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.

This new metrics utility is not referenced anywhere in the codebase, so calculateSavings is effectively dead code right now. Either integrate it into the insights dashboard (e.g., to show estimated time saved) or remove the file until it is actually used, to keep the utils folder from accumulating unused helpers.

Suggested change
const calculateSavings = (sessions) => {
if (!sessions || sessions.length === 0) return "0 minutes";
// We estimate that each file operation or self-healing fix
// saves a developer roughly 10 minutes of manual work.
const ESTIMATED_MINS_SAVED_PER_ACTION = 10;
const totalActions = sessions.reduce((acc, session) => {
const fileOps = session.filesChanged || 0;
const healings = session.healings || 0;
return acc + fileOps + healings;
}, 0);
const totalMinutes = totalActions * ESTIMATED_MINS_SAVED_PER_ACTION;
if (totalMinutes >= 60) {
const hours = (totalMinutes / 60).toFixed(1);
return `${hours} hours`;
}
return `${totalMinutes} minutes`;
};
module.exports = {
calculateSavings
// Placeholder: metrics helpers can be added here when integrated
// into the insights dashboard or other parts of the application.
module.exports = {
// Intentionally empty: add metrics utilities here when used.

Copilot uses AI. Check for mistakes.
Comment on lines +1 to +10
const insights = require('../src/insights');
const fs = require('fs');

describe('Insights Module', () => {
test('should record and retrieve a session', () => {
const initialTasks = insights.getStats().totals.tasks;
insights.recordSession({ task: 'Test Task', success: true, filesChanged: 2, healings: 1 });
const updatedStats = insights.getStats();
expect(updatedStats.totals.tasks).toBe(initialTasks + 1);
});
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.

This Jest test writes to the real ~/.coderrr/insights.json file and never cleans it up, which means running the test suite mutates the user's actual insights data and makes the test dependent on prior runs. It would be better to make the storage path configurable (e.g., via an environment variable or DI) so tests can point insights at a temporary directory, and then clean up any test data; also note that the imported fs module is not used and can be removed.

Copilot uses AI. Check for mistakes.

// Start monitoring output if requested
let outputWatcher = null;
let lastReadPosition = 0;
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.

Unused variable lastReadPosition.

Suggested change
let lastReadPosition = 0;

Copilot uses AI. Check for mistakes.
ui.info('The terminal window will show the command output.');
} else {
const errorMsg = result.error || 'Unknown error';
stepResult = `Failed to start command: "${step.command}". Error: ${errorMsg}`;
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 value assigned to stepResult here is unused.

Suggested change
stepResult = `Failed to start command: "${step.command}". Error: ${errorMsg}`;

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +205
let terminalProcess = null;
let childPid = null;

try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
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 value assigned to terminalProcess here is unused.

Suggested change
let terminalProcess = null;
let childPid = null;
try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
let childPid = null;
try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +205
let terminalProcess = null;
let childPid = null;

try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
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 value assigned to terminalProcess here is unused.

Suggested change
let terminalProcess = null;
let childPid = null;
try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
let childPid = null;
try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +205
let terminalProcess = null;
let childPid = null;

try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
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 value assigned to terminalProcess here is unused.

Suggested change
let terminalProcess = null;
let childPid = null;
try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);
terminalProcess = result.process;
let childPid = null;
try {
if (platform === 'win32') {
// Windows: Use start command with cmd.exe
const result = await this.spawnWindowsTerminal(normalizedCommand, cwd, outputFile, pidFile);
childPid = result.pid;
} else if (platform === 'darwin') {
// macOS: Use osascript to open Terminal.app
const result = await this.spawnMacTerminal(normalizedCommand, cwd, outputFile, pidFile);
childPid = result.pid;
} else {
// Linux: Try gnome-terminal, konsole, or xterm
const result = await this.spawnLinuxTerminal(normalizedCommand, cwd, outputFile, pidFile);

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Comments