Skip to content

Conversation

@EricBlanquer
Copy link
Contributor

@EricBlanquer EricBlanquer commented Jan 20, 2026

Summary

Bug Fixes

  • Fixed parent directory navigation on Windows (always went to C:)
  • Fixed back button not showing when folder is empty
  • Fixed path suggestions showing exact match in dropdown
  • Fixed misleading UI messages about workspace creation

New Features

  • Create folder button: Add folders directly from the folder browser (+ button)
image
  • Git clone with progress: Real-time progress display during repository cloning (SSE streaming)
image image
  • SSH key detection: Shows "SSH Key" for git@ URLs, hides token section (tokens only work with HTTPS)
image image
  • Smart auto-advance: Only auto-advances to confirm step for "Existing Workspace", stays on configure for "New Workspace" to allow entering git URL

Technical Changes

  • New SSE endpoint /api/projects/clone-progress for streaming clone progress
  • New endpoint /api/create-folder for folder creation
  • Auth middleware supports token via query param (required for EventSource/SSE)

Summary by CodeRabbit

  • New Features

    • Create new folders directly from the folder browser modal (toggle, input, keyboard shortcuts, focus management).
    • Real-time Git clone progress streamed and displayed during workspace creation.
  • Bug Fixes

    • Improved Windows and Unix path handling; parent-path calculation and empty-folder messaging fixed.
    • Folder list refreshes immediately after creation; create/cancel actions reset state correctly.
  • Chores

    • Backend endpoints added to support folder creation and clone-progress streaming.
  • Localization

    • Updated UI text for cloning states, SSH/HTTPS hints, token fields, and SSH key labels.

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

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Warning

Rate limit exceeded

@EricBlanquer has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 10 minutes and 29 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

Walkthrough

Adds frontend folder-creation UI/state and SSE-driven Git clone progress; new POST /api/create-folder endpoint; SSE GET /clone-progress with token-in-query fallback for authentication; server-side cloning into repo-named subfolders with improved validation, error mapping, and cleanup.

Changes

Cohort / File(s) Summary
Frontend: Project creation UI
src/components/ProjectCreationWizard.jsx
Added new-folder UI and state (showNewFolderInput, newFolderName, creatingFolder, cloneProgress), in-modal create-folder controls & keyboard handling, path suggestion filtering, parent-path handling for Windows/Unix roots, and SSE-driven clone-progress display.
Frontend: API helper
src/utils/api.js
Added api.createFolder(folderPath) → POST /api/create-folder.
Server: folder creation endpoint
server/index.js
Added POST /api/create-folder with ~ expansion, path normalization, FORBIDDEN_PATHS checks, parent-exists validation, conflict handling, and mkdir creation; returns structured errors on failure.
Server: auth middleware (SSE support)
server/middleware/auth.js
Authentication now falls back to req.query.token when Authorization header is missing (supports EventSource/SSE).
Server: project creation & clone progress SSE
server/routes/projects.js, server/projects.js
create-workspace now supports cloning into a repo-named subdirectory, pre-checks/409 for existing destination, cleans up partial clones on failure; added GET /clone-progress SSE route streaming git clone progress with token-embedded URLs and improved git error-to-message mapping; broadened name-encoding in addProjectManually.
i18n: localization updates
src/i18n/locales/en/common.json, src/i18n/locales/zh-CN/common.json
Added SSH key label, cloning-related messages/labels, token-related UI strings, and new folder-creation error text; adjusted step messages for clone/new workspace wording.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Server
  participant Git as "git clone (proc)"

  Client->>Server: POST /create-workspace (start clone) or GET /clone-progress?repo=...&path=...&token=... (EventSource)
  Server->>Server: validate token (Authorization header or req.query.token)
  Server->>Git: spawn `git clone` to destination subdir (token-embedded URL if provided)
  Git-->>Server: stdout/stderr (progress lines)
  Server-->>Client: SSE event: progress (data)
  alt clone succeeds
    Git-->>Server: exit 0
    Server->>Server: add cloned subpath as project
    Server-->>Client: SSE event: complete (project info)
  else clone fails
    Git-->>Server: exit != 0
    Server->>Server: cleanup partial clone
    Server-->>Client: SSE event: error (message)
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • blackmammoth
  • viper151

Poem

🐰 I dug a fresh new folder with a click,
Streams of git hummed progress, line by line, quick,
I hopped through roots of C:\ and / with glee,
Tokens tucked in my burrow for secure cloning,
Now projects bloom — a carrot-shaped pick! 🥕

🚥 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 pull request title accurately summarizes the main changes: folder browser fixes and git clone improvements.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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


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.

@blackmammoth blackmammoth self-assigned this Jan 21, 2026
Copy link
Collaborator

@blackmammoth blackmammoth left a comment

Choose a reason for hiding this comment

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

Here are some issues @EricBlanquer:

  1. If there are no subfolders, there is not a way to navigate back
image
  1. Clicking the ".." icon should bring us to the parent directory. However, it always brings us to "C:" on Windows
image image

@EricBlanquer
Copy link
Contributor Author

EricBlanquer commented Jan 21, 2026

Hi @blackmammoth

Fixed in c1586e3:

  1. Empty folder navigation: The ".." button now displays even when a folder has no subfolders, allowing users to
    navigate back to the parent directory.
  2. Windows parent directory: Fixed the parent path calculation to handle both forward slashes (/) and backslashes
    (\). Also added detection for Windows drive roots (e.g., C:\) to prevent broken navigation.

@blackmammoth
Copy link
Collaborator

@EricBlanquer Awesome! This fixes the issues. However, if the user clicked a "New Workspace", then they should have an option to create a path by entering their desired folder name. Right now, it always shows the following message:

image

@EricBlanquer EricBlanquer changed the title fix: use resolved path from API in folder browser feat: enhance project creation wizard - folder browser fixes and git clone improvements Jan 21, 2026
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: 4

🤖 Fix all issues with AI agents
In `@server/index.js`:
- Around line 530-556: The create-folder POST handler (route
'/api/create-folder') lacks workspace/path validation; update it to reuse or
import an exported validateWorkspacePath (from server/routes/projects.js) and
run the provided folderPath through that validator before accessing or creating
directories, returning a 400/403 when validation fails; additionally ensure
forbidden system roots (e.g., /etc, /usr) are checked via the same validator or
a small allowlist check and only allow creation when validateWorkspacePath
approves to prevent creating folders outside the allowed workspace root.

In `@server/routes/projects.js`:
- Around line 236-238: The repo name extraction can return an empty string when
githubUrl ends with a slash; update the logic around githubUrl -> repoName (used
when creating clonePath) to trim trailing slashes first and then strip a
trailing ".git" (or alternatively split on '/' and pick the last non-empty
segment) so repoName is never empty; adjust the code that computes repoName and
clonePath (referencing variables githubUrl, repoName, clonePath in
server/routes/projects.js) to use the trimmed/validated segment and fall back to
a clear error or default name if no segment is found.
- Around line 352-353: The repo name extraction using githubUrl, repoName, and
clonePath can fail when githubUrl ends with a trailing slash; normalize the URL
first by trimming any trailing slashes (e.g., remove trailing '/' characters)
before doing .replace(/\.git$/, '') and .split('/').pop() so repoName is correct
for inputs like "https://.../repo/" and "https://.../repo.git/"; update the
expression that computes repoName to operate on the trimmed URL and leave
clonePath logic using repoName unchanged.

In `@src/components/ProjectCreationWizard.jsx`:
- Around line 236-255: The createNewFolder function builds paths by
concatenating browserCurrentPath and newFolderName with a forward slash
(producing invalid Windows paths) and uses alert() for errors; change the API
contract and UI handling: have createNewFolder call api.createFolder({ parent:
browserCurrentPath, name: newFolderName.trim() }) (update api.createFolder
implementation/server endpoint accordingly) instead of string-joining paths,
call loadBrowserFolders(browserCurrentPath) to refresh the current folder, and
replace alert(...) with the component's error state updater (use
setError(error.message || 'Failed to create folder')) so errors render
consistently via the existing error UI.
🧹 Nitpick comments (3)
server/routes/projects.js (2)

394-415: Directory cleanup missing on clone failure.

When the clone fails, the created directories (absolutePath and potentially partial clonePath) are not cleaned up, unlike the create-workspace endpoint which removes the directory on failure. This could leave orphaned directories.

♻️ Suggested cleanup on failure
       } else {
         let errorMessage = 'Git clone failed';
         if (lastError.includes('Authentication failed') || lastError.includes('could not read Username')) {
           errorMessage = 'Authentication failed. Please check your credentials.';
         } else if (lastError.includes('Repository not found')) {
           errorMessage = 'Repository not found. Please check the URL and ensure you have access.';
         } else if (lastError.includes('already exists')) {
           errorMessage = 'Directory already exists';
         } else if (lastError) {
           errorMessage = lastError;
         }
+        // Cleanup partial clone directory on failure
+        try {
+          await fs.rm(clonePath, { recursive: true, force: true });
+        } catch (cleanupError) {
+          console.error('Failed to clean up after clone failure:', cleanupError);
+        }
         sendEvent('error', { message: errorMessage });
       }

267-273: Dead code: unreachable message branch.

The ternary at line 270-272 checks githubUrl, but this code path is only reached when githubUrl is falsy (line 262 returns early when cloning). The "cloned successfully" message branch can never execute.

♻️ Simplify to remove dead branch
       return res.json({
         success: true,
         project,
-        message: githubUrl
-          ? 'New workspace created and repository cloned successfully'
-          : 'New workspace created successfully'
+        message: 'New workspace created successfully'
       });
src/components/ProjectCreationWizard.jsx (1)

450-451: Good SSH URL detection, could be extended.

The check for git@ prefix correctly identifies SSH URLs. Note that SSH URLs can also be in the format ssh://git@github.com/..., which wouldn't be caught by startsWith('git@').

-                  {githubUrl && !githubUrl.startsWith('git@') && (
+                  {githubUrl && !githubUrl.startsWith('git@') && !githubUrl.startsWith('ssh://') && (

@EricBlanquer EricBlanquer force-pushed the fix/new-project-folder-selection branch from ff94c3c to 6dd270a Compare January 21, 2026 20:51
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: 2

🤖 Fix all issues with AI agents
In `@server/index.js`:
- Around line 530-570: The TOCTOU between fs.promises.access and
fs.promises.mkdir in the Express handler for app.post('/api/create-folder') can
cause mkdir to throw EEXIST and currently returns 500; modify the code around
the mkdir call (referencing targetPath and the mkdir invocation) to catch errors
from fs.promises.mkdir, inspect err.code === 'EEXIST' and return
res.status(409).json({ error: 'Folder already exists' }) for that case, and only
treat other errors as 500.

In `@server/routes/projects.js`:
- Around line 236-262: The clone flow can delete an existing directory if git
fails; before calling cloneGitHubRepository(check normalizedUrl, repoName,
clonePath), check whether clonePath already exists (fs.stat/fs.existsSync) and
if it does, bail out with a clear error (or pick a unique temp subfolder)
instead of attempting to overwrite it; when you proceed to create/clone into a
path, set a local flag (e.g., createdByThisOperation = true) or create a
uniquely named temp folder and only perform fs.rm(cleanup) in the catch block if
that flag is true (i.e., the directory was created by this operation), leaving
pre-existing user directories untouched; apply the same guard to the other clone
usage referenced and ensure addProjectManually is only called after a successful
clone.

@EricBlanquer
Copy link
Contributor Author

@EricBlanquer Awesome! This fixes the issues. However, if the user clicked a "New Workspace", then they should have an option to create a path by entering their desired folder name. Right now, it always shows the following message:

image

I've tested the "New Workspace" option and add new feature for it

@blackmammoth
Copy link
Collaborator

blackmammoth commented Jan 23, 2026

@EricBlanquer Awesome! This fixes the issues. However, if the user clicked a "New Workspace", then they should have an option to create a path by entering their desired folder name. Right now, it always shows the following message:
image

I've tested the "New Workspace" option and add new feature for it

@EricBlanquer Clicking "Create" gives an error.
image

The response from the API is:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /api/create-folder</pre>
</body>
</html>

Note: I'm using Windows

@blackmammoth
Copy link
Collaborator

@EricBlanquer Awesome! This fixes the issues. However, if the user clicked a "New Workspace", then they should have an option to create a path by entering their desired folder name. Right now, it always shows the following message:
image

I've tested the "New Workspace" option and add new feature for it

In addition, if you are in "New Workspace", you shouldn't see "Select" and "Use this folder". The user should only navigate to their desire directory and then they should be asked for a folder name they want to create.

@EricBlanquer
Copy link
Contributor Author

@EricBlanquer Awesome! This fixes the issues. However, if the user clicked a "New Workspace", then they should have an option to create a path by entering their desired folder name. Right now, it always shows the following message:
image

I've tested the "New Workspace" option and add new feature for it

@EricBlanquer Clicking "Create" gives an error. image

The response from the API is:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Error</title>
</head>
<body>
<pre>Cannot POST /api/create-folder</pre>
</body>
</html>

Note: I'm using Windows

fixed for Windows path

When selecting home folder in New Project wizard, ~ was being used
instead of /home/<user>, causing "Workspace path does not exist" error.
Now uses the resolved absolute path returned by the browse-filesystem API.
- Show parent directory (..) button even when folder has no subfolders
- Handle Windows backslash paths when calculating parent directory
- Prevent navigation to Windows drive root (C:\) from breaking
…one progress

- Add "+" button to create new folders directly from folder browser
- Add SSE endpoint for git clone with real-time progress display
- Show clone progress (receiving objects, resolving deltas) in UI
- Detect SSH URLs and display "SSH Key" instead of "No authentication"
- Hide token section for SSH URLs (tokens only work with HTTPS)
- Fix auto-advance behavior: only auto-advance for "Existing Workspace"
- Fix various misleading UI messages
- Support auth token via query param for SSE endpoints
- Add path validation to /api/create-folder endpoint (forbidden system dirs)
- Fix repo name extraction to handle trailing slashes in URLs
- Add cleanup of partial clone directory on SSE clone failure
- Remove dead code branch (unreachable message)
- Fix Windows path separator detection in createNewFolder
- Replace alert() with setError() for consistent error handling
- Detect ssh:// URLs in addition to git@ for SSH key display
- Show create folder button for both workspace types
@EricBlanquer EricBlanquer force-pushed the fix/new-project-folder-selection branch from 8853623 to 5cfb01b Compare January 23, 2026 19:41
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: 2

🤖 Fix all issues with AI agents
In `@server/routes/projects.js`:
- Around line 354-362: Optional chaining on req.user is unnecessary because
authenticateToken middleware guarantees req.user; update the call to
getGithubTokenById to use req.user.id instead of req.user?.id. Locate the block
handling githubToken (variables githubTokenId, newGithubToken and the call to
getGithubTokenById) and replace the optional chain with a direct property access
(req.user.id); ensure any related logic remains unchanged and that
authenticateToken and projectsRoutes references are left intact.

In `@src/components/ProjectCreationWizard.jsx`:
- Around line 818-833: The "Select"/"Use this folder" action should be hidden in
New Workspace mode; update the JSX rendering in ProjectCreationWizard so the
Button that calls selectFolder(...) is only rendered when workspaceType ===
'existing' (or inversely, not rendered when workspaceType === 'new'); locate the
folder list block that uses navigateToFolder(folder.path) and conditionally
render the Button (and the similar button instance later in the file) so
selection is only available for existing workspaces.
🧹 Nitpick comments (2)
server/index.js (1)

553-553: Consider extracting FORBIDDEN_PATHS to a shared module.

This constant is duplicated from server/routes/projects.js (lines 14-31). To maintain consistency and reduce duplication, consider extracting it to a shared utilities module.

♻️ Suggested refactor

Create a shared module (e.g., server/utils/paths.js):

// server/utils/paths.js
export const FORBIDDEN_PATHS = [
  '/', '/etc', '/bin', '/sbin', '/usr', '/dev', '/proc', 
  '/sys', '/var', '/boot', '/root', '/lib', '/lib64', 
  '/opt', '/tmp', '/run'
];

Then import in both files:

-const FORBIDDEN_PATHS = ['/', '/etc', '/bin', ...];
+import { FORBIDDEN_PATHS } from './utils/paths.js';
server/routes/projects.js (1)

409-415: Minor: Git stderr may expose credential hints on auth failure.

Git's stderr output is forwarded directly to the client. While git typically doesn't echo embedded credentials, error messages on authentication failure might reveal partial URL information. Consider sanitizing stderr before sending to the client, or at minimum, avoid forwarding raw error output when authentication fails.

♻️ Optional sanitization
 gitProcess.stderr.on('data', (data) => {
   const message = data.toString().trim();
   lastError = message;
   if (message) {
+    // Sanitize potential credential leaks from URLs
+    const sanitized = message.replace(/https?:\/\/[^@]+@/g, 'https://***@');
     sendEvent('progress', { message: sanitized });
   }
 });

@EricBlanquer
Copy link
Contributor Author

EricBlanquer commented Jan 23, 2026

@EricBlanquer Awesome! This fixes the issues. However, if the user clicked a "New Workspace", then they should have an option to create a path by entering their desired folder name. Right now, it always shows the following message:
image

I've tested the "New Workspace" option and add new feature for it

In addition, if you are in "New Workspace", you shouldn't see "Select" and "Use this folder". The user should only navigate to their desire directory and then they should be asked for a folder name they want to create.

oh, labels have been changed... before they were:
image

now they are:
image

they were better before, why a new step as we can now create folders from the select?
image

The regex only replaced forward slashes, causing Windows paths like
C:\Users\Eric\my_project to remain unchanged instead of being encoded
to C--Users-Eric-my-project. This caused API routes to fail.
@EricBlanquer EricBlanquer force-pushed the fix/new-project-folder-selection branch from 5cfb01b to 5fa8bed Compare January 23, 2026 20:08
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: 2

🤖 Fix all issues with AI agents
In `@server/routes/projects.js`:
- Around line 354-362: When githubTokenId is provided the code calls
getGithubTokenById but silently proceeds if it returns null, which will cause
auth failures; update the handler that uses githubTokenId to check the result of
getGithubTokenById (the token variable) and if it's null return a 404 response
(e.g., res.status(404).json({ error: "GitHub token not found" })) instead of
falling through with githubToken = null; ensure you still allow the
newGithubToken branch to work and reference the githubTokenId,
getGithubTokenById, githubToken, and newGithubToken variables to locate the fix.
- Around line 378-388: The code embeds githubToken into cloneUrl (cloneUrl,
githubUrl, githubToken) which can leak the token if that URL is later included
in lastError or server logs; add a redaction step (e.g., a helper like
redactTokenFromUrl or sanitizeUrl) that replaces the token/password in any URL
string with a placeholder before assigning to lastError or passing to
SSE/logging, and call this sanitizer wherever lastError is set or the error is
logged (references: lastError, the SSE send path, and any process/server logging
calls) so no embedded token is ever emitted.
🧹 Nitpick comments (3)
server/routes/projects.js (3)

215-216: Empty workspace directory left behind on clone failure.

When a GitHub URL is provided and clone fails, only clonePath is cleaned up (lines 256-264), but the parent absolutePath directory created here remains. This could leave empty workspace directories.

Consider cleaning up absolutePath if it was newly created and remains empty after clone failure, or defer directory creation until after clone validation succeeds.


324-325: Security consideration: GitHub token in query parameters.

The newGithubToken in query params may be logged by reverse proxies, load balancers, or server access logs. While necessary for EventSource (which doesn't support custom headers), consider:

  1. Ensuring server access logs redact query parameters containing tokens
  2. Using short-lived tokens when possible
  3. Preferring githubTokenId (stored token reference) over newGithubToken (actual token value)

455-457: Client disconnect may leave partial clone data.

When the client disconnects, gitProcess.kill() is called, but the process may have already created partial data. The close event handler (line 417) should fire with a non-zero exit code and trigger cleanup, but this depends on the kill signal being processed correctly.

Consider ensuring cleanup runs even on SIGTERM:

🔧 Suggested enhancement
     req.on('close', () => {
-      gitProcess.kill();
+      if (!gitProcess.killed) {
+        gitProcess.kill('SIGTERM');
+      }
     });

The current implementation should work in most cases since the close event will still fire after kill().

@EricBlanquer EricBlanquer force-pushed the fix/new-project-folder-selection branch 3 times, most recently from c77b3c2 to 140f6ad Compare January 23, 2026 20:26
@EricBlanquer EricBlanquer force-pushed the fix/new-project-folder-selection branch from 140f6ad to 00e5aee Compare January 23, 2026 20:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants