Skip to content

bring in agent backends#1

Open
odilitime wants to merge 5 commits into1.xfrom
odi-dev
Open

bring in agent backends#1
odilitime wants to merge 5 commits into1.xfrom
odi-dev

Conversation

@odilitime
Copy link
Member

@odilitime odilitime commented Jan 30, 2026

Summary by CodeRabbit

  • New Features

    • Multiple AI coding agents (Claude Code, Cursor, Aider, Codex, OpenCode, native) with auto-detection and selectable modes
    • Workspace management for multi-environment support
    • Real-time execution status tracking and per-task progress
    • Agent performance stats and failure-lesson tracking
  • Documentation

    • Expanded README with capabilities, configuration, usage examples, and orchestrator integration guide
    • New workspace and orchestrator integration docs

✏️ Tip: You can customize this high-level summary in your review settings.

odilitime and others added 2 commits January 30, 2026 01:02
Guidelines for plugin-code dev to add CODE_EXECUTION_STATUS provider
to enable better progress tracking when used with plugin-orchestrator.

Co-authored-by: Cursor <cursoragent@cursor.com>
Major feature addition transforming plugin-code into a comprehensive
AI coding toolkit.

## New AI Agent System
- AgentRegistry service for managing multiple coding agents
- Native agent: Uses elizaOS LLM + file actions (always available)
- CLI agents: Claude Code, Cursor, Aider, Codex, OpenCode
- Auto-detection of installed CLI tools
- CODE_MODE setting: auto | native | cli

## New Actions
- CODE: Universal entry point using best available agent
- CLAUDE_CODE, CURSOR, AIDER, CODEX, OPENCODE: Direct agent access
- DETECT_AGENTS: List available coding agents
- VIEW_LESSONS: Show failure history
- SHOW_STATS: Show agent performance metrics

## Learning & Stats (PRR Features)
- LessonsService: Track failures and learn patterns
- StatsService: Monitor agent performance over time
- On-disk persistence in .plugin-code/ directory

## Providers (Dynamic Multi-Resolution)
- CODE_HELP: Usage instructions for agent guidance
- CODE_SETTINGS: Current configuration (non-sensitive)
- CODE_EXECUTION_STATUS: Real-time execution tracking for orchestrator
- CODE_AGENTS: Agent availability (3 resolutions)
- CODE_LESSONS: Failure history (3 resolutions)
- CODE_STATS: Performance metrics (3 resolutions)

## Progressive Enhancement
- Integrates with plugin-workspace for active workspace path
- Delegates git operations to plugin-git when available
- GIT action suggests using plugin-git for better auth/security

## Why These Changes
- Unified entry point (CODE) simplifies user experience
- Multiple agents give flexibility and fallback options
- Learning from failures improves over time
- Execution tracking enables smart orchestrator integration
- Multi-resolution providers balance context vs token usage

Co-authored-by: Cursor <cursoragent@cursor.com>
Copilot AI review requested due to automatic review settings January 30, 2026 01:07
@coderabbitai
Copy link

coderabbitai bot commented Jan 30, 2026

Walkthrough

This PR adds a multi-agent code toolkit: multiple CLI/native coding agents, an AgentRegistry for discovery/selection, execution tracking and CODE_EXECUTION_STATUS providers, lessons and stats persistence services, workspace management docs, new provider surfaces, many agent actions, and a refactored plugin init that wires services and providers at startup.

Changes

Cohort / File(s) Summary
Documentation
ORCHESTRATOR_INTEGRATION.md, README.md, WORKSPACES.md
Adds orchestrator integration guide, expanded README (features, config, usage, architecture), and comprehensive workspace management spec.
Package & Config
package.json
Adds uuid dependency and new public config ELIZA_WORKSPACES_ROOT; minor plugin metadata text change.
Plugin Entrypoint
src/index.ts
Refactors plugin init: progressive enhancement, agent registration (native + CLI detection), service/provider registration, and broad public re-exports.
Agent Registry & Agents
src/services/agentRegistry.service.ts, src/services/agents/..., src/services/agents/index.ts
New AgentRegistry singleton, registerAgentWithDetection, and six agent implementations (Native, ClaudeCode, Cursor, Aider, Codex, OpenCode) plus utilities (execCommand, commandExists, etc.).
Execution Tracking & Types
src/services/executionTracker.service.ts, src/types/execution.ts, src/types/index.ts
New ExecutionTrackerService with per-conversation state, phases, action history, and execution types + idle factory.
Lessons & Stats Services
src/services/lessons.service.ts, src/services/stats.service.ts
New LessonsService and StatsService with persistence, query APIs, CSV export, and lifecycle hooks.
Providers
src/providers/executionStatus.provider.ts, src/providers/agents.providers.ts, src/providers/lessons.providers.ts, src/providers/stats.providers.ts, src/providers/settings.provider.ts, src/providers/help.provider.ts, src/providers/index.ts
Multi-resolution dynamic providers for execution status, agents list/overviews, lessons, stats, settings snapshot, and help text; organized re-exports.
Actions: Agents & PRR
src/actions/agents/..., src/actions/prr/*, src/actions/agents/index.ts, src/actions/index.ts
Adds CODE and per-agent actions (code, claudeCode, cursor, aider, codex, opencode, detectAgents) with availability checks and execution flows; PRR actions (viewLessons, showStats); barrel exports.
Action & Minor Changes
src/actions/editFile.ts, src/actions/git.ts
Small formatting tweak in editFile; git action gets fallback logging recommending plugin-git for auth-sensitive ops.
CoderService & Path Utils
src/services/coderService.ts, src/utils/pathUtils.ts
CoderService: progressive getAllowedDirectory using workspace when available and current-directory adjustments; minor pathUtils reflow.
Service Exports
src/services/index.ts
Adds exports for AgentRegistry, ExecutionTrackerService, LessonsService, StatsService, agent implementations, and utilities.
New Files / Large Additions
src/providers/*, src/services/*, src/actions/agents/*, docs...
Numerous new modules (providers, services, agents, actions) introducing runtime-visible classes, providers, and actions — review these for API shape and initialization ordering.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Action as CODE Action
    participant Registry as AgentRegistry
    participant Tracker as ExecutionTrackerService
    participant Agent as ICodingAgent
    participant Coder as CoderService

    User->>Action: invoke CODE action (prompt)
    Action->>Registry: query available agents / CODE_MODE
    Registry-->>Action: selected agent
    Action->>Tracker: startExecution(conversationId, agent)
    Action->>Agent: execute(prompt, projectPath, conversationId)
    Agent->>Coder: check status / read/write files
    Agent->>Agent: run CLI or LLM prompt
    Agent-->>Action: return AgentResult (success, modifiedFiles, output)
    Action->>Tracker: recordFileWrite / recordFileRead / updatePhase
    Action->>Tracker: completeExecution(conversationId, success)
    Action-->>User: return result and modified files
Loading
sequenceDiagram
    participant Plugin
    participant Runtime
    participant Registry as AgentRegistry
    participant Detection as CLI Detection
    participant Native as NativeAgent

    Plugin->>Registry: getInstance()
    Plugin->>Registry: register(Native)
    Plugin->>Detection: detect CLI agents (claude, cursor, aider...)
    Detection-->>Plugin: availability results
    Plugin->>Registry: registerAgentWithDetection(name, agent, cliCmd)
    Registry-->>Plugin: registration stored (isAvailable flag)
    Plugin->>Runtime: register ExecutionTrackerService, LessonsService, StatsService
    Plugin-->>Runtime: initialization complete
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~110 minutes

Poem

🐰 I hopped through files, with agents in tow,

Six CLI pals and one native to show,
Registry hums, trackers mark each stride,
Lessons and stats keep the lessons wide,
A toolkit blooms — many voices, one flow.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'bring in agent backends' accurately describes the main change: introducing multiple AI coding agent implementations (Claude Code, Cursor, Aider, Codex, OpenCode, Native) and their integration infrastructure into the codebase.
Docstring Coverage ✅ Passed Docstring coverage is 84.62% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch odi-dev

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Major feature addition transforming plugin-code into a comprehensive
AI coding toolkit.

## New AI Agent System
- AgentRegistry service for managing multiple coding agents
- Native agent: Uses elizaOS LLM + file actions (always available)
- CLI agents: Claude Code, Cursor, Aider, Codex, OpenCode
- Auto-detection of installed CLI tools
- CODE_MODE setting: auto | native | cli

## New Actions
- CODE: Universal entry point using best available agent
- CLAUDE_CODE, CURSOR, AIDER, CODEX, OPENCODE: Direct agent access
- DETECT_AGENTS: List available coding agents
- VIEW_LESSONS: Show failure history
- SHOW_STATS: Show agent performance metrics

## Learning & Stats (PRR Features)
- LessonsService: Track failures and learn patterns
- StatsService: Monitor agent performance over time
- On-disk persistence in .plugin-code/ directory

## Providers (Dynamic Multi-Resolution)
- CODE_HELP: Usage instructions for agent guidance
- CODE_SETTINGS: Current configuration (non-sensitive)
- CODE_EXECUTION_STATUS: Real-time execution tracking for orchestrator
- CODE_AGENTS: Agent availability (3 resolutions)
- CODE_LESSONS: Failure history (3 resolutions)
- CODE_STATS: Performance metrics (3 resolutions)

## Progressive Enhancement
- Integrates with plugin-workspace for active workspace path
- Delegates git operations to plugin-git when available
- GIT action suggests using plugin-git for better auth/security

## Why These Changes
- Unified entry point (CODE) simplifies user experience
- Multiple agents give flexibility and fallback options
- Learning from failures improves over time
- Execution tracking enables smart orchestrator integration
- Multi-resolution providers balance context vs token usage

Co-authored-by: Cursor <cursoragent@cursor.com>
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 brings AI coding agent backend support to plugin-code, transforming it from a simple file operations toolkit into a comprehensive AI-assisted coding platform. The PR adds support for multiple AI coding agents (Native, Claude Code, Cursor, Aider, Codex, OpenCode) with centralized registry management, execution tracking, performance statistics, and failure learning capabilities.

Changes:

  • Adds 6 AI coding agent implementations (Native agent using elizaOS LLM, plus 5 CLI-based agents)
  • Implements AgentRegistry service for centralized agent management and discovery
  • Adds ExecutionTrackerService for real-time execution status tracking (orchestrator integration)
  • Adds StatsService and LessonsService for performance tracking and failure learning
  • Introduces 14 new actions (CODE action as main entry point, specific agent actions, stats/lessons actions)
  • Adds 13 new dynamic providers with multi-resolution context (overview, default, full)
  • Enhances CoderService with progressive workspace integration support

Reviewed changes

Copilot reviewed 43 out of 43 changed files in this pull request and generated 14 comments.

Show a summary per file
File Description
src/types/execution.ts New execution status types for tracking agent progress and actions
src/types/index.ts Exports new execution types
src/services/executionTracker.service.ts Tracks code execution status per conversation with phase, progress, file activity
src/services/stats.service.ts Tracks agent performance statistics, stores to .plugin-code/stats.json
src/services/lessons.service.ts Records coding failures for learning, stores to .plugin-code/lessons.json
src/services/agentRegistry.service.ts Singleton registry for agent discovery, registration, and selection
src/services/coderService.ts Enhanced with optional workspace integration support via getAllowedDirectory
src/services/agents/*.agent.ts 6 agent implementations (Native, ClaudeCode, Cursor, Aider, Codex, OpenCode)
src/services/agents/utils.ts Shared utilities for CLI execution, binary detection, error classification
src/services/agents/index.ts Exports all agents and utilities
src/actions/agents/*.ts 7 new actions: CODE (main), CLAUDE_CODE, CURSOR, AIDER, CODEX, OPENCODE, DETECT_AGENTS
src/actions/prr/*.ts 2 new actions: VIEW_LESSONS, SHOW_STATS for performance review
src/actions/index.ts Exports all new actions
src/actions/git.ts Enhanced with plugin-git integration hints and progressive enhancement
src/actions/editFile.ts Minor formatting cleanup
src/providers/executionStatus.provider.ts 3-resolution provider for execution status (orchestrator visibility)
src/providers/agents.providers.ts 3-resolution provider for agent availability
src/providers/lessons.providers.ts 3-resolution provider for failure history
src/providers/stats.providers.ts 3-resolution provider for performance stats
src/providers/help.provider.ts Usage instructions provider
src/providers/settings.provider.ts Configuration status provider
src/providers/index.ts Exports all providers
src/interfaces/ICodingAgent.ts Core interface for coding agents, minor formatting fix
src/index.ts Plugin initialization with agent registration and comprehensive exports
src/utils/pathUtils.ts Minor formatting cleanup
package.json Adds uuid dependency (unused), adds ELIZA_WORKSPACES_ROOT setting
README.md Comprehensive documentation update covering new features
ORCHESTRATOR_INTEGRATION.md Integration guidelines for plugin-orchestrator
WORKSPACES.md Workspace management documentation (misplaced - not part of this PR)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

private static instance: AgentRegistry;
private agents: Map<string, AgentRegistration> = new Map();

private constructor() { }
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 empty space in the constructor creates inconsistent code style. While not functionally harmful, it's better to either remove the space or use proper formatting.

Suggested change
private constructor() { }
private constructor() {}

Copilot uses AI. Check for mistakes.

// Get CODE_MODE setting
const mode = (runtime.getSetting('CODE_MODE') as string) || 'auto';
const conversationId = message.roomId;
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 conversationId is directly assigned from message.roomId which could be undefined. This could cause issues in downstream services that expect a string. Consider providing a fallback value similar to how it's done in NativeCoderAgent line 71: const conversationId = params.conversationId || 'default' or use message.roomId ?? runtime.agentId.

Suggested change
const conversationId = message.roomId;
const conversationId = message.roomId ?? runtime.agentId;

Copilot uses AI. Check for mistakes.
return { success: false, error: 'Claude Code not available' };
}

const conversationId = message.roomId;
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.

Same issue as in the CODE action: message.roomId could be undefined, leading to potential runtime errors. Use a fallback value like message.roomId ?? runtime.agentId to ensure conversationId is always a string.

Suggested change
const conversationId = message.roomId;
const conversationId = message.roomId ?? runtime.agentId;

Copilot uses AI. Check for mistakes.
return { success: false, error: 'Aider not available' };
}

const conversationId = message.roomId;
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.

Same issue as in other agent actions: message.roomId could be undefined. Use a fallback value like message.roomId ?? runtime.agentId.

Suggested change
const conversationId = message.roomId;
const conversationId = message.roomId ?? runtime.agentId;

Copilot uses AI. Check for mistakes.
return { success: false, error: 'Codex not available' };
}

const conversationId = message.roomId;
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.

Same issue as in other agent actions: message.roomId could be undefined. Use a fallback value like message.roomId ?? runtime.agentId.

Suggested change
const conversationId = message.roomId;
const conversationId = message.roomId ?? runtime.agentId;

Copilot uses AI. Check for mistakes.
Comment on lines 1 to 388
# Workspace Management in plugin-code

## Overview

The workspace system provides a managed directory structure for working with any codebase - git repos, archives, or local projects. Similar to GitHub Codespaces or Replit, it handles cloning, extracting, and organizing projects in a secure, isolated manner.

## Architecture

```
~/.eliza-workspaces/
├── .metadata/
│ ├── workspaces.json # Registry of all workspaces
│ └── <workspace-id>.json # Per-workspace metadata (future)
├── facebook-react/ # Cloned from git
├── my-python-project/ # Extracted from zip
├── local-experiment/ # Created locally
└── nextjs-app-2025/ # Another project
```

## Key Features

### 🌐 Multiple Source Types
- **Git Clone**: Clone any repository from GitHub, GitLab, Bitbucket, etc.
- **Archive Import**: Extract from .zip or .tar.gz URLs
- **Local Creation**: Create empty workspace for new projects
- **Future**: Symlink support for development mode

### 🔒 Security Model
- Each conversation/session is locked to ONE active workspace at a time
- `CODER_ALLOWED_DIRECTORY` automatically set to active workspace path
- All file/shell operations restricted to current workspace
- Parent directory (`~/.eliza-workspaces/`) cannot be accessed by agents

### 📊 Auto-Detection
Workspaces automatically detect:
- **Languages**: JavaScript, TypeScript, Python, Rust, Go
- **Frameworks**: React, Next.js, Vue, ElizaOS
- **Package Managers**: bun, npm, yarn, pnpm, cargo, go, pip

## Configuration

### Environment Variables

```bash
# Workspace root directory (optional - defaults shown)
ELIZA_WORKSPACES_ROOT=~/.eliza-workspaces

# Strict mode - enforce workspace directory constraint
# When true, CODER_ALLOWED_DIRECTORY must be inside workspaces root
ELIZA_WORKSPACES_STRICT=false

# Legacy config still works
CODER_ENABLED=true
CODER_ALLOWED_DIRECTORY=/path/to/project # Auto-set from active workspace
```

### Character File

```json
{
"plugins": ["@elizaos/plugin-code"],
"settings": {
"CODER_ENABLED": true,
"ELIZA_WORKSPACES_ROOT": "~/.eliza-workspaces"
}
}
```

## Usage

### Creating Workspaces

**From Git Repository:**
```
"Clone https://github.com/facebook/react"
"Clone the Next.js repo from GitHub"
"Import https://github.com/user/repo branch develop"
```

**From Archive:**
```
"Import project from https://example.com/project.zip"
"Extract this archive: https://example.com/app.tar.gz"
```

**Local Workspace:**
```
"Create local workspace named my-project"
"Create a new workspace called test-app"
```

### Managing Workspaces

**List All Workspaces:**
```
"Show me all workspaces"
"List workspaces"
```

**Switch Workspace:**
```
"Switch to workspace react"
"Use the my-project workspace"
```

**Delete Workspace:**
```
"Delete workspace old-project yes delete"
"Remove workspace test yes delete"
```

⚠️ **Note**: Deletion requires explicit "yes delete" confirmation

### Working with Files

Once a workspace is active, all existing file operations work within that workspace:

```
"Read the package.json file"
"List files in src/"
"Edit app.js and change..."
"Run npm install"
```

## Integration with CoderService

The `CoderService` automatically integrates with `WorkspaceService`:

```typescript
// CoderService checks for active workspace first
getAllowedDirectory(conversationId) {
const workspaceService = runtime.getService('workspace');
const activeWorkspace = workspaceService.getActiveWorkspace(conversationId);

if (activeWorkspace) {
return activeWorkspace.path; // Use workspace path
}

return this.coderConfig.allowedDirectory; // Fallback to config
}
```

## Actions Reference

### CREATE_WORKSPACE
Creates a new workspace from various sources.

**Triggers:** `CLONE_REPO`, `IMPORT_PROJECT`, `NEW_WORKSPACE`, `SETUP_PROJECT`

**Examples:**
- `"Clone https://github.com/facebook/react"`
- `"Create workspace from https://example.com/project.zip"`
- `"Create local workspace named my-project"`

### LIST_WORKSPACES
Lists all available workspaces with details.

**Triggers:** `SHOW_WORKSPACES`, `WORKSPACES`, `LIST_PROJECTS`

**Shows:**
- Workspace name and path
- Source (git URL, archive URL, or local)
- Framework and language detection
- Last accessed time
- Active status

### SWITCH_WORKSPACE
Switches to a different workspace.

**Triggers:** `USE_WORKSPACE`, `CHANGE_WORKSPACE`, `ACTIVATE_WORKSPACE`

**Example:** `"Switch to workspace react"`

### DELETE_WORKSPACE
Permanently deletes a workspace.

**Triggers:** `REMOVE_WORKSPACE`, `DESTROY_WORKSPACE`

**Example:** `"Delete workspace old-project yes delete"`

⚠️ **Requires confirmation**: Must include "yes delete" in the request

## Providers

### WORKSPACE_STATUS
Provides information about the current workspace state.

**Includes:**
- Active workspace name and path
- Source information (git/archive/local)
- Detected framework and languages
- Package manager
- List of other available workspaces

**Used by:** Agent prompts to understand current working context

## API Reference

### WorkspaceService

```typescript
// Create workspace from git
const workspace = await workspaceService.createFromGit(repoUrl, {
branch: 'main', // optional
name: 'my-repo' // optional
});

// Create from archive
const workspace = await workspaceService.createFromArchive(archiveUrl, {
name: 'my-project' // optional
});

// Create local workspace
const workspace = await workspaceService.createLocal('project-name');

// Get active workspace
const workspace = workspaceService.getActiveWorkspace(conversationId);

// Set active workspace
await workspaceService.setActiveWorkspace(conversationId, workspaceId);

// List all workspaces
const workspaces = workspaceService.listWorkspaces();

// Delete workspace
await workspaceService.deleteWorkspace(workspaceId);
```

## Workspace Data Structure

```typescript
interface Workspace {
id: string; // Unique UUID
name: string; // Display name
path: string; // Absolute filesystem path
source: {
type: 'git' | 'zip' | 'local' | 'symlink';
url?: string; // Original source URL
branch?: string; // Git branch (if git)
commit?: string; // Git commit hash (if git)
};
created: Date;
lastAccessed: Date;
active: boolean; // Currently active?
metadata: {
language?: string[]; // Detected languages
framework?: string; // Detected framework
packageManager?: string; // Detected package manager
};
}
```

## Migration from Existing Setup

If you're currently using `CODER_ALLOWED_DIRECTORY`:

**Option 1: Keep Existing Behavior**
```bash
# Don't set ELIZA_WORKSPACES_ROOT - continues using CODER_ALLOWED_DIRECTORY
CODER_ENABLED=true
CODER_ALLOWED_DIRECTORY=/path/to/my/project
```

**Option 2: Migrate to Workspaces**
```bash
# Set workspaces root
ELIZA_WORKSPACES_ROOT=~/.eliza-workspaces

# Create workspace from existing project (symlink coming soon)
# For now: copy or clone project into ~/.eliza-workspaces/
cp -r /path/to/my/project ~/.eliza-workspaces/my-project
```

Then in chat: `"Switch to workspace my-project"`

## Future Enhancements

- **Symlink Support**: Link to existing directories without copying
- **Workspace Templates**: Pre-configured project templates
- **Collaborative Workspaces**: Share workspace state across agents
- **Automatic Cleanup**: Archive old/unused workspaces
- **Git Integration**: Auto-update, branch management, PR creation
- **Resource Limits**: Disk space quotas per workspace
- **Workspace Snapshots**: Save/restore workspace state

## Examples

### Complete Workflow

```
User: "Clone the React repository"
Agent: 🔄 Cloning repository from https://github.com/facebook/react...
Agent: ✅ Workspace created and activated!
**react**
📂 Path: `~/.eliza-workspaces/react`
🔗 Source: git (https://github.com/facebook/react)
🎯 Framework: React
📝 Languages: javascript, typescript
📦 Package Manager: yarn

User: "List all files in src/"
Agent: [Lists React source files...]

User: "Run yarn install"
Agent: [Executes yarn install in workspace...]

User: "Switch to my other project"
Agent: [Shows list of workspaces...]

User: "Create a new workspace called test-app"
Agent: 📁 Creating local workspace "test-app"...
Agent: ✅ Workspace created!

User: "Create index.js with hello world"
Agent: [Creates file in test-app workspace...]
```

## Troubleshooting

### Workspace Not Found
```
Error: Workspace "xyz" not found
```
**Solution**: Run `"List workspaces"` to see available workspaces

### Git Clone Failed
```
Error: Failed to clone repository
```
**Common causes:**
- Invalid URL
- Private repository without authentication
- Network issues

**Solution**: Ensure URL is public or configure Git credentials

### Out of Disk Space
```
Error: ENOSPC: no space left on device
```
**Solution**: Delete unused workspaces:
```
"Delete workspace old-project yes delete"
```

### Path Access Denied
```
Error: Cannot access path outside allowed directory
```
**Explanation**: Security feature - all operations restricted to active workspace

**Solution**: Ensure you're working within the current workspace or switch workspaces

## Security Considerations

1. **Directory Isolation**: Agents cannot access files outside active workspace
2. **Parent Directory Protection**: `~/.eliza-workspaces/` root is not accessible
3. **Command Restrictions**: All `CODER_FORBIDDEN_COMMANDS` still apply
4. **Git Authentication**: Credentials should be configured at OS level, not in agent
5. **Archive Sources**: Only download from trusted URLs

## Best Practices

1. **Naming**: Use descriptive, lowercase names with hyphens
2. **Organization**: Group related workspaces by project/client
3. **Cleanup**: Regularly delete unused workspaces
4. **Git Repos**: Prefer cloning over uploading archives for better version control
5. **Large Files**: Avoid workspaces with >1GB of files (performance)

## Comparison to Other Tools

| Feature | Eliza Workspaces | GitHub Codespaces | Replit | VS Code Dev Containers |
|---------|------------------|-------------------|--------|------------------------|
| **Chat Interface** | ✅ | ❌ | ❌ | ❌ |
| **Git Clone** | ✅ | ✅ | ✅ | ✅ |
| **Archive Import** | ✅ | ❌ | ✅ | ❌ |
| **Local Creation** | ✅ | ❌ | ✅ | ✅ |
| **Auto-Detection** | ✅ | ✅ | ✅ | ✅ |
| **Multi-Workspace** | ✅ | ✅ | ✅ | ❌ |
| **Offline Mode** | ✅ | ❌ | ❌ | ✅ |
| **AI Coding Agents** | ✅ | ❌ | ❌ | ❌ |

---

**Need Help?** Ask your agent:
- `"How do workspaces work?"`
- `"Show me workspace commands"`
- `"What workspace am I in?"`
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 WORKSPACES.md file appears to describe workspace management functionality that is not part of this PR. The file mentions "WorkspaceService" and workspace-related actions (CREATE_WORKSPACE, LIST_WORKSPACES, etc.) which are not included in the changes. This documentation file seems misplaced and should either be removed or moved to the correct PR/repository.

Copilot uses AI. Check for mistakes.
return { success: false, error: 'Cursor not available' };
}

const conversationId = message.roomId;
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.

Same issue as in other agent actions: message.roomId could be undefined. Use a fallback value like message.roomId ?? runtime.agentId.

Suggested change
const conversationId = message.roomId;
const conversationId = message.roomId ?? runtime.agentId;

Copilot uses AI. Check for mistakes.
// Get project root from CoderService
const coderService = runtime.getService<CoderService>('coder');
if (coderService) {
const projectRoot = coderService.getAllowedDirectory();
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 getAllowedDirectory() method signature was changed to accept an optional conversationId parameter, but this call doesn't provide it. This could cause issues if workspace integration is active since the method may return the wrong directory. Consider passing a conversationId or using a method that doesn't require workspace context for initialization.

Copilot uses AI. Check for mistakes.
}

async execute(params: ExecuteParams, runtime: IAgentRuntime): Promise<AgentResult> {
const taskId = params.conversationId || 'unknown';
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 taskId.

Suggested change
const taskId = params.conversationId || 'unknown';

Copilot uses AI. Check for mistakes.
// Force native agent
const nativeReg = registry.get('native');
if (nativeReg?.isAvailable) {
agentName = 'native';
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 agentName here is unused.

Copilot uses AI. Check for mistakes.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 16

🤖 Fix all issues with AI agents
In `@ORCHESTRATOR_INTEGRATION.md`:
- Around line 29-202: Replace the old CoderService examples with the actual
ExecutionTrackerService API: in the codeExecutionStatusProvider sample and agent
snippets, get the service via
runtime.getService<ExecutionTrackerService>('executionTracker') and call the
real methods (e.g., getExecutionStatus / updateExecutionStatus) rather than
coderService.getExecutionStatus/updateStatus; switch phase/string values to the
real ExecutionPhase enums (including starting, completing, error) instead of
'idle'|'planning'|'reading'|'writing'|'verifying'; replace nullable/legacy
fields with the actual ExecutionStatus shape from src/types/execution.ts
(include actionHistory instead of recentActions, adjust timing/identifier fields
to match the type), and update NativeCoderAgent.execute and
ClaudeCodeAgent.execute examples to call
ExecutionTrackerService.updateExecutionStatus with the new phase values and
actionHistory updates when parsing CLI output.
- Around line 238-243: The Markdown table separator row in
ORCHESTRATOR_INTEGRATION.md is missing spaces around the pipe characters which
violates markdownlint MD060; update the separator row between the header and
body so each pipe has a single space before and after it (i.e., change
"|---------------|-------------|" to use " | " spacing consistent with the
header and rows), ensuring the separator aligns with the header columns for the
table shown under the "Without Status | With Status" heading.

In `@README.md`:
- Around line 145-168: Update the ASCII art fenced code blocks in README.md to
include a language identifier (use "text") to satisfy markdownlint MD040;
specifically add ```text at the start of the CODE_MODE diagram and the
plugin-code diagram (the blocks containing the "User: 'fix the bug in utils.ts'
... Check CODE_MODE" flow and the "plugin-code ├── Services ..." tree) so both
diagrams declare a language instead of bare ``` fences.
- Around line 37-54: The markdown tables in README (e.g., rows with headers like
CODER_ENABLED, CODER_ALLOWED_DIRECTORY and CODE_MODE, CODE_CLAUDE_MODEL, etc.)
have inconsistent pipe spacing triggering MD060; update each table to use a
consistent pipe-spacing style (for example, single space before and after each
cell delimiter) across all tables (including the sections you noted and the ones
at lines ~76-105, 110-123, 131-142) by normalizing the pipe spacing or running
the project's markdown formatter so every cell follows the same " | cell | "
pattern.

In `@src/providers/executionStatus.provider.ts`:
- Around line 87-97: The forEach callbacks on status.filesRead and
status.filesWritten currently use concise arrow expressions that implicitly
return the result of lines.push(...) which triggers the Biome lint error; change
those callbacks to use block bodies (or replace with a for...of loop) and call
lines.push(...) as a statement (no return value) so the callback does not return
anything—update the two occurrences that iterate over status.filesRead and
status.filesWritten and ensure you still push the same formatted strings (e.g.,
`  - ${f}`) into the lines array.

In `@src/services/agentRegistry.service.ts`:
- Around line 326-356: The parseAgentFromInput function builds one giant
alternation regex from all aliases which can lead to ReDoS; fix it by avoiding
the combined alternation: iterate each agent (this.agents) and then each
name/alias, escape the alias (as already done), and construct/test a small
per-name RegExp like
`\\b(?:using|with|via|in|on)\\s+(?:the\\s+)?${escapedName}(?:\\s+agent)?\\b` or,
even safer, perform tokenized string checks (split lowerText into words and
verify a preposition token precedes the candidate name) instead of one large
regex; additionally, add validation when registering aliases (reject very long
strings or disallow unescaped regex metacharacters) in the registration code to
prevent attacker-controlled patterns from entering the registry.

In `@src/services/agents/aider.agent.ts`:
- Around line 143-145: The call to classifyError(output) in the failure branch
is unused; either remove it or surface its return value: capture const
classification = classifyError(output) and include it in the failure handling
(for example append classification to the logger.error message or set an error
variable used downstream), or simply delete the classifyError(output) invocation
if classification isn't needed; update the block around result.exitCode,
classifyError, and logger.error to reflect the chosen approach (use
classifyError’s return value in the log or remove the call).

In `@src/services/agents/codex.agent.ts`:
- Around line 50-54: The regex literals in isCursorPositionError are flagged by
Biome for control characters; replace the literal regexes with RegExp
constructors using escaped string patterns to preserve behavior. Specifically,
change the ANSI-strip and control-char replaces to use new RegExp(...) with the
same patterns and 'g' flag (e.g., pattern for "\x1b\[[0-9;]*[a-zA-Z]" and for
"[\x00-\x1f]" expressed as escaped strings) and replace the final test regex
with new
RegExp('cursor.{0,10}position.{0,10}could.{0,10}not.{0,10}be.{0,10}read', 'i')
so lint noControlCharactersInRegex is satisfied while keeping function
isCursorPositionError's behavior unchanged.

In `@src/services/agents/opencode.agent.ts`:
- Around line 134-138: The returned result in opencode.agent.ts currently always
sets modifiedFiles: [] which misreports edits; update the function that returns
this object in opencode.agent.ts so modifiedFiles is either removed until
implemented or populated from git (e.g., capture changed paths via a git
diff/name-only call or a library like simple-git) and include those paths in the
modifiedFiles array before returning the result object; locate the return block
that emits success, modifiedFiles, output and replace the empty array with the
computed file list (or omit the key entirely).
- Around line 78-80: The debug/info logs in OpenCodeAgent are printing raw
prompt content (logger.info and logger.debug in the method that executes tasks),
which risks leaking secrets; change the logging in the OpenCodeAgent execution
method to avoid printing the raw params.prompt — instead log non-sensitive
metadata such as prompt length, a fixed mask or a one-way hash (e.g., SHA256) of
the prompt, and context like params.projectPath and task id; update the
logger.debug call that currently uses params.prompt.substring(...) to emit only
the safe summary/hash or "prompt redacted" so no plaintext prompt is written to
logs.
- Around line 101-118: The current invocation builds args and calls
execCommand(OPENCODE_BINARY, args, { stdin: params.prompt }) which is wrong for
OpenCode: change the args to include the "run" subcommand and pass the prompt as
a positional argument (after "--" or as the last arg) instead of via stdin
(replace use of stdin param), and ensure the model value (from params.model or
runtime.getSetting('CODE_OPENCODE_MODEL')) is normalized to the required
provider/model format before pushing it as "--model"; update usage of
OPENCODE_BINARY, args, execCommand, params.prompt, params.model, and
isValidModelName to implement these changes.

In `@src/services/coderService.ts`:
- Around line 327-333: searchInDirectory is using
this.coderConfig.allowedDirectory to compute relative file paths, causing
inconsistency when a workspace is active because
resolveWithin/getAllowedDirectory(conversationId) uses the dynamic allowed dir;
update the code so the dynamic allowed directory from
getAllowedDirectory(conversationId) is used for relative paths instead of
this.coderConfig.allowedDirectory—either compute allowedDir once in searchFiles
(via getAllowedDirectory) and pass it into searchInDirectory, or change
searchInDirectory to accept a conversationId and call getAllowedDirectory
itself; adjust references to allowedDir when building results (path.relative) to
use the dynamic value and keep resolveWithin, searchFiles, searchInDirectory,
and getAllowedDirectory consistent.

In `@src/services/lessons.service.ts`:
- Around line 244-251: The toCSV() export currently escapes double quotes but
leaves newlines (and potentially CRLF) inside lesson.error which can break CSV
rows; update the error normalization in toCSV (referencing toCSV(),
this.lessons, and lesson.error) to first replace CR and LF (e.g.,
.replace(/\r?\n/g, ' ')), then escape quotes (.replace(/"/g, '""')), then
substring to 100 chars, and continue wrapping the field in quotes as already
done so CSV rows remain intact even when errors contain newlines or commas.
- Around line 78-88: The initialize method can silently leave storagePath empty
if CoderService isn't available; modify initialize( runtime: IAgentRuntime ) so
that when runtime.getService<CoderService>('coder') returns undefined you emit a
visible warning (e.g., this.logger.warn(...) or console.warn(...)) and set a
safe fallback storagePath (for example path.join(process.cwd(), '.plugin-code',
'lessons.json')) before calling this.load(); keep references to initialize,
IAgentRuntime, getService, CoderService, storagePath and load so the change is
easy to locate.

In `@WORKSPACES.md`:
- Around line 372-382: The comparison table starting with the header "| Feature
| Eliza Workspaces | GitHub Codespaces | Replit | VS Code Dev Containers |" has
inconsistent pipe spacing and triggers MD060; normalize the table by aligning
the pipe characters and cell padding to your project's markdown table style
(e.g., ensure a single space after and before each pipe or run your markdown
formatter), making the header, separator row, and all data rows follow the same
column padding so markdownlint no longer reports MD060.
- Around line 73-91: Add language identifiers ("text") to the three fenced code
blocks under the headings "From Git Repository", "From Archive", and "Local
Workspace" so markdownlint MD040 is satisfied; update the opening fences for
each unlabeled block to use ```text (the blocks containing the repository
clone/import examples, the archive import/extract examples, and the local
workspace creation examples).
🧹 Nitpick comments (19)
src/types/execution.ts (1)

92-98: Consider documenting progressMode values.

The progressMode field has 'auto' | 'manual' options. While Line 12 mentions that "Progress is calculated from files read/written" (implying 'auto' behavior), it would be helpful to document what 'manual' mode does or when it should be used.

src/services/coderService.ts (1)

42-67: Good progressive enhancement pattern.

The workspace integration is well-documented and correctly falls back when unavailable. Consider adding a trace-level log in the catch block to aid debugging when workspace service lookup fails unexpectedly.

Minor: Line 55 uses any type for workspaceService. If a shared interface exists for the workspace service, using it would improve type safety.

🔧 Optional: Add trace logging for debugging
       } catch {
-        // plugin-workspace not available, fall back to config
+        // plugin-workspace not available, fall back to config
+        logger.trace({ src: 'plugin:code' }, 'plugin-workspace not available, using config directory');
       }
src/services/stats.service.ts (1)

50-52: Serialize saves to avoid overlapping writes and I/O churn.

recordAttempt() awaits save() on every call; concurrent calls can interleave writes and overwrite newer data. Consider a simple save queue to serialize writes (or debounce if you want batching).

🔧 Suggested refactor (serialized saves)
   private stats: Map<string, AgentStats> = new Map();
   private storagePath: string = '';
   private loaded = false;
+  private saveQueue: Promise<void> = Promise.resolve();

@@
     this.stats.set(agent, existing);
-    await this.save();
+    this.saveQueue = this.saveQueue.then(() => this.save());
+    await this.saveQueue;

Also applies to: 148-173

src/services/executionTracker.service.ts (2)

56-68: Return defensive copies from getStatus to avoid external mutation.

Shallow copies leave filesRead, filesWritten, and actionHistory shared with internal state.

🧯 Defensive copy
-    return { ...status };
+    return {
+      ...status,
+      filesRead: [...status.filesRead],
+      filesWritten: [...status.filesWritten],
+      actionHistory: status.actionHistory.map((a) => ({ ...a })),
+    };

360-367: Handle Windows path separators in shortenPath.

Using only '/' misses Windows paths; split on both separators.

🪟 Cross‑platform path split
-    const parts = filePath.split('/');
+    const parts = filePath.split(/[\\/]/);
src/actions/agents/code.ts (1)

84-88: Add a fallback conversationId for non‑room contexts.

If message.roomId is undefined (e.g., system‑initiated calls), tracking and directory lookup can break.

🧭 Safer conversationId
-    const conversationId = message.roomId;
+    const conversationId = message.roomId ?? runtime.agentId;
src/providers/executionStatus.provider.ts (1)

24-35: Escape CSV fields to avoid malformed output.

Descriptions or file paths can contain quotes, commas, or newlines.

🧾 Safer CSV encoding
 function formatHistoryAsCsv(actions: ExecutionAction[]): string {
   if (actions.length === 0) return 'No actions recorded';

   const header = 'type,description,file,success,timestamp';
+  const escape = (value: string) =>
+    `"${value.replace(/"/g, '""').replace(/\r?\n/g, ' ')}"`;
   const rows = actions.map((a) => {
     const file = a.file || '';
     const time = new Date(a.timestamp).toISOString();
-    return `${a.type},"${a.description}",${file},${a.success},${time}`;
+    return `${a.type},${escape(a.description)},${escape(file)},${a.success},${time}`;
   });
src/actions/agents/aider.ts (1)

26-94: Consider extracting shared agent action logic.

This handler is nearly identical to cursorAction (and likely other agent actions in this PR). The common pattern includes:

  1. Get coderService and validate availability
  2. Check agent availability from registry
  3. Extract and validate prompt
  4. Build ExecuteParams and execute
  5. Handle success/failure with callbacks

A shared factory or helper function could reduce duplication and ensure consistency across all agent actions.

♻️ Example: Agent action factory pattern
// In a shared helper file, e.g., src/actions/agents/createAgentAction.ts
function createAgentAction(agentName: string, config: {
  displayName: string;
  installHint: string;
  similes: string[];
}): Action {
  return {
    name: agentName.toUpperCase(),
    description: `Execute coding task with ${config.displayName}. Use when user says "use ${agentName}".`,
    similes: config.similes,
    validate: async (_runtime) => {
      const registry = AgentRegistry.getInstance();
      return registry.get(agentName)?.isAvailable ?? false;
    },
    handler: async (runtime, message, _state, _options, callback) => {
      // ... shared handler logic with agentName parameterized
    },
  };
}

// Usage:
export const aiderAction = createAgentAction('aider', {
  displayName: 'Aider CLI',
  installHint: 'pip install aider-chat',
  similes: ['use aider', 'aider', 'with aider', 'using aider'],
});
src/providers/settings.provider.ts (1)

28-28: Specify radix for parseInt.

Although modern JavaScript defaults to base 10 for numeric strings, explicitly specifying the radix improves clarity and avoids potential issues with strings that might be interpreted differently.

♻️ Suggested fix
-    const timeoutMs = parseInt(runtime.getSetting('CODER_TIMEOUT_MS') as string) || 300000;
+    const timeoutMs = parseInt(runtime.getSetting('CODER_TIMEOUT_MS') as string, 10) || 300000;
src/actions/agents/claudeCode.ts (1)

26-96: Consider extracting shared handler logic into a reusable helper.

The handler implementation is nearly identical to opencode.ts (and likely other agent actions). The only differences are:

  • Agent name string ('claude-code' vs 'opencode')
  • Error message text
  • Action name in return value

This pattern could be consolidated into a factory function to reduce duplication.

♻️ Example helper function
// In a shared file like agents/helpers.ts
export function createAgentHandler(agentName: string, displayName: string, installUrl?: string) {
  return async (runtime, message, _state, _options, callback) => {
    const registry = AgentRegistry.getInstance();
    const coderService = runtime.getService<CoderService>('coder');
    
    if (!coderService) {
      await callback({ text: 'CoderService not available.' });
      return { success: false, error: 'CoderService not available' };
    }
    
    const reg = registry.get(agentName);
    if (!reg?.isAvailable) {
      const msg = installUrl 
        ? `${displayName} CLI not available. Install from: ${installUrl}`
        : `${displayName} CLI not available.`;
      await callback({ text: msg });
      return { success: false, error: `${displayName} not available` };
    }
    // ... rest of shared logic
  };
}
src/services/agents/claudeCode.agent.ts (1)

186-194: Unused return value from classifyError().

classifyError(output) is called but its return value is discarded. If classifyError is intended only for logging/side effects, this is fine. Otherwise, consider using the classified error type to provide more specific error messages to users.

♻️ Potential enhancement
       if (result.exitCode !== 0) {
-        classifyError(output);
+        const errorType = classifyError(output);
         logger.error(`[ClaudeCodeAgent] Failed with exit code: ${result.exitCode}`);
         return {
           success: false,
-          error: result.stderr || 'Claude Code execution failed',
+          error: result.stderr || `Claude Code execution failed (${errorType})`,
           output,
         };
       }
src/services/index.ts (1)

16-30: Minor inconsistency: writePromptFile and cleanupPromptFile are not re-exported.

The src/services/agents/index.ts exports writePromptFile and cleanupPromptFile, but they're not included in the re-exports here. If these utilities are intended for external use, consider adding them for API consistency.

♻️ Add missing exports if needed
 export {
   NativeCoderAgent,
   ClaudeCodeAgent,
   CursorAgent,
   AiderAgent,
   CodexAgent,
   OpenCodeAgent,
   execCommand,
   commandExists,
   findAvailableBinary,
   isValidModelName,
+  writePromptFile,
+  cleanupPromptFile,
   classifyError,
   createFixPrompt,
 } from './agents/index.ts';
src/actions/prr/viewLessons.ts (1)

44-49: Regex may not capture all intended search patterns.

The regex /(?:search|find|for)\s+["']?([^"']+)["']?/i captures text after "search", "find", or "for", but the for keyword alone is too generic and may cause false positives (e.g., "show lessons for today" would extract "today" as search keyword). Additionally, the pattern doesn't handle cases like "search for X" well since "for" would match before "search for" gets a chance.

Consider refining the pattern or documenting the expected input format.

💡 Suggested refinement
-    const searchMatch = messageText.match(/(?:search|find|for)\s+["']?([^"']+)["']?/i);
+    const searchMatch = messageText.match(/(?:search|find)\s+(?:for\s+)?["']?([^"']+)["']?/i);
src/services/agents/cursor.agent.ts (1)

84-114: Consider logging the actual error when authentication check fails.

When checkStatus catches an error during the models command, it only returns the message but doesn't log it. For debugging purposes, logging the actual error would be helpful.

📝 Suggested improvement
     } catch (error: unknown) {
       const err = error as Error;
+      logger.debug(`[CursorAgent] Auth check failed: ${err.message}`);
       return { ready: false, error: `Failed to check auth: ${err.message}` };
     }
src/services/agents/aider.agent.ts (1)

55-82: Duplicate API key checks between checkStatus and execute.

The API key validation logic (lines 65-73) is duplicated in execute (lines 98-106). Consider extracting this to a private helper method to improve maintainability.

src/services/agents/native.agent.ts (2)

114-123: Whitespace trimming on file content may alter intended formatting.

Line 115 trims the content with .trim(), which could remove intentional leading/trailing whitespace or newlines in source files. For code files, trailing newlines are often required by linters (e.g., POSIX compliance). Consider preserving the original content or only trimming leading/trailing blank lines.

💡 Preserve trailing newline
       while ((match = FILE_BLOCK_REGEX.exec(response.text)) !== null) {
         const filePath = match[1].trim();
-        const content = match[2].trim();
+        // Trim leading whitespace but preserve trailing newline for POSIX compliance
+        const content = match[2].replace(/^\s*\n/, '').replace(/\s*$/, '\n');
 
         if (filePath && content) {

153-161: Partial success returns success: true but error details may be lost.

When errors occur but some files succeed (lines 163-167), the function logs a warning but continues to return success: true (line 172). The error details are only appended to the output string. Consider returning success: false with modifiedFiles populated, or adding a warnings field to AgentResult for better error visibility.

src/index.ts (1)

180-219: Async agent registration results are awaited but not checked.

The registerAgentWithDetection calls are awaited but their boolean return values (indicating CLI availability) are not used. Consider logging which CLI agents were detected vs not found for better observability during startup.

💡 Log detection results
-    await registerAgentWithDetection('claude-code', new ClaudeCodeAgent(), 'claude', {
+    const claudeAvailable = await registerAgentWithDetection('claude-code', new ClaudeCodeAgent(), 'claude', {
       displayName: 'Claude Code',
       isRecommended: true,
       isStable: true,
       description: "Anthropic's official Claude Code CLI",
       aliases: ['claude', 'claude-code', 'anthropic'],
     });
+    if (!claudeAvailable) {
+      logger.debug('[plugin-code] Claude Code CLI not found');
+    }
src/services/lessons.service.ts (1)

154-155: Lesson ID generation has low collision resistance.

The ID format L${Date.now()}-${Math.random().toString(36).substring(2, 8)} uses only 6 random characters (~31 bits of entropy). While sufficient for most use cases, rapid sequential failures within the same millisecond could theoretically collide. Consider using a longer random suffix or a UUID.

Comment on lines +29 to +202
### Proposed: `CODE_EXECUTION_STATUS` Provider

```typescript
/**
* Provider that exposes current coding execution status.
*
* WHY: Orchestrator needs visibility into CODE action execution
* to make better progress estimates and detect stalemate.
*/
export const codeExecutionStatusProvider: Provider = {
name: 'CODE_EXECUTION_STATUS',
description: 'Current status of coding agent execution',

get: async (runtime: IAgentRuntime, message: Memory, state?: State) => {
const coderService = runtime.getService<CoderService>('coder');
if (!coderService) {
return {
text: 'Coder service not available',
values: { available: false },
};
}

const status = coderService.getExecutionStatus();

return {
text: formatStatus(status),
values: {
// Is a coding task currently running?
isExecuting: status.isExecuting,

// Which agent is being used?
agent: status.agent, // 'claude-code', 'cursor', 'native', etc.

// Current phase
phase: status.phase, // 'idle', 'planning', 'reading', 'writing', 'verifying'

// Files being worked on
currentFile: status.currentFile,
filesRead: status.filesRead,
filesWritten: status.filesWritten,

// Progress estimate (0-100)
progress: status.progress,

// Time elapsed
startedAt: status.startedAt,
elapsedMs: status.elapsedMs,

// Last action taken
lastAction: status.lastAction,
},
data: status,
};
},
};
```

### What CoderService Needs to Track

```typescript
interface ExecutionStatus {
// Execution state
isExecuting: boolean;
agent: string | null;
conversationId: string | null;

// Phase tracking
phase: 'idle' | 'planning' | 'reading' | 'writing' | 'verifying';

// File tracking
currentFile: string | null;
filesRead: string[];
filesWritten: string[];

// Progress
progress: number; // 0-100 estimate

// Timing
startedAt: number | null;
elapsedMs: number;

// History (last few actions for context)
lastAction: string | null;
recentActions: string[];
}
```

### How Agents Update Status

Each agent implementation should call status updates:

```typescript
// In NativeCoderAgent.execute():
async execute(params: ExecuteParams, runtime: IAgentRuntime): Promise<AgentResult> {
const coderService = runtime.getService<CoderService>('coder');

// Start
coderService.updateStatus({
isExecuting: true,
agent: 'native',
phase: 'planning',
progress: 10,
});

// Reading files
coderService.updateStatus({
phase: 'reading',
currentFile: 'src/auth.ts',
progress: 30,
});

// Writing
coderService.updateStatus({
phase: 'writing',
currentFile: 'src/auth.ts',
filesWritten: ['src/auth.ts'],
progress: 70,
});

// Done
coderService.updateStatus({
isExecuting: false,
phase: 'idle',
progress: 100,
});

return result;
}
```

### For CLI Agents (claude, cursor, etc.)

CLI agents can update status based on output parsing:

```typescript
// In ClaudeCodeAgent.execute():
async execute(params: ExecuteParams, runtime: IAgentRuntime): Promise<AgentResult> {
const coderService = runtime.getService<CoderService>('coder');

coderService.updateStatus({
isExecuting: true,
agent: 'claude-code',
phase: 'planning',
});

// Stream CLI output and parse for status updates
const process = spawn('claude', [...]);

process.stdout.on('data', (data) => {
const output = data.toString();

// Parse for file operations
if (output.includes('Reading')) {
const file = parseFileName(output);
coderService.updateStatus({
phase: 'reading',
currentFile: file,
filesRead: [...status.filesRead, file],
});
}

if (output.includes('Writing')) {
const file = parseFileName(output);
coderService.updateStatus({
phase: 'writing',
currentFile: file,
filesWritten: [...status.filesWritten, file],
});
}
});

// ...
}
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align the examples with the actual ExecutionTrackerService and ExecutionStatus types.

The doc samples use CoderService.updateStatus() / coderService.getExecutionStatus() and an older interface shape (nullable fields, missing phases/actionHistory). The implementation now uses ExecutionTrackerService plus ExecutionPhase values like starting, completing, and error, and actionHistory in ExecutionStatus. Please update the snippets and field lists to match src/services/executionTracker.service.ts and src/types/execution.ts so integrators aren’t misled.

🤖 Prompt for AI Agents
In `@ORCHESTRATOR_INTEGRATION.md` around lines 29 - 202, Replace the old
CoderService examples with the actual ExecutionTrackerService API: in the
codeExecutionStatusProvider sample and agent snippets, get the service via
runtime.getService<ExecutionTrackerService>('executionTracker') and call the
real methods (e.g., getExecutionStatus / updateExecutionStatus) rather than
coderService.getExecutionStatus/updateStatus; switch phase/string values to the
real ExecutionPhase enums (including starting, completing, error) instead of
'idle'|'planning'|'reading'|'writing'|'verifying'; replace nullable/legacy
fields with the actual ExecutionStatus shape from src/types/execution.ts
(include actionHistory instead of recentActions, adjust timing/identifier fields
to match the type), and update NativeCoderAgent.execute and
ClaudeCodeAgent.execute examples to call
ExecutionTrackerService.updateExecutionStatus with the new phase values and
actionHistory updates when parsing CLI output.

Comment on lines +238 to +243
| Without Status | With Status |
|---------------|-------------|
| "CODE succeeded" | "CODE succeeded: wrote 3 files in 12s using claude-code" |
| Progress: guess | Progress: based on files read/written |
| Stalemate: after 3 failures | Stalemate: detect stuck at "reading" phase |
| User sees: "Running..." | User sees: "Writing src/auth.ts..." |
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix table pipe spacing to satisfy markdownlint MD060.

The separator row is missing spaces around pipes.

🧹 Table separator formatting
-|---------------|-------------|
+| ------------- | ----------- |
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
| Without Status | With Status |
|---------------|-------------|
| "CODE succeeded" | "CODE succeeded: wrote 3 files in 12s using claude-code" |
| Progress: guess | Progress: based on files read/written |
| Stalemate: after 3 failures | Stalemate: detect stuck at "reading" phase |
| User sees: "Running..." | User sees: "Writing src/auth.ts..." |
| Without Status | With Status |
| ------------- | ----------- |
| "CODE succeeded" | "CODE succeeded: wrote 3 files in 12s using claude-code" |
| Progress: guess | Progress: based on files read/written |
| Stalemate: after 3 failures | Stalemate: detect stuck at "reading" phase |
| User sees: "Running..." | User sees: "Writing src/auth.ts..." |
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 239-239: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 239-239: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 239-239: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 239-239: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)

🤖 Prompt for AI Agents
In `@ORCHESTRATOR_INTEGRATION.md` around lines 238 - 243, The Markdown table
separator row in ORCHESTRATOR_INTEGRATION.md is missing spaces around the pipe
characters which violates markdownlint MD060; update the separator row between
the header and body so each pipe has a single space before and after it (i.e.,
change "|---------------|-------------|" to use " | " spacing consistent with
the header and rows), ensuring the separator aligns with the header columns for
the table shown under the "Without Status | With Status" heading.

Comment on lines 37 to +54
| Variable | Description | Required | Default |
|----------|-------------|----------|---------|
| `CODER_ENABLED` | Enable/disable the plugin | No | `false` |
| `CODER_ALLOWED_DIRECTORY` | Directory for operations | Yes | `process.cwd()` |
| `CODER_TIMEOUT` | Command timeout (ms) | No | `30000` |
| `CODER_FORBIDDEN_COMMANDS` | Additional forbidden commands (comma-separated) | No | - |
| `CODER_FORBIDDEN_COMMANDS` | Additional forbidden commands | No | - |

### AI Agent Settings

| Variable | Description | Values | Default |
|----------|-------------|--------|---------|
| `CODE_MODE` | Agent selection mode | `auto`, `native`, `cli` | `auto` |
| `CODE_CLAUDE_MODEL` | Model for Claude Code | Model name | - |
| `CODE_CURSOR_MODEL` | Model for Cursor | Model name | - |
| `CODE_AIDER_MODEL` | Model for Aider | Provider/model | - |
| `CODE_CODEX_MODEL` | Model for Codex | Model name | - |
| `CODE_OPENCODE_MODEL` | Model for OpenCode | Model name | - |

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Normalize table pipe spacing to satisfy MD060.

markdownlint flags table column style inconsistencies across the README tables. Please normalize pipe spacing to the configured style (or run your markdown formatter).

Also applies to: 76-105, 110-123, 131-142

🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 38-38: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 38-38: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 47-47: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)

🤖 Prompt for AI Agents
In `@README.md` around lines 37 - 54, The markdown tables in README (e.g., rows
with headers like CODER_ENABLED, CODER_ALLOWED_DIRECTORY and CODE_MODE,
CODE_CLAUDE_MODEL, etc.) have inconsistent pipe spacing triggering MD060; update
each table to use a consistent pipe-spacing style (for example, single space
before and after each cell delimiter) across all tables (including the sections
you noted and the ones at lines ~76-105, 110-123, 131-142) by normalizing the
pipe spacing or running the project's markdown formatter so every cell follows
the same " | cell | " pattern.

Comment on lines +145 to +168
## How CODE_MODE Works

```
User: "fix the bug in utils.ts"
|
v
CODE action
|
v
Check CODE_MODE
|
+---+---+
| |
auto native/cli
| |
v v
Prefer CLI → Native fallback
|
v
Execute with selected agent
|
v
Return result (success/failure)
```
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add language identifiers to the ASCII diagrams.

markdownlint (MD040) requires fenced blocks to declare a language; text works well for diagrams.

💡 Suggested fix
-```
+```text
 User: "fix the bug in utils.ts"
        |
        v
    CODE action
        |
        v
   Check CODE_MODE
        |
    +---+---+
    |       |
   auto   native/cli
    |       |
    v       v
 Prefer CLI → Native fallback
    |
    v
 Execute with selected agent
    |
    v
 Return result (success/failure)

- +text
plugin-code
├── Services
│ ├── CoderService # File ops, shell, working directory
│ ├── AgentRegistry # Manages all coding agents
│ ├── ExecutionTrackerService # Tracks execution status per conversation
│ ├── LessonsService # Tracks failures
│ └── StatsService # Tracks performance
├── Agents
│ ├── NativeCoderAgent # elizaOS LLM + file actions
│ ├── ClaudeCodeAgent # Claude Code CLI
│ ├── CursorAgent # Cursor Agent CLI
│ ├── AiderAgent # Aider CLI
│ ├── CodexAgent # Codex CLI
│ └── OpenCodeAgent # OpenCode CLI
├── Actions
│ ├── File ops # read, write, edit, etc.
│ ├── Agent actions # CODE, CLAUDE_CODE, etc.
│ └── PRR actions # VIEW_LESSONS, SHOW_STATS
└── Providers
├── coderStatusProvider # Core status
├── help.provider # Usage instructions
├── settings.provider # Configuration
├── executionStatus.provider # 3 resolutions (for orchestrator)
├── agents.providers # 3 resolutions
├── lessons.providers # 3 resolutions
└── stats.providers # 3 resolutions

</details>


Also applies to: 190-217

<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 markdownlint-cli2 (0.20.0)</summary>

[warning] 147-147: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In @README.md around lines 145 - 168, Update the ASCII art fenced code blocks in
README.md to include a language identifier (use "text") to satisfy markdownlint
MD040; specifically add text at the start of the CODE_MODE diagram and the plugin-code diagram (the blocks containing the "User: 'fix the bug in utils.ts' ... Check CODE_MODE" flow and the "plugin-code ├── Services ..." tree) so both diagrams declare a language instead of bare fences.


</details>

<!-- fingerprinting:phantom:poseidon:eagle -->

<!-- This is an auto-generated comment by CodeRabbit -->

Comment on lines +87 to +97
if (status.filesRead.length > 0) {
lines.push('');
lines.push('**Files Read:**');
status.filesRead.forEach((f) => lines.push(` - ${f}`));
}

if (status.filesWritten.length > 0) {
lines.push('');
lines.push('**Files Written:**');
status.filesWritten.forEach((f) => lines.push(` - ${f}`));
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fix Biome error: forEach callbacks must not return values.

The current arrow expression returns lines.push(...), triggering the lint error.

✅ Lint‑safe loop bodies
-      status.filesRead.forEach((f) => lines.push(`  - ${f}`));
+      status.filesRead.forEach((f) => {
+        lines.push(`  - ${f}`);
+      });
...
-      status.filesWritten.forEach((f) => lines.push(`  - ${f}`));
+      status.filesWritten.forEach((f) => {
+        lines.push(`  - ${f}`);
+      });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if (status.filesRead.length > 0) {
lines.push('');
lines.push('**Files Read:**');
status.filesRead.forEach((f) => lines.push(` - ${f}`));
}
if (status.filesWritten.length > 0) {
lines.push('');
lines.push('**Files Written:**');
status.filesWritten.forEach((f) => lines.push(` - ${f}`));
}
if (status.filesRead.length > 0) {
lines.push('');
lines.push('**Files Read:**');
status.filesRead.forEach((f) => {
lines.push(` - ${f}`);
});
}
if (status.filesWritten.length > 0) {
lines.push('');
lines.push('**Files Written:**');
status.filesWritten.forEach((f) => {
lines.push(` - ${f}`);
});
}
🧰 Tools
🪛 Biome (2.3.13)

[error] 90-90: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)


[error] 96-96: This callback passed to forEach() iterable method should not return a value.

Either remove this return or remove the returned value.

(lint/suspicious/useIterableCallbackReturn)

🤖 Prompt for AI Agents
In `@src/providers/executionStatus.provider.ts` around lines 87 - 97, The forEach
callbacks on status.filesRead and status.filesWritten currently use concise
arrow expressions that implicitly return the result of lines.push(...) which
triggers the Biome lint error; change those callbacks to use block bodies (or
replace with a for...of loop) and call lines.push(...) as a statement (no return
value) so the callback does not return anything—update the two occurrences that
iterate over status.filesRead and status.filesWritten and ensure you still push
the same formatted strings (e.g., `  - ${f}`) into the lines array.

Comment on lines +327 to +333
const allowedDir = this.coderConfig.allowedDirectory; // Use base config for search
for (let i = 0; i < lines.length; i++) {
if (matches.length >= maxMatches) break;
const line = lines[i] ?? '';
if (!line.toLowerCase().includes(needleLower)) continue;
matches.push({
file: path.relative(this.coderConfig.allowedDirectory, full),
file: path.relative(allowedDir, full),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Potential path inconsistency when workspace is active.

searchInDirectory uses this.coderConfig.allowedDirectory (the static base config) for computing relative file paths in results, while resolveWithin uses the dynamic getAllowedDirectory(conversationId).

If a workspace is active, search results will show paths relative to the base config directory rather than the active workspace, which could be confusing to users. Consider using the same dynamic directory for consistency, or document that search results always use the base config path.

🔧 Suggested fix for path consistency
   private async searchInDirectory(
     dir: string,
     needleLower: string,
     matches: Array<{ file: string; line: number; content: string }>,
-    maxMatches: number
+    maxMatches: number,
+    allowedDir: string
   ): Promise<void> {
     // ...
-        const allowedDir = this.coderConfig.allowedDirectory; // Use base config for search
         for (let i = 0; i < lines.length; i++) {

Then pass allowedDir from searchFiles:

-    await this.searchInDirectory(resolved.fullPath, needle.toLowerCase(), matches, limit);
+    const allowedDir = this.getAllowedDirectory(conversationId);
+    await this.searchInDirectory(resolved.fullPath, needle.toLowerCase(), matches, limit, allowedDir);
🤖 Prompt for AI Agents
In `@src/services/coderService.ts` around lines 327 - 333, searchInDirectory is
using this.coderConfig.allowedDirectory to compute relative file paths, causing
inconsistency when a workspace is active because
resolveWithin/getAllowedDirectory(conversationId) uses the dynamic allowed dir;
update the code so the dynamic allowed directory from
getAllowedDirectory(conversationId) is used for relative paths instead of
this.coderConfig.allowedDirectory—either compute allowedDir once in searchFiles
(via getAllowedDirectory) and pass it into searchInDirectory, or change
searchInDirectory to accept a conversationId and call getAllowedDirectory
itself; adjust references to allowedDir when building results (path.relative) to
use the dynamic value and keep resolveWithin, searchFiles, searchInDirectory,
and getAllowedDirectory consistent.

Comment on lines +78 to +88
private async initialize(runtime: IAgentRuntime): Promise<void> {
// Get project root from CoderService
const coderService = runtime.getService<CoderService>('coder');
if (coderService) {
const projectRoot = coderService.getAllowedDirectory();
this.storagePath = path.join(projectRoot, '.plugin-code', 'lessons.json');
}

// Load existing lessons if file exists
await this.load();
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Service initialization may fail silently if CoderService is not yet started.

The initialize method depends on CoderService being available via runtime.getService('coder'). If CoderService starts after LessonsService (service ordering), storagePath remains empty and lessons won't persist. Consider adding a warning log when CoderService is unavailable.

🔧 Suggested improvement
   private async initialize(runtime: IAgentRuntime): Promise<void> {
     // Get project root from CoderService
     const coderService = runtime.getService<CoderService>('coder');
     if (coderService) {
       const projectRoot = coderService.getAllowedDirectory();
       this.storagePath = path.join(projectRoot, '.plugin-code', 'lessons.json');
+    } else {
+      logger.warn('[LessonsService] CoderService not available - lessons will not persist to disk');
     }
 
     // Load existing lessons if file exists
     await this.load();
   }
🤖 Prompt for AI Agents
In `@src/services/lessons.service.ts` around lines 78 - 88, The initialize method
can silently leave storagePath empty if CoderService isn't available; modify
initialize( runtime: IAgentRuntime ) so that when
runtime.getService<CoderService>('coder') returns undefined you emit a visible
warning (e.g., this.logger.warn(...) or console.warn(...)) and set a safe
fallback storagePath (for example path.join(process.cwd(), '.plugin-code',
'lessons.json')) before calling this.load(); keep references to initialize,
IAgentRuntime, getService, CoderService, storagePath and load so the change is
easy to locate.

Comment on lines +244 to +251
toCSV(): string {
const lines = ['id,timestamp,agent,error'];
for (const lesson of this.lessons.slice(-50)) {
// Last 50 for CSV
const error = lesson.error.replace(/"/g, '""').substring(0, 100);
lines.push(`${lesson.id},${lesson.timestamp},${lesson.agent},"${error}"`);
}
return lines.join('\n');
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

CSV export doesn't escape commas in error messages.

The toCSV method escapes double quotes but doesn't handle commas within the error field. If an error message contains a comma, it will break CSV parsing.

🔧 Wrap error field in quotes regardless of content

The current code already wraps the error in quotes, which handles commas. However, newlines in error messages could still break CSV rows. Consider also replacing newlines:

   toCSV(): string {
     const lines = ['id,timestamp,agent,error'];
     for (const lesson of this.lessons.slice(-50)) {
       // Last 50 for CSV
-      const error = lesson.error.replace(/"/g, '""').substring(0, 100);
+      const error = lesson.error.replace(/"/g, '""').replace(/[\r\n]+/g, ' ').substring(0, 100);
       lines.push(`${lesson.id},${lesson.timestamp},${lesson.agent},"${error}"`);
     }
     return lines.join('\n');
   }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
toCSV(): string {
const lines = ['id,timestamp,agent,error'];
for (const lesson of this.lessons.slice(-50)) {
// Last 50 for CSV
const error = lesson.error.replace(/"/g, '""').substring(0, 100);
lines.push(`${lesson.id},${lesson.timestamp},${lesson.agent},"${error}"`);
}
return lines.join('\n');
toCSV(): string {
const lines = ['id,timestamp,agent,error'];
for (const lesson of this.lessons.slice(-50)) {
// Last 50 for CSV
const error = lesson.error.replace(/"/g, '""').replace(/[\r\n]+/g, ' ').substring(0, 100);
lines.push(`${lesson.id},${lesson.timestamp},${lesson.agent},"${error}"`);
}
return lines.join('\n');
}
🤖 Prompt for AI Agents
In `@src/services/lessons.service.ts` around lines 244 - 251, The toCSV() export
currently escapes double quotes but leaves newlines (and potentially CRLF)
inside lesson.error which can break CSV rows; update the error normalization in
toCSV (referencing toCSV(), this.lessons, and lesson.error) to first replace CR
and LF (e.g., .replace(/\r?\n/g, ' ')), then escape quotes (.replace(/"/g,
'""')), then substring to 100 chars, and continue wrapping the field in quotes
as already done so CSV rows remain intact even when errors contain newlines or
commas.

Comment on lines +73 to +91
**From Git Repository:**
```
"Clone https://github.com/facebook/react"
"Clone the Next.js repo from GitHub"
"Import https://github.com/user/repo branch develop"
```

**From Archive:**
```
"Import project from https://example.com/project.zip"
"Extract this archive: https://example.com/app.tar.gz"
```

**Local Workspace:**
```
"Create local workspace named my-project"
"Create a new workspace called test-app"
```

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced example blocks.

markdownlint (MD040) flags fenced blocks without a language tag. Use text for prompt examples (and apply similarly to other unlabeled fences in this doc).

💡 Suggested fix
-```
+```text
 "Clone https://github.com/facebook/react"
 "Clone the Next.js repo from GitHub"
 "Import https://github.com/user/repo branch develop"

- +text
"Import project from https://example.com/project.zip"
"Extract this archive: https://example.com/app.tar.gz"


-```
+```text
 "Create local workspace named my-project"
 "Create a new workspace called test-app"
🧰 Tools
🪛 markdownlint-cli2 (0.20.0)

[warning] 77-77: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 77-77: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 77-77: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 77-77: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 77-77: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 77-77: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 90-90: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 90-90: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 90-90: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 90-90: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)


[warning] 90-90: Table column style
Table pipe is missing space to the right for style "compact"

(MD060, table-column-style)


[warning] 90-90: Table column style
Table pipe is missing space to the left for style "compact"

(MD060, table-column-style)

🤖 Prompt for AI Agents
In `@WORKSPACES.md` around lines 73 - 91, Add language identifiers ("text") to the
three fenced code blocks under the headings "From Git Repository", "From
Archive", and "Local Workspace" so markdownlint MD040 is satisfied; update the
opening fences for each unlabeled block to use ```text (the blocks containing
the repository clone/import examples, the archive import/extract examples, and
the local workspace creation examples).

Comment on lines +372 to +382
| Feature | Eliza Workspaces | GitHub Codespaces | Replit | VS Code Dev Containers |
|---------|------------------|-------------------|--------|------------------------|
| **Chat Interface** | ✅ | ❌ | ❌ | ❌ |
| **Git Clone** | ✅ | ✅ | ✅ | ✅ |
| **Archive Import** | ✅ | ❌ | ✅ | ❌ |
| **Local Creation** | ✅ | ❌ | ✅ | ✅ |
| **Auto-Detection** | ✅ | ✅ | ✅ | ✅ |
| **Multi-Workspace** | ✅ | ✅ | ✅ | ❌ |
| **Offline Mode** | ✅ | ❌ | ❌ | ✅ |
| **AI Coding Agents** | ✅ | ❌ | ❌ | ❌ |

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Normalize table pipe spacing to satisfy MD060.

markdownlint reports table column style issues in the comparison table; align spacing to your configured table style (or run your markdown formatter).

🤖 Prompt for AI Agents
In `@WORKSPACES.md` around lines 372 - 382, The comparison table starting with the
header "| Feature | Eliza Workspaces | GitHub Codespaces | Replit | VS Code Dev
Containers |" has inconsistent pipe spacing and triggers MD060; normalize the
table by aligning the pipe characters and cell padding to your project's
markdown table style (e.g., ensure a single space after and before each pipe or
run your markdown formatter), making the header, separator row, and all data
rows follow the same column padding so markdownlint no longer reports MD060.

odilitime and others added 2 commits January 30, 2026 01:47
Resolved conflict in WORKSPACES.md between local and remote branches.
Both added the file with same content but different capitalization.

Kept correct capitalization: elizaOS (not ElizaOS).

Co-authored-by: Cursor <cursoragent@cursor.com>
- description: "elizaos" → "elizaOS" (lowercase eliza, capital OS)
- pluginType: "elizaos:plugin" → "elizaOS:plugin"

Per project style guide, the correct capitalization is "elizaOS" not "elizaos".

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant