- Introduced a new POST /discard-changes endpoint to discard all uncommitted changes in a worktree, including resetting staged changes, discarding modifications to tracked files, and removing untracked files.
- Implemented a corresponding handler in the UI to confirm and execute the discard operation, enhancing user control over worktree changes.
- Added a ViewWorktreeChangesDialog component to display changes in the worktree, improving the user experience for managing worktree states.
- Updated the WorktreePanel and WorktreeActionsDropdown components to integrate the new functionality, allowing users to view and discard changes directly from the UI.
This update streamlines the management of worktree changes, providing users with essential tools for version control.
- Updated createDiffsHandler, createFileDiffHandler, createInfoHandler, createStatusHandler, and auto-mode service to sanitize featureId when constructing worktree paths.
- Ensured consistent handling of featureId to prevent issues with invalid characters in branch names.
- Added branchName support in UI components to enhance feature visibility and management.
This change improves the robustness of worktree operations and enhances user experience by ensuring valid paths are used throughout the application.
- Updated auto mode handlers to support branch-specific operations, allowing for better management of features across different worktrees.
- Introduced normalization of branch names to handle undefined values gracefully.
- Enhanced status and response messages to reflect the current worktree context.
- Updated the auto mode service to manage state and concurrency settings per worktree, improving user experience and flexibility.
- Added UI elements to display current max concurrency for auto mode in both board and mobile views.
This update aims to streamline the auto mode experience, making it more intuitive for users working with multiple branches and worktrees.
* fix: prevent refresh button from overlapping close button in Dev Server dialog
Use compact mode for DialogContent and add right padding to the header
to ensure the refresh button doesn't overlap with the dialog close button.
Fixes#579
* fix: restore p-0 to prevent unwanted padding from compact mode
* fix: convert OpenCode model format to CLI slash format
The OpenCode CLI expects models in provider/model format (e.g., opencode/big-pickle),
but after commit 4b0d1399 changed model IDs from slash format to prefix format,
the buildCliArgs() method was not updated to convert back to CLI format.
Root cause:
- Commit 4b0d1399 changed OpenCode model IDs from opencode/model to opencode-model
- The old code used stripProviderPrefix() which just removed the prefix
- This resulted in bare model names (e.g., "big-pickle") being passed to CLI
- CLI interpreted "big-pickle" as a provider ID, causing ProviderModelNotFoundError
Fix:
- Updated buildCliArgs() to properly convert model formats for CLI
- Bare model names (after prefix strip) now get opencode/ prepended
- Models with slashes (dynamic providers) pass through unchanged
Model conversion examples:
- opencode-big-pickle → (stripped to) big-pickle → opencode/big-pickle
- opencode-github-copilot/gpt-4o → (stripped to) github-copilot/gpt-4o → github-copilot/gpt-4o
- google/gemini-2.5-pro → google/gemini-2.5-pro (unchanged)
* refactor: simplify OpenCode model format conversion logic
Address review feedback from Gemini Code Assist to reduce code repetition.
The conditional logic for handling models with/without slashes is now
unified into a simpler two-step approach:
1. Strip opencode- prefix if present
2. Prepend opencode/ if no slash exists
* feat: add Claude API provider profiles for alternative endpoints
Add support for managing multiple Claude-compatible API endpoints
(z.AI GLM, AWS Bedrock, etc.) through provider profiles in settings.
Features:
- New ClaudeApiProfile type with base URL, API key, model mappings
- Pre-configured z.AI GLM template with correct model names
- Profile selector in Settings > Claude > API Profiles
- Clean switching between profiles and direct Anthropic API
- Immediate persistence to prevent data loss on restart
Profile support added to all execution paths:
- Agent service (chat)
- Ideation service
- Auto-mode service (feature agents, enhancements)
- Simple query service (title generation, descriptions, etc.)
- Backlog planning, commit messages, spec generation
- GitHub issue validation, suggestions
Environment variables set when profile is active:
- ANTHROPIC_BASE_URL, ANTHROPIC_AUTH_TOKEN/API_KEY
- ANTHROPIC_DEFAULT_HAIKU/SONNET/OPUS_MODEL
- API_TIMEOUT_MS, CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC
* feat(platform): add cross-platform openInTerminal utility
Add utility function to open a terminal in a specified directory:
- macOS: Uses Terminal.app via AppleScript
- Windows: Tries Windows Terminal, falls back to cmd
- Linux: Tries common terminal emulators (gnome-terminal,
konsole, xfce4-terminal, xterm, x-terminal-emulator)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* feat(server): add open-in-terminal endpoint
Add POST /open-in-terminal endpoint to open a system terminal in the
worktree directory using the cross-platform openInTerminal utility.
The endpoint validates that worktreePath is provided and is an
absolute path for security.
Extracted from PR #558.
* feat(ui): add Open in Terminal action to worktree dropdown
Add "Open in Terminal" option to the worktree actions dropdown menu.
This opens the system terminal in the worktree directory.
Changes:
- Add openInTerminal method to http-api-client
- Add Terminal icon and menu item to worktree-actions-dropdown
- Add onOpenInTerminal prop to WorktreeTab component
- Add handleOpenInTerminal handler to use-worktree-actions hook
- Wire up handler in worktree-panel for both mobile and desktop views
Extracted from PR #558.
* fix(ui): open in terminal navigates to Automaker terminal view
Instead of opening the system terminal, the "Open in Terminal" action
now opens Automaker's built-in terminal with the worktree directory:
- Add pendingTerminalCwd state to app store
- Update use-worktree-actions to set pending cwd and navigate to /terminal
- Add effect in terminal-view to create session with pending cwd
This matches the original PR #558 behavior.
* feat(ui): add terminal open mode setting (new tab vs split)
Add a setting to choose how "Open in Terminal" behaves:
- New Tab: Creates a new tab named after the branch (default)
- Split: Adds to current tab as a split view
Changes:
- Add openTerminalMode setting to terminal state ('newTab' | 'split')
- Update terminal-view to respect the setting
- Add UI in Terminal Settings to toggle the behavior
- Rename pendingTerminalCwd to pendingTerminal with branch name
The new tab mode names tabs after the branch for easy identification.
The split mode is useful for comparing terminals side by side.
* feat(ui): display branch name in terminal header with git icon
- Move branch name display from tab name to terminal header
- Show full branch name (no truncation) with GitBranch icon
- Display branch name for both 'new tab' and 'split' modes
- Persist openTerminalMode setting to server and include in import/export
- Update settings dropdown to simplified "New Tab" label
* feat: add external terminal support with cross-platform detection
Add support for opening worktree directories in external terminals
(iTerm2, Warp, Ghostty, System Terminal, etc.) while retaining the
integrated terminal as the default option.
Changes:
- Add terminal detection for macOS, Windows, and Linux
- Add "Open in Terminal" split-button in worktree dropdown
- Add external terminal selection in Settings > Terminal
- Add default open mode setting (new tab vs split)
- Display branch name in terminal panel header
- Support 20+ terminals across platforms
Part of #558, Closes#550
* fix: address PR review comments
- Add nonce parameter to terminal navigation to allow reopening same
worktree multiple times
- Fix shell path escaping in editor.ts using single-quote wrapper
- Add validatePathParams middleware to open-in-external-terminal route
- Remove redundant validation block from createOpenInExternalTerminalHandler
- Remove unused pendingTerminal state and setPendingTerminal action
- Remove unused getTerminalInfo function from editor.ts
* fix: address PR review security and validation issues
- Add runtime type check for worktreePath in open-in-terminal handler
- Fix Windows Terminal detection using commandExists before spawn
- Fix xterm shell injection by using sh -c with escapeShellArg
- Use loose equality for null/undefined in useEffectiveDefaultTerminal
- Consolidate duplicate imports from open-in-terminal.js
* chore: update package-lock.json
* fix: use response.json() to prevent disposal race condition in E2E test
Replace response.body() with response.json() in open-existing-project.spec.ts
to fix the "Response has been disposed" error. This matches the pattern used
in other test files.
* Revert "fix: use response.json() to prevent disposal race condition in E2E test"
This reverts commit 36bdf8c24a.
* fix: address PR review feedback for terminal feature
- Add explicit validation for worktreePath in createOpenInExternalTerminalHandler
- Add aria-label to refresh button in terminal settings for accessibility
- Only show "no terminals" message when not refreshing
- Reset initialCwdHandledRef on failure to allow retries
- Use z.coerce.number() for nonce URL param to handle string coercion
- Preserve branchName when creating layout for empty tab
- Update getDefaultTerminal return type to allow null result
---------
Co-authored-by: Kacper <kacperlachowiczwp.pl@wp.pl>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This update modifies the list handler to skip PR assignment for the main worktree, preventing confusion when displaying PRs on the main branch tab. Additionally, the fallback logic for assigning stored metadata is refined to only apply if the PR state is 'OPEN', ensuring more accurate representation of PRs.
This commit introduces significant updates to the cursor model handling and auto mode features. The cursor model IDs have been standardized to a canonical format, ensuring backward compatibility while migrating legacy IDs. New endpoints for starting and stopping the auto mode loop have been added, allowing for better control over project-specific auto mode operations.
Key changes:
- Updated cursor model IDs to use the 'cursor-' prefix for consistency.
- Added new API endpoints: `/start` and `/stop` for managing auto mode.
- Enhanced the status endpoint to provide detailed project-specific auto mode information.
- Improved error handling and logging throughout the auto mode service.
- Migrated legacy model IDs to their canonical counterparts in various components.
This update aims to streamline the user experience and ensure a smooth transition for existing users while providing new functionalities.
* feat: add auto-login for dev mode and fix log box formatting
Add AUTOMAKER_AUTO_LOGIN environment variable that, when set to 'true',
automatically creates a session for web mode users without requiring
them to enter the API key. Useful for development environments.
Also fix formatting issues in console log boxes:
- API Key box: add right border, show auto-login status and tips
- Claude auth warning: add separator line, fix emoji spacing
- Server info box: use consistent 71-char width, proper padding
- Port conflict error: use same width, proper dynamic padding
Environment variables:
- AUTOMAKER_AUTO_LOGIN=true: Skip login prompt, auto-create session
- AUTOMAKER_API_KEY: Use a fixed API key (existing)
- AUTOMAKER_HIDE_API_KEY=true: Hide the API key banner (existing)
* fix: add production safeguard to auto-login and extract log box constant
- Add NODE_ENV !== 'production' check to prevent auto-login in production
- Extract magic number 67 to BOX_CONTENT_WIDTH constant in auth.ts and index.ts
- Document AUTOMAKER_AUTO_LOGIN env var in CLAUDE.md and README.md
* feat: add three viewing modes for app specification
Introduces View, Edit, and Source modes for the spec page:
- View: Clean read-only display with cards, badges, and accordions
- Edit: Structured form-based editor for all spec fields
- Source: Raw XML editor for advanced users
Also adds @automaker/spec-parser shared package for XML parsing
between server and client.
* fix: address PR review feedback
- Replace array index keys with stable UUIDs in array-field-editor,
features-section, and roadmap-section components
- Replace regex-based XML parsing with fast-xml-parser for robustness
- Simplify renderContent logic in spec-view by removing dead code paths
* fix: convert git+ssh URLs to https in package-lock.json
* fix: address PR review feedback for spec visualiser
- Remove unused RefreshCw import from spec-view.tsx
- Add explicit parsedSpec check in renderContent for robustness
- Hide save button in view mode since it's read-only
- Remove GripVertical drag handles since drag-and-drop is not implemented
- Rename Map imports to MapIcon to avoid shadowing global Map
- Escape tagName in xml-utils.ts RegExp functions for safety
- Add aria-label attributes for accessibility on mode tabs
* fix: address additional PR review feedback
- Fix Textarea controlled/uncontrolled warning with default value
- Preserve IDs in useEffect sync to avoid unnecessary remounts
- Consolidate lucide-react imports
- Add JSDoc note about tag attributes limitation in xml-utils.ts
- Remove redundant disabled prop from SpecModeTabs
This commit refines the migration functionality in the SettingsService to focus on migrating only specific application data files from the legacy Electron userData directory. The migration now explicitly handles files such as settings.json, credentials.json, and agent-sessions, while excluding internal caches. Enhanced logging provides clearer insights into the migration process, including skipped items and errors encountered.
Key changes:
- Modified migration logic to target specific application data files and directories.
- Improved logging for migration status and error handling.
- Introduced a new private method, `copyDirectory`, to facilitate directory copying.
This update expands the migration functionality in the SettingsService to include the entire data directory, rather than just specific files. The migration now handles all files and directories, including settings.json, credentials.json, sessions-metadata.json, and conversation histories. Additionally, logging has been improved to reflect the migration of all items and to provide clearer information on the migration process.
Key changes:
- Updated migration logic to recursively copy all contents from the legacy directory.
- Enhanced logging for migration status and errors.
- Added a new private method, `copyDirectoryContents`, to facilitate the recursive copying of files and directories.
This commit introduces a new feature in the SettingsService to migrate user settings from the legacy Electron userData directory to the new shared data directory. The migration process checks for the existence of settings in both locations and handles the transfer of settings.json and credentials.json files if necessary. It also includes logging for successful migrations and any errors encountered during the process, ensuring a smooth transition for users upgrading from previous versions.
Key changes:
- Added `migrateFromLegacyElectronPath` method to handle migration logic.
- Implemented platform-specific paths for legacy settings based on the operating system.
- Enhanced error handling and logging for migration operations.
The /api/fs/image endpoint requires authentication, but when loading images via
CSS background-image or img tags, only query parameters can be used (headers
cannot be set). Web mode passes the session token as a query parameter (?token=...),
but the auth middleware didn't recognize it, causing image requests to fail.
This fix adds support for the 'token' query parameter in the checkAuthentication
function, allowing the auth middleware to validate web mode session tokens when
they're passed as query parameters.
Now image loads work correctly in web mode by:
1. Client passes session token in URL: ?token={sessionToken}
2. Auth middleware recognizes and validates the token query parameter
3. Image endpoint successfully serves the image after authentication
This fixes the issue where kanban board background images were not visible
in web mode.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Adds authentication checks to the /api/fs/image endpoint to validate
session tokens in web mode. This ensures background images and other
image assets load correctly in web mode by validating:
- session token from query parameter (web mode)
- API key from query parameter (Electron mode)
- session cookie (web mode fallback)
- X-API-Key and X-Session-Token headers
This fixes the issue where kanban board background images were not
visible in web mode because the image request lacked proper authentication.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Wrap route.fetch() and response.json() in try/catch blocks to handle
cases where the response is disposed before it can be accessed. Falls
back to route.continue() to let the original request proceed normally.
This fixes the intermittent "Response has been disposed" error in
open-existing-project.spec.ts that occurs due to timing issues in CI.
When creating new projects, the theme was always explicitly set even when
matching the global theme. This caused "Use Global Theme" to be unchecked,
preventing global theme changes from affecting the project.
Now theme is only set on new projects when explicitly provided or when
recovering a trashed project's theme preference.
XtermLogViewer was passing DEFAULT_TERMINAL_FONT directly to xterm.js,
but this value is 'default' - a sentinel string for the dropdown selector,
not a valid CSS font family. Also the font size was hardcoded to 13px.
Now reads the user's font preference from terminalState:
- fontFamily: Uses getTerminalFontFamily() to convert to CSS font stack
- defaultFontSize: Uses store value when fontSize prop not provided
Also adds useEffects to update font settings dynamically when they change.
This ensures dev server logs respect Settings > Terminal settings.
Address PR review comments by:
- Creating shared sanitizeForTestId utility in apps/ui/src/lib/utils.ts
- Updating ProjectSwitcherItem to use the shared utility
- Adding matching helper to test utils for E2E tests
- Updating all E2E tests to use the sanitization helper
This ensures the component and tests use identical sanitization logic,
making tests robust against project names with special characters.
- Replace direct localStorage.setItem() with setItem helper in use-settings-migration.ts (line 472) for consistent storage-availability checks and error handling
- Replace brittle attribute selector with Playwright's getByRole in open-existing-project.spec.ts (line 162) to handle names containing special characters
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The data-testid generation was using only the sanitized project name which
could produce collisions and didn't handle special characters properly.
Changes:
- Combine stable project.id with sanitized name: project-switcher-{id}-{name}
- Expand sanitization to remove non-alphanumeric chars (except hyphens)
- Collapse multiple hyphens and trim leading/trailing hyphens
- Update E2E tests to use ends-with selector for matching
This ensures test IDs are deterministic, unique, and safe for CSS selectors.
- Expanded docstrings in use-settings-migration.ts for parseLocalStorageSettings, localStorageHasMoreData, mergeSettings, and performSettingsMigration
- Expanded docstrings in use-settings-sync.ts for getSettingsFieldValue and hasSettingsFieldChanged helper functions
- Added detailed parameter and return value documentation
- Improved clarity on migration flow and settings merging logic
This brings docstring coverage from 77.78% to 80%+ to satisfy CodeRabbit checks.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit fixes bidirectional data synchronization between Electron and Web
modes by addressing multiple interconnected issues:
**Core Fixes:**
1. **Electron userData Path (main.ts)**
- Explicitly set userData path in development using app.setPath()
- Navigate from __dirname to project root instead of relying on process.cwd()
- Ensures Electron reads from /data instead of ~/.config/Automaker
2. **Server DataDir Path (main.ts, start-automaker.sh)**
- Fixed startServer() to use __dirname for reliable path calculation
- Export DATA_DIR environment variable in start-automaker.sh
- Server now consistently uses shared /data directory
3. **Settings Sync Protection (settings-service.ts)**
- Modified wipe protection to distinguish legitimate removals from accidents
- Allow empty projects array if trashedProjects has items
- Prevent false-positive wipe detection when removing projects
4. **Diagnostics & Logging**
- Enhanced cache loading logging in use-settings-migration.ts
- Detailed migration decision logs for troubleshooting
- Track project counts from both cache and server
**Impact:**
- Projects created in Electron now appear in Web mode after restart
- Projects removed in Web mode stay removed in Electron after restart
- Settings changes sync bidirectionally across mode switches
- No more data loss or project duplication issues
**Testing:**
- Verified Electron uses /home/dhanush/Projects/automaker/data
- Confirmed server startup logs show correct DATA_DIR
- Tested project persistence across mode restarts
- Validated no writes to ~/.config/Automaker in dev mode
Fixes: Data persistence between Electron and Web modes
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
CRITICAL: Electron was using ~/.config/@automaker/app/data/ while web mode
used ./data/, causing projects to never sync between modes.
In development mode, both now use the shared project root ./data directory.
In production, Electron uses its isolated userData directory for app portability.
This ensures:
- Electron projects sync to the same server data directory as web mode
- Projects opened in Electron immediately appear in web mode
- Server restart doesn't lose projects from either mode
The issue was on line 487 where DATA_DIR was set to app.getPath('userData')
instead of the shared project ./data directory.
Fixes the fundamental problem where projects never appeared in web mode
even though they were in the server's settings file.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Updated the PR state handling to use a consistent uppercase format ('OPEN', 'MERGED', 'CLOSED') throughout the codebase. This includes changes to the worktree metadata interface, PR creation logic, and related tests to ensure uniformity and prevent potential mismatches in state representation.
Additionally, modified the GitHub PR fetching logic to retrieve all PR states, allowing for better detection of state changes.
This refactor enhances clarity and consistency in how PR states are managed and displayed.
This update standardizes the loading indicators by replacing all instances of Loader2 with the new Spinner component. The Spinner component provides a consistent look and feel for loading states throughout the UI, enhancing the user experience.
Changes include:
- Updated loading indicators in various components such as popovers, modals, and views.
- Ensured that the Spinner component is used with appropriate sizes for different contexts.
No functional changes were made; this is purely a visual and structural improvement.
When switching between Electron and web modes or when the server temporarily
stops, web mode was falling back to stale localStorage data instead of fresh
server data.
This fix:
1. Updates localStorage cache whenever fresh server settings are fetched
2. Updates localStorage cache whenever settings are synced to server
3. Prioritizes fresh settings cache over old Zustand persisted storage
This ensures that:
- Web mode always sees the latest projects even after mode switches
- Switching from Electron to web mode immediately shows new projects
- Server restarts don't cause web mode to use stale cached data
Fixes issue where projects opened in Electron didn't appear in web mode
after stopping and restarting the server.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Projects are critical data that must persist across mode switches (Electron/web).
Previously, project changes were debounced by 1 second, which could cause data
loss if:
1. User switched from Electron to web mode quickly
2. App closed before debounce timer fired
3. Network temporarily unavailable during debounce window
This change makes project array changes sync immediately (syncNow) instead of
using the 1-second debounce, ensuring projects are always persisted to the
server right away and visible in both Electron and web modes.
Fixes issue where projects opened in Electron didn't appear in web mode.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
In web mode, image loads may not send session cookies due to proxy/CORS
restrictions. This adds the session token as a query parameter to ensure
images load correctly with proper authentication in web mode.
Fixes custom project icons and images not loading in web mode.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
When a project fails to initialize because the directory no longer exists
(e.g., test artifacts, deleted folders), automatically remove it from the
project list instead of showing the error repeatedly on every reload.
This prevents users from being stuck with broken project references in their
settings after testing or when project directories are moved/deleted.
The user is notified with a toast message explaining the removal.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Web mode sessions were being lost on page reload because the session token was
stored only in memory (cachedSessionToken). When the page reloaded, the token
was cleared and verifySession() would fail, redirecting users to login.
This commit adds localStorage persistence for the session token, ensuring:
1. Token survives page reloads in web mode
2. verifySession() can use the persisted token from localStorage
3. Token is cleared properly on logout
4. Graceful fallback if localStorage is unavailable (SSR, disabled storage)
The HTTP-only cookie alone isn't sufficient for web mode due to SameSite cookie
restrictions and potential proxy issues with credentials forwarding.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Enables ws: true for /api proxy to properly forward WebSocket connections through the development server in web mode. This ensures real-time features work correctly when developing in browser mode.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The web mode launcher was setting CORS_ORIGIN to only include the system
hostname and 127.0.0.1, but users access via http://localhost:3007 which
wasn't in the allowed list.
Now includes:
- http://localhost:3007 (primary dev URL)
- http://$HOSTNAME:3007 (system hostname if needed)
- http://127.0.0.1:3007 (loopback IP)
Also cleaned up debug logging from CORS check since root cause is now clear.
Fixes: Persistent "Not allowed by CORS" errors in web mode
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Added detailed logging to see:
- What origin is being sent
- How the hostname is parsed
- Why origins are being accepted/rejected
This will help us understand why CORS is still failing in web mode.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
The CORS check was too strict for local development. Changed to:
- Parse origin URL properly to extract hostname
- Allow all localhost origins (any port)
- Allow all 127.0.0.1 origins (loopback IP)
- Allow all private network IPs (192.168.x.x, 10.x.x.x, 172.x.x.x)
- Keep security by rejecting unknown origins
This fixes CORS errors when accessing from http://localhost:3007
or other local addresses during web mode development.
Fixes: "Not allowed by CORS" errors in web mode
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
In web mode, the API client was hardcoding localhost:3008, which bypassed
the Vite proxy and caused CORS errors. Now it uses relative URLs (just /api)
in web mode, allowing the proxy to handle routing and making requests appear
same-origin.
- Web mode: Use relative URLs for proxy routing (no CORS issues)
- Electron mode: Continue using hardcoded localhost:3008
This allows the Vite proxy configuration to actually work in web mode.
Fixes: Persistent CORS errors in web mode development
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
When running in web mode (npm run dev:web), the frontend on localhost:3007
was making cross-origin requests to the backend on localhost:3008, causing
CORS errors.
Added Vite proxy configuration to forward /api requests from the dev server
to the backend. This makes all API calls appear same-origin to the browser,
eliminating CORS blocks during development.
Now web mode users can access http://localhost:3007 without CORS errors.
Fixes: CORS "Not allowed by CORS" errors in web mode
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>