From bcf6c4e60de3e45455c6b8fbeda9fc1b505c0965 Mon Sep 17 00:00:00 2001 From: Pedram Amini Date: Tue, 3 Feb 2026 19:31:52 -0600 Subject: [PATCH] ## CHANGES MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Added brand-new cross-platform guide covering Windows, Linux, macOS, SSH gotchas 🌍 - Documented SSH remote constraints: no chokidar watch, stdin prompts, path norms πŸ›°οΈ - Standardized path best-practices: `path.join`, `path.posix`, delimiters, tilde expansion 🧭 - Clarified shell execution differences: default shells, which/where lookup, permissions 🐚 - Codified agent portability quirks: session IDs, storage locations, resume flags πŸ“¦ - Introduced keyboard/input pitfalls: macOS Alt keycodes, Windows command-length limits ⌨️ - Added Git cross-platform warnings: stat differences and case-sensitivity traps 🧩 - Upgraded collaboration rules: assumptions, confusion stops, pushback, scope discipline 🀝 - Added Sentry/error-handling guidance: bubble unexpected errors, report with context πŸ”Ž - Refreshed docs structure references to match current `src/` layout and modules πŸ—ΊοΈ --- CLAUDE-PLATFORM.md | 221 +++++++++++++++++++++++++++++++++++++++++++++ CLAUDE-WIZARD.md | 10 +- CLAUDE.md | 109 ++++++++++++++++------ 3 files changed, 307 insertions(+), 33 deletions(-) create mode 100644 CLAUDE-PLATFORM.md diff --git a/CLAUDE-PLATFORM.md b/CLAUDE-PLATFORM.md new file mode 100644 index 00000000..69a9125b --- /dev/null +++ b/CLAUDE-PLATFORM.md @@ -0,0 +1,221 @@ +# CLAUDE-PLATFORM.md + +Cross-platform and multi-environment considerations for the Maestro codebase. For the main guide, see [[CLAUDE.md]]. + +--- + +## Platform Compatibility Matrix + +| Feature | macOS | Windows | Linux | SSH Remote | +|---------|-------|---------|-------|------------| +| Claude Code | Full | Full | Full | Full | +| OpenAI Codex | Full | Full | Full | Full | +| OpenCode | Full | Full | Full | Full | +| Factory Droid | Full | Full | Full | Full | +| File watching (chokidar) | Yes | Yes | Yes | **No** | +| Git worktrees | Yes | Yes | Yes | Yes | +| PTY terminal | Yes | Yes | Yes | N/A | + +--- + +## Critical Platform Gotchas + +### 1. Path Handling + +**Path separators differ:** +```typescript +// WRONG - hardcoded separator +const fullPath = folder + '/' + filename; + +// CORRECT - use path.join or path.posix for SSH +import * as path from 'path'; +const fullPath = path.join(folder, filename); // Local +const remotePath = path.posix.join(folder, filename); // SSH remote +``` + +**Path delimiters differ:** +```typescript +// Windows uses ';', Unix uses ':' +const delimiter = path.delimiter; // Use this, don't hardcode +``` + +**Tilde expansion:** +```typescript +// Node.js fs does NOT expand ~ automatically +import { expandTilde } from '../shared/pathUtils'; +const expanded = expandTilde('~/.config/file'); // Always use this +``` + +**Minimum path lengths:** +```typescript +// Validation must account for platform differences +const minPathLength = process.platform === 'win32' ? 4 : 5; // C:\a vs /a/b +``` + +**Windows reserved names:** +```typescript +// CON, PRN, AUX, NUL, COM1-9, LPT1-9 are invalid on Windows +const reservedNames = /^(con|prn|aux|nul|com[1-9]|lpt[1-9])$/i; +``` + +### 2. Shell Detection & Execution + +**Default shells differ:** +```typescript +// Windows: $SHELL doesn't exist; default to PowerShell +const defaultShell = process.platform === 'win32' ? 'powershell.exe' : 'bash'; +``` + +**Command lookup differs:** +```typescript +// 'which' on Unix, 'where' on Windows +const command = process.platform === 'win32' ? 'where' : 'which'; +``` + +**Executable permissions:** +```typescript +// Unix requires X_OK check; Windows does not +if (process.platform !== 'win32') { + await fs.promises.access(filePath, fs.constants.X_OK); +} +``` + +**Windows shell execution:** +```typescript +// Some Windows commands need shell: true +const useShell = isWindows && needsWindowsShell(command); +``` + +### 3. SSH Remote Execution + +**Two SSH identifiers with different lifecycles:** +```typescript +// sshRemoteId: Set AFTER AI agent spawns (via onSshRemote callback) +// sessionSshRemoteConfig.remoteId: Set BEFORE spawn (user configuration) + +// WRONG - fails for terminal-only SSH sessions +const sshId = session.sshRemoteId; + +// CORRECT - works for all SSH sessions +const sshId = session.sshRemoteId || session.sessionSshRemoteConfig?.remoteId; +``` + +**File watching not available for SSH:** +```typescript +// chokidar can't watch remote directories +if (sshRemoteId) { + // Use polling instead of file watching +} +``` + +**Prompts must go via stdin for SSH:** +```typescript +// IMPORTANT: ALL agent prompts are passed via stdin passthrough for SSH. +// This avoids shell escaping issues and command line length limits. +if (isSSH) { + // Pass prompt via stdin, not as command line argument +} +``` + +**Path resolution on remote:** +```typescript +// Don't resolve paths locally when operating on remote +// The remote may have different filesystem structure +if (isRemote) { + // Use path as-is, normalize slashes only +} +``` + +### 4. Agent-Specific Differences + +**Session ID terminology:** +```typescript +// Claude Code: session_id +// Codex: thread_id +// Different field names, same concept +``` + +**Storage locations differ per platform:** +```typescript +// Claude Code: ~/.claude/projects// +// Codex: ~/.codex/sessions/YYYY/MM/DD/*.jsonl +// OpenCode: +// - macOS/Linux: ~/.config/opencode/storage/ +// - Windows: %APPDATA%/opencode/storage/ +``` + +**Resume flags differ:** +```typescript +// Claude Code: --resume +// Codex: resume (subcommand, not flag) +// OpenCode: --session +``` + +**Read-only mode flags differ:** +```typescript +// Claude Code: --permission-mode plan +// Codex: --sandbox read-only +// OpenCode: --agent plan +``` + +### 5. Keyboard & Input + +**macOS Alt key produces special characters:** +```typescript +// Alt+L = 'Β¬', Alt+P = 'Ο€', Alt+U = 'ΓΌ' +// Must use e.code for Alt key combos, not e.key +if (e.altKey && process.platform === 'darwin') { + const key = e.code.replace('Key', '').toLowerCase(); // 'KeyL' -> 'l' +} +``` + +**Windows command line length limit:** +```typescript +// cmd.exe has ~8KB command line limit +// Use sendPromptViaStdin to bypass this for long prompts +``` + +### 6. Git Operations + +**Git stat format differs:** +```typescript +// GNU stat vs BSD stat have different format specifiers +// Use git commands that work cross-platform +``` + +**Case sensitivity:** +```typescript +// macOS with case-insensitive filesystem: +// Renaming "readme.md" to "README.md" may not trigger expected events +``` + +--- + +## Testing Checklist + +When making changes that involve any of the above areas, verify: + +- [ ] Works on macOS (primary development platform) +- [ ] Works on Windows (PowerShell default, path separators) +- [ ] Works on Linux (standard Unix behavior) +- [ ] Works with SSH remote sessions (no file watching, stdin passthrough) +- [ ] Path handling uses `path.join` or `path.posix` as appropriate +- [ ] No hardcoded path separators (`/` or `\`) +- [ ] Shell commands use platform-appropriate lookup (`which`/`where`) +- [ ] Agent-specific code handles all supported agents, not just Claude + +--- + +## Key Files for Platform Logic + +| Concern | Primary Files | +|---------|---------------| +| Path utilities | `src/shared/pathUtils.ts` | +| Shell detection | `src/main/utils/shellDetector.ts` | +| WSL detection | `src/main/utils/wslDetector.ts` | +| CLI detection | `src/main/utils/cliDetection.ts` | +| SSH spawn wrapper | `src/main/utils/ssh-spawn-wrapper.ts` | +| SSH command builder | `src/main/utils/ssh-command-builder.ts` | +| Agent path probing | `src/main/agents/path-prober.ts` | +| Windows diagnostics | `src/main/debug-package/collectors/windows-diagnostics.ts` | +| Safe exec | `src/main/utils/execFile.ts` | diff --git a/CLAUDE-WIZARD.md b/CLAUDE-WIZARD.md index af49e083..709f8286 100644 --- a/CLAUDE-WIZARD.md +++ b/CLAUDE-WIZARD.md @@ -87,16 +87,16 @@ The Wizard maintains two types of state: - Cleared on completion or when user chooses "Just Quit" **State Save Triggers:** -- Auto-save: When `currentStep` changes (step > 1) - `WizardContext.tsx:791` -- Manual save: User clicks "Save & Exit" - `MaestroWizard.tsx:147` +- Auto-save: When `currentStep` changes (step > 1) - `WizardContext.tsx` useEffect with `saveResumeState()` +- Manual save: User clicks "Save & Exit" - `MaestroWizard.tsx` `handleConfirmExit()` **State Clear Triggers:** -- Wizard completion: `App.tsx:4681` + `WizardContext.tsx:711` -- User quits: "Just Quit" button - `MaestroWizard.tsx:168` +- Wizard completion: `App.tsx` wizard completion handler + `WizardContext.tsx` `COMPLETE_WIZARD` action +- User quits: "Quit without saving" button - `MaestroWizard.tsx` `handleQuitWithoutSaving()` - User starts fresh: "Start Fresh" in resume modal - `App.tsx` resume handlers **Opening Wizard Logic:** -The `openWizard()` function in `WizardContext.tsx:528-535` handles state initialization: +The `openWizard()` function in `WizardContext.tsx` handles state initialization: ```typescript // If previous wizard was completed, reset in-memory state first if (state.isComplete === true) { diff --git a/CLAUDE.md b/CLAUDE.md index e6676bef..893c28f6 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -15,10 +15,35 @@ This guide has been split into focused sub-documents for progressive disclosure: | [[CLAUDE-FEATURES.md]] | Usage Dashboard and Document Graph features | | [[CLAUDE-AGENTS.md]] | Supported agents and capabilities | | [[CLAUDE-SESSION.md]] | Session interface and code conventions | +| [[CLAUDE-PLATFORM.md]] | Cross-platform concerns (Windows, Linux, macOS, SSH remote) | | [AGENT_SUPPORT.md](AGENT_SUPPORT.md) | Detailed agent integration guide | --- +## Agent Behavioral Guidelines + +Core behaviors for effective collaboration. Failures here cause the most rework. + +### Surface Assumptions Early +Before implementing non-trivial work, explicitly state assumptions. Never silently fill in ambiguous requirementsβ€”the most common failure mode is guessing wrong and running with it. Format: "Assumptions: 1) X, 2) Y. Correct me now or I proceed." + +### Manage Confusion Actively +When encountering inconsistencies, conflicting requirements, or unclear specs: **STOP**. Name the specific confusion, present the tradeoff, and wait for resolution. Bad: silently picking one interpretation. Good: "I see X in file A but Y in file Bβ€”which takes precedence?" + +### Push Back When Warranted +Not a yes-machine. When an approach has clear problems: point out the issue directly, explain the concrete downside, propose an alternative, then accept the decision if overridden. Sycophancy ("Of course!") followed by implementing a bad idea helps no one. + +### Enforce Simplicity +Natural tendency is to overcomplicateβ€”actively resist. Before finishing: Can this be fewer lines? Are abstractions earning their complexity? Would a senior dev say "why didn't you just..."? Prefer the boring, obvious solution. + +### Maintain Scope Discipline +Touch only what's asked. Do NOT: remove comments you don't understand, "clean up" orthogonal code, refactor adjacent systems as side effects, or delete seemingly-unused code without approval. Surgical precision, not unsolicited renovation. + +### Dead Code Hygiene +After refactoring: identify now-unreachable code, list it explicitly, ask "Should I remove these now-unused elements: [list]?" Don't leave corpses. Don't delete without asking. + +--- + ## Standardized Vernacular Use these terms consistently in code, comments, and documentation: @@ -50,6 +75,7 @@ Maestro is an Electron desktop app for managing multiple AI coding assistants si | `claude-code` | Claude Code | **Active** | | `codex` | OpenAI Codex | **Active** | | `opencode` | OpenCode | **Active** | +| `factory-droid` | Factory Droid | **Active** | | `terminal` | Terminal | Internal | See [[CLAUDE-AGENTS.md]] for capabilities and integration details. @@ -79,22 +105,13 @@ npm run test:watch # Run tests in watch mode src/ β”œβ”€β”€ main/ # Electron main process (Node.js) β”‚ β”œβ”€β”€ index.ts # Entry point, IPC handlers -β”‚ β”œβ”€β”€ process-manager.ts # Process spawning (PTY + child_process) β”‚ β”œβ”€β”€ preload.ts # Secure IPC bridge -β”‚ β”œβ”€β”€ agent-detector.ts # Agent detection and configuration -β”‚ β”œβ”€β”€ agent-capabilities.ts # Agent capability definitions -β”‚ β”œβ”€β”€ agent-session-storage.ts # Session storage interface -β”‚ β”œβ”€β”€ parsers/ # Agent output parsers -β”‚ β”‚ β”œβ”€β”€ agent-output-parser.ts # Parser interface -β”‚ β”‚ β”œβ”€β”€ claude-output-parser.ts # Claude Code parser -β”‚ β”‚ β”œβ”€β”€ opencode-output-parser.ts # OpenCode parser -β”‚ β”‚ └── error-patterns.ts # Error detection patterns -β”‚ β”œβ”€β”€ storage/ # Session storage implementations -β”‚ β”‚ β”œβ”€β”€ claude-session-storage.ts -β”‚ β”‚ └── opencode-session-storage.ts -β”‚ β”œβ”€β”€ tunnel-manager.ts # Cloudflare tunnel support -β”‚ β”œβ”€β”€ web-server.ts # Fastify server for web/mobile interface -β”‚ └── utils/execFile.ts # Safe command execution +β”‚ β”œβ”€β”€ process-manager.ts # Process spawning (PTY + child_process) +β”‚ β”œβ”€β”€ agent-*.ts # Agent detection, capabilities, session storage +β”‚ β”œβ”€β”€ parsers/ # Per-agent output parsers + error patterns +β”‚ β”œβ”€β”€ storage/ # Per-agent session storage implementations +β”‚ β”œβ”€β”€ ipc/handlers/ # IPC handler modules (stats, git, playbooks, etc.) +β”‚ └── utils/ # Utilities (execFile, ssh-spawn-wrapper, etc.) β”‚ β”œβ”€β”€ renderer/ # React frontend (desktop) β”‚ β”œβ”€β”€ App.tsx # Main coordinator @@ -102,31 +119,21 @@ src/ β”‚ β”œβ”€β”€ hooks/ # Custom React hooks β”‚ β”œβ”€β”€ services/ # IPC wrappers (git.ts, process.ts) β”‚ β”œβ”€β”€ constants/ # Themes, shortcuts, priorities -β”‚ └── contexts/ # Layer stack context +β”‚ └── contexts/ # Context providers (LayerStack, etc.) β”‚ β”œβ”€β”€ web/ # Web/mobile interface β”‚ β”œβ”€β”€ mobile/ # Mobile-optimized React app -β”‚ β”œβ”€β”€ components/ # Shared web components -β”‚ └── hooks/ # Web-specific hooks +β”‚ └── components/ # Shared web components β”‚ β”œβ”€β”€ cli/ # CLI tooling for batch automation β”‚ β”œβ”€β”€ commands/ # CLI command implementations -β”‚ β”œβ”€β”€ services/ # Playbook and batch processing -β”‚ └── index.ts # CLI entry point +β”‚ └── services/ # Playbook and batch processing β”‚ β”œβ”€β”€ prompts/ # System prompts (editable .md files) -β”‚ β”œβ”€β”€ wizard-*.md # Wizard conversation prompts -β”‚ β”œβ”€β”€ autorun-*.md # Auto Run default prompts -β”‚ └── index.ts # Central exports β”‚ β”œβ”€β”€ shared/ # Shared types and utilities -β”‚ β”œβ”€β”€ types.ts # Common type definitions -β”‚ └── templateVariables.ts # Template variable processing β”‚ └── docs/ # Mintlify documentation (docs.runmaestro.ai) - β”œβ”€β”€ docs.json # Navigation and configuration - β”œβ”€β”€ screenshots/ # All documentation screenshots - └── *.md # Documentation pages ``` --- @@ -174,6 +181,52 @@ src/ ## Critical Implementation Guidelines +### Error Handling & Sentry + +Maestro uses Sentry for error tracking. Field data from production crashes is invaluable for improving code quality. + +**DO let exceptions bubble up:** +```typescript +// WRONG - silently swallowing errors hides bugs from Sentry +try { + await riskyOperation(); +} catch (e) { + console.error(e); // Lost to the void +} + +// CORRECT - let unhandled exceptions reach Sentry +await riskyOperation(); // Crashes are reported automatically +``` + +**DO handle expected/recoverable errors explicitly:** +```typescript +// CORRECT - known failure modes should be handled gracefully +try { + await fetchUserData(); +} catch (e) { + if (e.code === 'NETWORK_ERROR') { + showOfflineMessage(); // Expected, recoverable + } else { + throw e; // Unexpected - let Sentry capture it + } +} +``` + +**DO use Sentry utilities for explicit reporting:** +```typescript +import { captureException, captureMessage } from '../utils/sentry'; + +// Report exceptions with context +await captureException(error, { userId, operation: 'sync' }); + +// Report notable events that aren't crashes +await captureMessage('Unusual state detected', 'warning', { state }); +``` + +**Key files:** `src/main/utils/sentry.ts`, `src/renderer/components/ErrorBoundary.tsx` + +--- + ### SSH Remote Execution Awareness **IMPORTANT:** When implementing any feature that spawns agent processes (e.g., context grooming, group chat, batch operations), you MUST support SSH remote execution.