feat: add open command for opening directories as projects#70
feat: add open command for opening directories as projects#70paschdan wants to merge 11 commits intogrinev:mainfrom
Conversation
|
@paschdan thanks for the PR! Only today I had time to look at it carefully and think about the feature as a whole. In general, I see the value of At the same time, in the current form I am a bit uncomfortable with this feature from a security point of view. Right now it allows browsing almost any local directory and selecting it as a project. That means the bot can be used not only for known project folders, but also for system folders or other sensitive locations on the machine. Even if the bot is limited to one Telegram user, this still feels too broad by default. I think this feature could work much better if we limit it to a configurable allowlist of roots. My suggestion:
For me this would be a much safer balance:
Below are also some technical remarks from the review:
Overall, I think the implementation work is solid, and I especially like the extraction of |
@grinev |
@paschdan ok, you can skip this part |
Extract the project-switching state logic (clear session, reset pinned message, refresh keyboard) from projects.ts into a shared utility so it can be reused by the upcoming /open command without duplication.
Add file-tree.ts with pure utilities for browsing the local filesystem: directory scanning with pagination, hidden-dir filtering, tilde-based display paths, entry labels, and tree headers with i18n-aware counts.
Add a new /open bot command that lets users browse the local filesystem via inline keyboard navigation and select a directory as a project. Includes callback-data path encoding to stay within Telegram's 64-byte limit, pagination, and i18n strings for all 6 supported locales.
Stale or crafted callback data could produce out-of-bounds page indicators like (4/2). Clamp the page to the valid range and return the normalized page in the scan result so all callers use the safe value.
Move the session directory cache write to after getProjectByWorktree and switchToProject complete successfully, so a failed switch does not leave a stale entry in the cached project list.
…ndows Reuse the existing worktreeKey() helper so getProjectByWorktree compares paths case-insensitively on Windows, matching the behavior already used in getProjects() for merging API and cached projects.
…wlist Add OPEN_BROWSER_ROOTS env var (comma-separated absolute paths) to limit which directories the /open command can browse. Defaults to the user's home directory when not set. - New browser-roots.ts utility: root parsing, path normalization, isWithinAllowedRoot guard with case-insensitive matching on Windows - Guard all navigation, pagination, and selection callbacks against paths outside allowed roots - Show root-selection keyboard when multiple roots are configured - Suppress the Up button when at an allowed root boundary - Replace Home button with Back to roots for multi-root setups - i18n strings for root selection and access-denied in all 6 locales
88ef040 to
b715e96
Compare
|
@grinev Thanks for the thorough review! Here's what I've done to address your feedback: Rebased onto latest the branch now includes all changes through v0.15.0, including #72. The Technical remarks — addressed as individual fix commits:
Main concern — browsing scope: Implemented the allowlist via
|
Expand leading ~ or ~/ to the user's home directory when parsing OPEN_BROWSER_ROOTS, so entries like ~/projects resolve correctly. Updated .env.example to show tilde-based examples.
|
@paschdan thanks for your work! I will look and give feedback today/tomorrow |
|
@paschdan pls add command description to readme |
|
I tested the updated branch, and right now opening a project via The problem is in the selection flow order:
Because of that, selecting a new directory fails if this path is not already known by OpenCode or present in the session-directory cache. So the previous change fixed the stale-cache issue, but it also broke the main happy-path for Example from logs: This means /open currently cannot actually open a new directory as a project in many normal cases. |
Description of changes
/opencommand: Adds a directory browser via Telegram inline keyboard, allowing users to navigate the local filesystem and select a folder as a project — without needing to know the exact path upfront.switchToProjectextraction: Refactors the project-switching state logic (clear session, reset pinned message, refresh keyboard) out ofprojects.tsinto a sharedsrc/bot/utils/switch-project.tsutility, eliminating duplication between/projectsand/open.file-treeutility: Addssrc/bot/utils/file-tree.tswith pure functions for directory scanning, pagination (8 entries/page), hidden-directory filtering, tilde-based display paths, and i18n-aware subfolder counts.callback_datalimit by transparently switching to compact indexed references (#0,#1, …) for long absolute paths.Closes issue (optional)
How it was tested
tests/bot/commands/open.test.ts— command, callback routing, busy guard, error paths, path encoding round-trips, stale index invalidationtests/bot/utils/switch-project.test.ts— all state-clearing branches, keyboard rebuild, pinned message failure resiliencetests/bot/utils/file-tree.test.ts— real temp-directory integration tests for scanning, pagination, hidden-dir filtering, error codesnpm run build— cleannpm run lint— cleannpm test— all passChecklist
feat: add /open command for browsing and adding project directoriesmainnpm run lint,npm run build, andnpm test