Add in-app folder picker for web and mobile clients#492
Merged
BunsDev merged 4 commits intoOpenKnots:mainfrom Apr 25, 2026
Merged
Add in-app folder picker for web and mobile clients#492BunsDev merged 4 commits intoOpenKnots:mainfrom
BunsDev merged 4 commits intoOpenKnots:mainfrom
Conversation
When the native folder picker is unavailable — typically on a headless remote host running the okcode server, where osascript / zenity / kdialog return null — the web client currently has no way to select a project directory short of typing an absolute path by hand. Add a WS method, projects.browseDirectory, that walks any directory the server process can stat and returns its immediate children. The Sidebar "pick folder" flow falls back to a new in-app dialog that consumes this method when running in a non-Electron client and the native picker returns null. Security posture documented on the handler: the method is gated by the same auth token as every other WS route, but within that gate it does no path allowlisting — holders of a valid token can enumerate the full filesystem of the service user, which is the point of a filesystem picker.
|
@jbrahy is attempting to deploy a commit to the 0xBuns Team on Vercel. A member of the Team first needs to authorize it. |
The previous listing split entries into directories-first / files-second with no sort affordance, which was awkward at a glance and gave the user no way to change order. - Single flat list sorted case-insensitively by filename using locale rules (sensitivity: "base"), so "Endgame-..." and "endgame-..." collate adjacently. - Column header "Name" with an A→Z / Z→A arrow icon; clicking toggles sort direction. Default is ascending. - Files keep their muted, non-interactive styling and now render with a file icon rather than empty spacer so the visual hierarchy is clear when directories and files are intermixed in the same sorted list.
…orts - Replace the fixed 320px list height with max-h:320px + min-h:80px so small directories no longer show a huge empty panel below the last entry, while long listings still scroll. - Bump the column header to text-xs with foreground/70 so it is actually legible instead of sinking into the container background at 10px. - Add min-w-0 to the path input so a long /deep/nested/path no longer forces the flex row to overflow the dialog panel on narrow viewports. - Switch the loading spinner centering from h-full (which collapsed to zero now that the parent is no longer fixed-height) to its own min-h:80px so the spinner has room to breathe.
Previous revision nested DialogPanel inside DialogPopup with a manual width override (w-[min(560px,95vw)]), which was wider than DialogPopup's max-w-lg container and caused the path input, list rows, and footer buttons to spill past the card's right edge. Rewrite to follow the convention used by CloneRepositoryDialog / WorktreeCleanupDialog: - DialogPopup (max-w-xl) is the outer card; DialogHeader, DialogPanel, and DialogFooter are its direct children. - Drop the manual width on DialogPanel; let DialogPopup's max-w-xl and the panel's own padding (px-6 pb-6) drive layout. - Replace the raw overflow-auto list with ScrollArea (max-h-[280px]). - Replace Loader2Icon with Spinner from ./ui/spinner. - Switch nav buttons to size="icon-sm" for consistency with the system. - Switch Cancel/Use-this-folder to size="sm" so they match other footer buttons. - text-red-500 → text-destructive for the error state. - Group the sort header and "Some entries skipped" hint in a single toolbar row above the list instead of a separate paragraph below.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
projects.browseDirectory, that lists immediate children of any directory the server process can stat. Scoped to the authenticated WS transport.ServerFolderPickerDialog— an in-app folder picker that consumes the new method over WebSocket, used as a fallback from the Sidebar "pick folder" flow whenever the native OS picker is unavailable (i.e. when the server is running headless — osascript / zenity / kdialog return null).partialflag, directory-kind symlinks, filesystem-rootparentPathomission, and the default-to-home behavior.Security posture (documented on the handler)
The new endpoint is gated by the same auth token as every other WS method. Within that gate, it performs no path allowlisting — any caller holding a valid token can enumerate the full filesystem of the user the server process runs as. That is intentional for a filesystem picker, but operators sharing the auth token widely should treat filesystem enumeration as within scope of that token. See the docstring on
browseFileSystemDirectoryfor details.Test plan
bun run fmt:checkbun run lintbun run typecheckcd apps/server && bun run test -- fileSystemBrowser(9/9 passing)$HOME; navigate up/down via dirent click and the../entry; confirm project is added at chosen path🤖 Generated with Claude Code