Skip to content

Conversation

@greghughespdx
Copy link

@greghughespdx greghughespdx commented Jan 2, 2026

Watches the specs directory for changes made outside the app (CLI, AI agents, etc.) and smoothly update task views in real-time without requiring manual refresh.

Features:

  • File watcher using chokidar monitors specs directory
  • Surgical Zustand store updates (no UI flash)
  • Debounced updates (400ms) to handle rapid changes
  • Opt-in via Settings > Agent Settings > "Auto-Sync External Changes"
  • Detects: new tasks, removed tasks, and task modifications

Implementation:

  • Extended FileWatcher class with specs directory watching
  • Added IPC channels for spec events (added/removed/updated)
  • Added TASK_GET handler for fetching individual tasks
  • Surgical store handlers in task-store.ts
  • Settings toggle with dynamic watcher start/stop

🤖 Generated with Claude Code

Base Branch

  • This PR targets the develop branch (required for all feature/fix PRs)
  • This PR targets main (hotfix only - maintainers)

Description

Adds real-time sync for tasks created or modified outside the app (via CLI, AI agents, etc.) so users don't need to refresh manually. Added Settings feature to allow the user to toggle the feature on or off in Settings/Agents

Related Issue

N/A

Type of Change

  • 🐛 Bug fix
  • ✨ New feature
  • 📚 Documentation
  • ♻️ Refactor
  • 🧪 Test

Area

  • Frontend
  • Backend
  • Fullstack

Commit Message Format

(format was followed in commit)

Checklist

  • I've synced with develop branch
  • I've tested my changes locally
  • I've followed the code principles (SOLID, DRY, KISS)
  • My PR is small and focused (< 400 lines ideally)

CI/Testing Requirements

  • All CI checks pass
  • All existing tests pass
  • New features include test coverage
  • Bug fixes include regression tests

Screenshots

SCR-20260101-nsct-2

Feature Toggle

  • Behind localStorage flag: use_feature_name
  • Behind settings toggle
  • Behind environment variable/config
  • N/A - Feature is complete and ready for all users

Breaking Changes

Breaking: No


This is my first ever PR - it feels good to make one - thanks for building Auto-Claude!

Summary by CodeRabbit

  • New Features
    • Added "Watch Filesystem for External Changes" toggle in General Settings to enable/disable live spec monitoring.
    • Automatically detects and emits spec added/removed/updated events and syncs the UI without requiring manual refresh.
    • Supports fetching a single task by spec ID and applies targeted (surgical) updates to the task list instead of full reloads.

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

greghughespdx and others added 4 commits January 1, 2026 21:29
Watch the specs directory for changes made outside the app (CLI, AI agents, etc.)
and update task views in real-time without requiring manual refresh.

Features:
- File watcher using chokidar monitors specs directory
- Surgical Zustand store updates (no UI flash)
- Debounced updates (400ms) to handle rapid changes
- Opt-in via Settings > Agent Settings > "Auto-Sync External Changes"
- Detects: new tasks, removed tasks, and task modifications

Implementation:
- Extended FileWatcher class with specs directory watching
- Added IPC channels for spec events (added/removed/updated)
- Added TASK_GET handler for fetching individual tasks
- Surgical store handlers in task-store.ts
- Settings toggle with dynamic watcher start/stop

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
- Extract duplicate file event handlers into handleSpecFileEvent helper
- Add optimized getTask() method to ProjectStore for single-task loading
- Add loadTaskFromSpecFolder() private method to avoid loading all tasks
- Update TASK_GET handler to use efficient single-task loader

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Addresses PR feedback - prevents memory leaks by clearing pending
setTimeout callbacks when unwatchSpecsDirectory() or
unwatchAllSpecsDirectories() is called.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@gemini-code-assist
Copy link
Contributor

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 2, 2026

📝 Walkthrough

Walkthrough

Adds a specs-watching subsystem to the frontend: FileWatcher now monitors spec directories (add/remove/update with debounced updates), new IPC channels and handlers propagate spec events, ProjectStore.getTask enables single-spec retrieval, and renderer/store layers react to spec events. Settings toggle controls watcher lifecycle.

Changes

Cohort / File(s) Summary
File Watcher Core
apps/frontend/src/main/file-watcher.ts
Adds specs watching subsystem: SpecsWatcherInfo, PendingUpdate, DEBOUNCE_MS, watchSpecsDirectory(), unwatchSpecsDirectory(), unwatchAllSpecsDirectories(), isWatchingSpecs(), private debouncedSpecUpdate() and pending-update handling. Emits spec-added, spec-removed, spec-updated. Exports fileWatcher singleton.
IPC Event Forwarding
apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
Registers listeners on fileWatcher for spec-added, spec-removed, spec-updated and forwards them to renderer via IPC_CHANNELS.TASK_SPEC_ADDED, TASK_SPEC_REMOVED, TASK_SPEC_UPDATED. (Handlers duplicated in file—watch for repeated registration.)
Settings Watcher Integration
apps/frontend/src/main/ipc-handlers/settings-handlers.ts
On SETTINGS_SAVE, reacts to watchFilesystemForExternalChanges: enables watchers for each project via fileWatcher.watchSpecsDirectory() or disables all via fileWatcher.unwatchAllSpecsDirectories().
Task CRUD & IPC
apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
Adds isFilesystemWatchingEnabled cache + invalidateWatchingSettingsCache(); conditionally starts spec watcher on TASK_LIST if enabled; registers TASK_GET handler for single-task retrieval by specId. Exports invalidateWatchingSettingsCache.
Data Access Layer
apps/frontend/src/main/project-store.ts
Adds getTask(projectId, specId) and helper loadTaskFromSpecFolder() to load a single Task from a spec folder without full enumeration.
Preload API & Types
apps/frontend/src/preload/api/task-api.ts, apps/frontend/src/shared/types/ipc.ts
Exposes getTask(projectId, specId) over IPC and adds three event listener APIs: onSpecAdded, onSpecRemoved, onSpecUpdated with proper callbacks and cleanup. Adds TASK_GET and TASK_SPEC_* channels.
Renderer Store & IPC Hooks
apps/frontend/src/renderer/stores/task-store.ts, apps/frontend/src/renderer/hooks/useIpc.ts
Adds removeTaskBySpecId() and handlers handleSpecAdded(), handleSpecRemoved(), handleSpecUpdated() that perform surgical fetches via getTask. Registers/cleans up IPC listeners in useIpc.
UI Settings & i18n
apps/frontend/src/renderer/components/settings/GeneralSettings.tsx, apps/frontend/src/shared/i18n/locales/*/settings.json
Adds UI toggle for watchFilesystemForExternalChanges and i18n keys general.watchFilesystem / general.watchFilesystemDescription.
Config & Types
apps/frontend/src/shared/constants/config.ts, apps/frontend/src/shared/types/settings.ts
Adds watchFilesystemForExternalChanges to DEFAULT_APP_SETTINGS (false) and optional field to AppSettings.
Mocks & Minor Formatting
apps/frontend/src/renderer/lib/mocks/task-mock.ts, apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
Mock adds getTask() stub and spec event listener stubs. Minor JSX formatting change in AdvancedSettings.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    participant UI as Renderer UI
    participant Main as Main (IPC)
    participant FileWatcher as FileWatcher
    participant ProjectStore as ProjectStore
    participant TaskStore as Task Store

    UI->>Main: SETTINGS_SAVE (watchFilesystemForExternalChanges = true)
    Main->>FileWatcher: watchSpecsDirectory(projectId, specsPath)
    Note over FileWatcher: Watches spec directories\n(add/remove file/dir, changes to plan/metadata)
    FileWatcher->>FileWatcher: Debounce updates for spec folders
    FileWatcher-->>Main: emit 'spec-updated'(projectId, specId)
    Main-->>Renderer: IPC TASK_SPEC_UPDATED(projectId, specId)
    Renderer->>TaskStore: handleSpecUpdated(projectId, specId)
    TaskStore->>Main: IPC TASK_GET(projectId, specId)
    Main->>ProjectStore: getTask(projectId, specId)
    ProjectStore-->>Main: Task | null
    Main-->>TaskStore: IPC result (Task | null)
    TaskStore->>TaskStore: Update store (replace/add task)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested labels

feature, area/frontend, 🔄 Checking, size/XL

Suggested reviewers

  • AlexMadera
  • MikeeBuilds
  • AndyMik90

Poem

🐰✨
I watch the specs hop in the night, so spry and fleet,
Debounces keep their footsteps soft and neat,
I nudge the store to fetch what changed just so,
A little rabbit keeps your tasks in flow. 🥕🪄

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: add real-time task sync for external changes' directly and clearly summarizes the main feature being added—real-time synchronization of task specs when changed externally.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1e1c8c and 1d97a2a.

📒 Files selected for processing (5)
  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/shared/i18n/locales/fr/settings.json
🧰 Additional context used
📓 Path-based instructions (4)
apps/frontend/src/**/*.{ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use i18n translation keys for all user-facing text in the frontend instead of hardcoded strings

Files:

  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use useTranslation() hook with namespace prefixes (e.g., 'navigation:items.key') for accessing translation strings in React components

Files:

  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
apps/frontend/src/shared/i18n/locales/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/shared/i18n/locales/**/*.json: Store translation strings in namespace-organized JSON files at apps/frontend/src/shared/i18n/locales/{lang}/*.json for each supported language
When implementing new frontend features, add translation keys to all language files (minimum: en/.json and fr/.json)

Files:

  • apps/frontend/src/shared/i18n/locales/fr/settings.json
🧠 Learnings (2)
📚 Learning: 2025-12-30T16:38:36.314Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T16:38:36.314Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : When implementing new frontend features, add translation keys to all language files (minimum: en/*.json and fr/*.json)

Applied to files:

  • apps/frontend/src/shared/i18n/locales/fr/settings.json
📚 Learning: 2025-12-30T16:38:36.314Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T16:38:36.314Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Store translation strings in namespace-organized JSON files at `apps/frontend/src/shared/i18n/locales/{lang}/*.json` for each supported language

Applied to files:

  • apps/frontend/src/shared/i18n/locales/fr/settings.json
🧬 Code graph analysis (3)
apps/frontend/src/renderer/stores/task-store.ts (1)
apps/frontend/src/renderer/stores/project-store.ts (1)
  • useProjectStore (44-206)
apps/frontend/src/main/project-store.ts (3)
apps/frontend/src/shared/types/task.ts (3)
  • Task (237-257)
  • ImplementationPlan (260-275)
  • TaskMetadata (171-235)
apps/frontend/src/shared/constants/config.ts (2)
  • getSpecsDir (106-109)
  • AUTO_BUILD_PATHS (83-100)
apps/frontend/src/renderer/components/task-detail/TaskMetadata.tsx (1)
  • TaskMetadata (50-241)
apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts (5)
apps/frontend/src/main/settings-utils.ts (1)
  • readSettingsFile (29-43)
apps/frontend/src/shared/types/settings.ts (1)
  • AppSettings (217-270)
apps/frontend/src/shared/constants/config.ts (2)
  • DEFAULT_APP_SETTINGS (19-54)
  • getSpecsDir (106-109)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (958-958)
apps/frontend/src/main/file-watcher.ts (1)
  • fileWatcher (310-310)
🔇 Additional comments (12)
apps/frontend/src/shared/i18n/locales/fr/settings.json (1)

103-104: French and English translations are complete and appropriately implemented.

Both translation keys exist in en/settings.json and fr/settings.json, satisfying the coding guidelines requirement. The English translations ("Auto-Sync External Changes" and the description) accurately describe the filesystem watching feature, and the French translations are well-written and contextually appropriate.

apps/frontend/src/main/ipc-handlers/settings-handlers.ts (1)

205-233: LGTM! Watcher lifecycle management is correctly implemented.

The filesystem watcher setting change handler properly:

  • Invalidates the cache to ensure TASK_LIST picks up the new setting
  • Starts watchers for all projects when enabled (with duplicate checks via isWatchingSpecs)
  • Stops all watchers when disabled
  • Handles errors gracefully without breaking the settings save operation
apps/frontend/src/main/project-store.ts (3)

309-330: LGTM! Optimized single-task retrieval is well-implemented.

The getTask method provides an efficient alternative to scanning all specs:

  • Validates project existence before attempting to load
  • Checks if the spec folder exists to fail fast
  • Delegates to loadTaskFromSpecFolder with appropriate parameters

This enables surgical updates for the filesystem watcher without full task list reloads.


332-411: LGTM! Requirements.json fallback is now present.

The loadTaskFromSpecFolder method now includes the requirements.json fallback for descriptions (lines 377-411), addressing the past review concern. The extraction logic is sophisticated and handles edge cases like investigation titles and instruction text.


413-480: LGTM! Task construction and location handling are correct.

The method properly:

  • Reads task metadata and determines status/review reason
  • Extracts subtasks and staged status
  • Derives the title from various sources (plan, spec.md heading)
  • Uses the location parameter correctly in the returned Task object
  • Handles errors gracefully by logging and returning null

The location parameter has a sensible default ('main') since getTask specifically loads from the main specs directory.

apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts (3)

13-38: LGTM! Settings cache addresses I/O overhead concern.

The caching mechanism effectively reduces disk reads:

  • 5-second TTL balances freshness vs performance
  • Explicit invalidation via invalidateWatchingSettingsCache() ensures settings changes are picked up immediately
  • Simple implementation without over-engineering

This addresses the past review concern about reading settings on every TASK_LIST call.


54-67: LGTM! Watcher initialization is properly guarded.

The watcher start logic correctly:

  • Validates the project exists
  • Checks if watching is enabled via the cached setting
  • Prevents duplicate watchers with isWatchingSpecs check
  • Handles errors without blocking the TASK_LIST response

73-93: LGTM! TASK_GET handler enables surgical task fetches.

The new handler properly:

  • Uses projectStore.getTask for optimized single-task loading
  • Returns a consistent IPCResult structure
  • Includes diagnostic logging for debugging
  • Handles the not-found case by returning null in the data field

This enables the filesystem watcher to surgically update individual tasks without reloading the entire task list.

apps/frontend/src/renderer/stores/task-store.ts (4)

168-180: LGTM! removeTaskBySpecId is correctly implemented.

The action properly:

  • Finds the task by specId
  • Handles the not-found case gracefully
  • Clears the selection if the removed task was selected (prevents dangling references)
  • Returns updated state with the task filtered out

561-593: LGTM! handleSpecAdded correctly implements surgical updates with validation.

The handler properly:

  • Validates the event is for the currently selected project (addresses past review concern)
  • Fetches only the new task via window.electronAPI.getTask (surgical update)
  • Handles the duplicate case by updating instead of adding
  • Falls back to a full reload only if the surgical fetch fails
  • Includes appropriate logging for debugging

599-611: LGTM! handleSpecRemoved is simple and correct.

The handler properly:

  • Validates the event is for the currently selected project (addresses past review concern)
  • Removes the task via removeTaskBySpecId
  • Includes logging for debugging

617-647: LGTM! handleSpecUpdated efficiently handles surgical updates.

The handler properly:

  • Validates the event is for the currently selected project (addresses past review concern)
  • Checks if the task exists in the store before fetching (optimization)
  • Fetches only the updated task via window.electronAPI.getTask
  • Updates the task in place without reloading all tasks
  • Logs errors without triggering a full reload (task remains with old data, which is acceptable)

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.

Copy link
Contributor

@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: 5

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 344ec65 and d1e1c8c.

⛔ Files ignored due to path filters (1)
  • apps/frontend/package-lock.json is excluded by !**/package-lock.json, !**/package-lock.json
📒 Files selected for processing (16)
  • apps/frontend/src/main/file-watcher.ts
  • apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/preload/api/task-api.ts
  • apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
  • apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
  • apps/frontend/src/renderer/hooks/useIpc.ts
  • apps/frontend/src/renderer/lib/mocks/task-mock.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/shared/i18n/locales/en/settings.json
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/shared/types/settings.ts
🧰 Additional context used
📓 Path-based instructions (4)
apps/frontend/src/shared/i18n/locales/**/*.json

📄 CodeRabbit inference engine (CLAUDE.md)

apps/frontend/src/shared/i18n/locales/**/*.json: Store translation strings in namespace-organized JSON files at apps/frontend/src/shared/i18n/locales/{lang}/*.json for each supported language
When implementing new frontend features, add translation keys to all language files (minimum: en/.json and fr/.json)

Files:

  • apps/frontend/src/shared/i18n/locales/en/settings.json
apps/frontend/src/**/*.{ts,tsx,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Always use i18n translation keys for all user-facing text in the frontend instead of hardcoded strings

Files:

  • apps/frontend/src/shared/types/settings.ts
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/renderer/lib/mocks/task-mock.ts
  • apps/frontend/src/renderer/hooks/useIpc.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/main/file-watcher.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
  • apps/frontend/src/preload/api/task-api.ts
apps/frontend/src/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use useTranslation() hook with namespace prefixes (e.g., 'navigation:items.key') for accessing translation strings in React components

Files:

  • apps/frontend/src/shared/types/settings.ts
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/renderer/lib/mocks/task-mock.ts
  • apps/frontend/src/renderer/hooks/useIpc.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/main/file-watcher.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
  • apps/frontend/src/preload/api/task-api.ts
apps/frontend/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

apps/frontend/**/*.{ts,tsx}: Review React patterns and TypeScript type safety.
Check for proper state management and component composition.

Files:

  • apps/frontend/src/shared/types/settings.ts
  • apps/frontend/src/shared/constants/ipc.ts
  • apps/frontend/src/renderer/lib/mocks/task-mock.ts
  • apps/frontend/src/renderer/hooks/useIpc.ts
  • apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts
  • apps/frontend/src/renderer/stores/task-store.ts
  • apps/frontend/src/renderer/components/settings/GeneralSettings.tsx
  • apps/frontend/src/main/ipc-handlers/settings-handlers.ts
  • apps/frontend/src/shared/constants/config.ts
  • apps/frontend/src/renderer/components/settings/AdvancedSettings.tsx
  • apps/frontend/src/shared/types/ipc.ts
  • apps/frontend/src/main/file-watcher.ts
  • apps/frontend/src/main/project-store.ts
  • apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts
  • apps/frontend/src/preload/api/task-api.ts
🧠 Learnings (2)
📚 Learning: 2025-12-30T16:38:36.314Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T16:38:36.314Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : When implementing new frontend features, add translation keys to all language files (minimum: en/*.json and fr/*.json)

Applied to files:

  • apps/frontend/src/shared/i18n/locales/en/settings.json
📚 Learning: 2025-12-30T16:38:36.314Z
Learnt from: CR
Repo: AndyMik90/Auto-Claude PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-30T16:38:36.314Z
Learning: Applies to apps/frontend/src/shared/i18n/locales/**/*.json : Store translation strings in namespace-organized JSON files at `apps/frontend/src/shared/i18n/locales/{lang}/*.json` for each supported language

Applied to files:

  • apps/frontend/src/shared/i18n/locales/en/settings.json
🧬 Code graph analysis (6)
apps/frontend/src/renderer/components/settings/GeneralSettings.tsx (1)
apps/frontend/src/renderer/components/settings/utils/hookProxyFactory.ts (1)
  • settings (15-15)
apps/frontend/src/main/ipc-handlers/settings-handlers.ts (3)
apps/frontend/src/main/project-store.ts (1)
  • projectStore (921-921)
apps/frontend/src/main/file-watcher.ts (1)
  • fileWatcher (310-310)
apps/frontend/src/shared/constants/config.ts (1)
  • getSpecsDir (106-109)
apps/frontend/src/shared/types/ipc.ts (1)
apps/frontend/src/shared/types/task.ts (1)
  • Task (237-257)
apps/frontend/src/main/project-store.ts (2)
apps/frontend/src/shared/types/task.ts (4)
  • Task (237-257)
  • ImplementationPlan (260-275)
  • TaskMetadata (171-235)
  • PlanSubtask (285-294)
apps/frontend/src/shared/constants/config.ts (2)
  • getSpecsDir (106-109)
  • AUTO_BUILD_PATHS (83-100)
apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts (1)
apps/frontend/src/main/file-watcher.ts (1)
  • fileWatcher (310-310)
apps/frontend/src/preload/api/task-api.ts (2)
apps/frontend/src/shared/types/task.ts (1)
  • Task (237-257)
apps/frontend/src/shared/constants/ipc.ts (1)
  • IPC_CHANNELS (6-488)
🔇 Additional comments (24)
apps/frontend/src/shared/constants/ipc.ts (1)

51-56: LGTM! Clean IPC channel additions.

The new IPC channel constants follow the existing naming conventions and are logically grouped with related task operations. The spec lifecycle events (added/removed/updated) and the single-task retrieval channel (TASK_GET) are clearly named and properly namespaced.

apps/frontend/src/renderer/components/settings/GeneralSettings.tsx (1)

166-182: LGTM! Well-implemented settings toggle.

The filesystem watching toggle follows the established patterns in this component:

  • Properly uses i18n translation keys (no hardcoded strings)
  • Correctly handles undefined with ?? false fallback
  • Maintains type safety with proper TypeScript types
  • Consistent layout and structure with other toggles
apps/frontend/src/main/ipc-handlers/agent-events-handlers.ts (1)

203-230: LGTM! Spec event forwarding handlers are well-implemented.

The new event listeners for spec lifecycle events (added/removed/updated) follow the established pattern in this file:

  • Proper null checks for mainWindow before sending
  • Consistent use of IPC channel constants
  • Helpful console logging for debugging
  • Clean forwarding from fileWatcher to renderer
apps/frontend/src/shared/constants/config.ts (1)

51-53: LGTM! Well-documented opt-in feature flag.

The new watchFilesystemForExternalChanges setting is properly documented and defaults to false, making it a safe opt-in feature. The descriptive comment clearly explains its purpose.

apps/frontend/src/shared/types/settings.ts (1)

268-269: LGTM! Type definition is correct.

The new optional field is properly typed and documented, following the existing conventions in the AppSettings interface.

apps/frontend/src/main/ipc-handlers/settings-handlers.ts (2)

6-6: LGTM! Clean imports for the new functionality.

The imports for getSpecsDir, fileWatcher, and projectStore are correctly added to support the filesystem watching feature.

Also applies to: 17-18


204-229: LGTM! Watcher management logic is well-structured.

The logic correctly handles enabling/disabling filesystem watching:

  • When enabled: starts watchers for all projects not currently being watched
  • When disabled: stops all watchers globally
  • Error handling with logging is present
  • The isWatchingSpecs check prevents duplicate watchers

Note: The watcher startup operations use .catch() without await, which means the settings save completes before all watchers are fully started. This is likely intentional to avoid blocking the UI, and errors are properly logged.

apps/frontend/src/renderer/hooks/useIpc.ts (3)

2-2: LGTM! Handlers correctly imported from task-store.

The spec event handlers are properly imported to support the new filesystem watching feature.


169-189: LGTM! Spec event listeners follow existing patterns.

The three new IPC listeners (onSpecAdded, onSpecRemoved, onSpecUpdated) are implemented consistently with existing event listeners:

  • Each logs a debug message for traceability
  • Calls the appropriate handler from task-store
  • Unused _specPath parameter is correctly prefixed

204-206: LGTM! Cleanup functions properly registered.

The cleanup functions for the new spec listeners are correctly added to the effect's cleanup section, ensuring no memory leaks.

apps/frontend/src/renderer/lib/mocks/task-mock.ts (2)

14-17: LGTM! Mock method matches the new API.

The getTask mock correctly returns a success response with null data, which is appropriate for a browser mock that doesn't have access to actual task data.


99-104: LGTM! Spec event listener mocks are correctly implemented.

The three new no-op event listeners (onSpecAdded, onSpecRemoved, onSpecUpdated) follow the same pattern as existing event listener mocks, returning no-op cleanup functions. This enables the code to run in browser environments during development.

apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts (1)

55-75: LGTM!

The new TASK_GET handler correctly uses the optimized single-task loader and follows the established IPCResult pattern. The logging is helpful for debugging, and returning success: true with null data for missing tasks is consistent with other handlers.

apps/frontend/src/shared/types/ipc.ts (2)

150-150: LGTM!

The getTask method signature correctly returns Task | null wrapped in IPCResult, consistent with the handler implementation.


666-676: LGTM!

The spec event listener signatures are well-defined with appropriate callback parameters and cleanup return types. The interface additions align with the implementation in task-api.ts.

apps/frontend/src/main/project-store.ts (1)

309-330: LGTM!

The getTask method provides an efficient single-task lookup by directly accessing the spec folder instead of scanning all tasks. The null checks and path construction are correct.

apps/frontend/src/renderer/stores/task-store.ts (2)

167-179: LGTM!

The removeTaskBySpecId implementation correctly handles selection clearing when the removed task was selected, preventing stale selection state.


598-625: LGTM!

The handleSpecUpdated handler correctly checks if the task exists before fetching and appropriately logs when a task is not found. The surgical update pattern avoids unnecessary full reloads.

apps/frontend/src/preload/api/task-api.ts (2)

89-91: LGTM!

The getTask implementation correctly invokes the IPC channel with both projectId and specId parameters.


294-342: LGTM!

The spec event listener implementations follow the established pattern consistently:

  • Proper handler extraction of IPC event arguments
  • Correct channel subscriptions matching the interface
  • Cleanup functions properly remove listeners to prevent memory leaks
apps/frontend/src/main/file-watcher.ts (4)

13-24: LGTM!

The new interfaces are well-structured. SpecsWatcherInfo tracks the necessary state for cleanup, and PendingUpdate correctly captures the debounce context including the timeout handle.


151-231: Well-implemented specs directory watching with appropriate filtering.

The implementation correctly:

  • Cleans up existing watchers before starting new ones (line 153)
  • Uses depth: 1 to limit file system traversal (line 167)
  • Filters addDir/unlinkDir events to only direct children (lines 184-186, 195-197)
  • Extracts specId correctly from file paths (lines 212-218)
  • Uses awaitWriteFinish to handle partial writes

233-254: LGTM!

The debounce implementation correctly handles rapid successive updates by clearing existing timeouts before scheduling new ones. The 400ms debounce window is reasonable for coalescing file system events.


256-306: Proper cleanup of pending timeouts prevents memory leaks.

Both unwatchSpecsDirectory and unwatchAllSpecsDirectories correctly clear pending debounced timeouts before closing watchers, preventing orphaned timers from firing after cleanup.

Comment on lines 16 to 20
function isFilesystemWatchingEnabled(): boolean {
const savedSettings = readSettingsFile() as Partial<AppSettings> | undefined;
const settings = { ...DEFAULT_APP_SETTINGS, ...savedSettings };
return settings.watchFilesystemForExternalChanges ?? false;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick | 🔵 Trivial

Settings read on every TASK_LIST call may cause I/O overhead.

isFilesystemWatchingEnabled() reads the settings file synchronously from disk on every TASK_LIST invocation. For frequently called operations, consider caching the setting value and invalidating on settings change events.

🤖 Prompt for AI Agents
In apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts around lines 16 to
20, isFilesystemWatchingEnabled() currently reads the settings file on every
TASK_LIST call causing I/O overhead; change this to read once and cache the
resolved boolean in a module-level variable (initialize at module load or first
call), have the function return the cached value, and add an explicit
invalidation/update path that listens for settings change events (e.g.,
SETTINGS_UPDATED IPC or the existing settings write flow) to refresh the cached
value from disk so the cached value stays correct after user changes.

Comment on lines +35 to +49

// Start watching the specs directory for this project (if enabled in settings)
const project = projectStore.getProject(projectId);
if (project && isFilesystemWatchingEnabled()) {
const specsBaseDir = getSpecsDir(project.autoBuildPath);
const specsPath = path.join(project.path, specsBaseDir);

// Only start watching if not already watching
if (!fileWatcher.isWatchingSpecs(projectId)) {
console.log(`[IPC] TASK_LIST starting specs watcher for project ${projectId}`);
fileWatcher.watchSpecsDirectory(projectId, specsPath).catch((err) => {
console.error(`[IPC] Failed to start specs watcher for project ${projectId}:`, err);
});
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

rg -n "unwatchSpecsDirectory" --type ts

Repository: AndyMik90/Auto-Claude

Length of output: 265


🏁 Script executed:

cat -n apps/frontend/src/main/file-watcher.ts | sed -n '140,170p'

Repository: AndyMik90/Auto-Claude

Length of output: 1469


🏁 Script executed:

cat -n apps/frontend/src/main/file-watcher.ts | sed -n '259,290p'

Repository: AndyMik90/Auto-Claude

Length of output: 1309


🏁 Script executed:

rg -n "unwatchSpecsDirectory" --type ts -B 5 -A 5

Repository: AndyMik90/Auto-Claude

Length of output: 1958


🏁 Script executed:

rg -n "unwatchSpecsDirectory\|removeProject\|closeProject\|onProjectRemoved" --type ts | head -50

Repository: AndyMik90/Auto-Claude

Length of output: 47


🏁 Script executed:

rg -n "watchSpecsDirectory|unwatchSpecsDirectory" --type ts -A 2 -B 2

Repository: AndyMik90/Auto-Claude

Length of output: 2400


🏁 Script executed:

cat -n apps/frontend/src/main/ipc-handlers/settings-handlers.ts | sed -n '200,240p'

Repository: AndyMik90/Auto-Claude

Length of output: 2161


🏁 Script executed:

rg -n "unwatchAllSpecsDirectories\|stopAll" --type ts

Repository: AndyMik90/Auto-Claude

Length of output: 47


🏁 Script executed:

cat -n apps/frontend/src/main/file-watcher.ts | sed -n '290,310p'

Repository: AndyMik90/Auto-Claude

Length of output: 779


🏁 Script executed:

rg -n "removeProject|deleteProject|closeProject" --type ts | head -30

Repository: AndyMik90/Auto-Claude

Length of output: 3284


🏁 Script executed:

cat -n apps/frontend/src/main/ipc-handlers/project-handlers.ts | sed -n '180,210p'

Repository: AndyMik90/Auto-Claude

Length of output: 1248


🏁 Script executed:

cat -n apps/frontend/src/main/project-store.ts | sed -n '120,150p'

Repository: AndyMik90/Auto-Claude

Length of output: 849


🏁 Script executed:

rg -n "fileWatcher" apps/frontend/src/main/ipc-handlers/project-handlers.ts

Repository: AndyMik90/Auto-Claude

Length of output: 47


🏁 Script executed:

cat -n apps/frontend/src/main/ipc-handlers/project-handlers.ts | head -50

Repository: AndyMik90/Auto-Claude

Length of output: 1984


🏁 Script executed:

rg -n "fileWatcher\|unwatchSpecsDirectory" apps/frontend/src/main/ipc-handlers/ --type ts

Repository: AndyMik90/Auto-Claude

Length of output: 47


🏁 Script executed:

cat -n apps/frontend/src/main/project-store.ts | sed -n '1,50p'

Repository: AndyMik90/Auto-Claude

Length of output: 1925


Missing watcher cleanup on project removal.

The watcher is properly cleaned up when the watchFilesystemForExternalChanges setting is toggled off (all watchers are stopped via unwatchAllSpecsDirectories). However, when a project is removed from the UI, the corresponding watcher is not cleaned up. The PROJECT_REMOVE handler in project-handlers.ts should call fileWatcher.unwatchSpecsDirectory(projectId) to prevent orphaned watchers.

🤖 Prompt for AI Agents
In apps/frontend/src/main/ipc-handlers/task/crud-handlers.ts around lines 35 to
49: the code starts a specs directory watcher for a project but review notes
that watchers are not cleaned up when a project is removed; update the
PROJECT_REMOVE handler in
apps/frontend/src/main/ipc-handlers/project-handlers.ts to call
fileWatcher.unwatchSpecsDirectory(projectId) (preferably only if
fileWatcher.isWatchingSpecs(projectId) is true) when a project is removed, and
wrap the call in a try/catch (or handle the returned promise) to log any errors
so the watcher is reliably cleaned up without crashing the app.

@AndyMik90 AndyMik90 self-assigned this Jan 2, 2026
@AlexMadera AlexMadera self-assigned this Jan 2, 2026
- Add French translations for watchFilesystem settings keys
- Validate projectId in spec event handlers to prevent cross-project modifications
- Cache filesystem watching setting with 5s TTL to avoid disk I/O
- Add requirements.json fallback in loadTaskFromSpecFolder
- Pass location parameter correctly in loadTaskFromSpecFolder

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
@MikeeBuilds MikeeBuilds added feature New feature or request area/frontend This is frontend only size/XL Extra large (1000+ lines) ❌ MERGE CONFLICTS labels Jan 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/frontend This is frontend only feature New feature or request ❌ MERGE CONFLICTS size/XL Extra large (1000+ lines)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants