Skip to content

feat: add PROJECTS_EXCLUDED_PATHS to hide unwanted projects from /projects - #197

Merged
grinev merged 3 commits into
grinev:mainfrom
Johell1NS:feat/projects-excluded-paths
Aug 31, 2026
Merged

grinev merged 3 commits into
grinev:mainfrom
Johell1NS:feat/projects-excluded-paths

Conversation

@Johell1NS

Copy link
Copy Markdown
Contributor

Motivation

The /projects command lists every project OpenCode has ever tracked (the whole worktree of every session). When a user works from many paths — including system or home directories — the list gets polluted with projects they never want to switch to. This makes switching projects via /projects slower and noisy.

Change

Adds an optional PROJECTS_EXCLUDED_PATHS env var (comma-separated absolute paths, same format as OPEN_BROWSER_ROOTS). Any project whose worktree matches one of these paths is filtered out of the /projects list.

PROJECTS_EXCLUDED_PATHS=/home/me/.config/opencode/skills,/home/me/backup

The filter is applied after the existing linked-worktree hiding, keeps the previous behaviour when the var is unset, and is logged for transparency.

Files changed

  • src/config.ts — parse PROJECTS_EXCLUDED_PATHS into config.bot.excludedProjectPaths
  • src/app/services/project-service.ts — filter resolved projects
  • .env.example — document the new variable
  • tests/config.test.ts — cover env parsing (unset, comma-separated, whitespace/empty entries)
  • tests/app/services/project-service.test.ts — cover filtering (unset, single/multiple paths, applied after linked-worktree hiding)

Testing

npm run lint && npm test && npm run build all pass (1224 tests).

@kamysheblid

Copy link
Copy Markdown

In an earlier PR maintainer had the idea of using menus instead which might be better, so there would be an archive button in the menu when you first run /projects that will remove projects from being displayed in the menu until they are opened again using the directory.

The main issue is that you might implement it and maintainer might not accept the PR.

@grinev

grinev commented Aug 29, 2026

Copy link
Copy Markdown
Owner

@Johell1NS thanks for PR

Can you please fix one issue before merging

Major: src/app/services/project-service.ts:71-74 compares excluded paths with raw string equality. This can fail for valid equivalent
paths, such as /home/user/repo vs /home/user/repo/, or C:\Repo vs C:/Repo on Windows. The existing worktreeKey helper already
normalizes these differences, but it is not used here.

Please normalize both configured paths and project worktrees before comparing them, and add tests for trailing separators and Windows
path casing/separators. Otherwise, configured projects may remain visible in /projects.

…ling separators and Windows paths

Normalize both configured PROJECTS_EXCLUDED_PATHS and project worktrees
using the existing worktreeKey helper (handles trailing slashes,
Windows separators and case-insensitivity) before comparing. Add tests
for trailing separators and Windows casing/separators as requested in
review.
@Johell1NS

Copy link
Copy Markdown
Contributor Author

Hi @grinev, thanks for the review!

Fixed the Major issue you flagged in src/app/services/project-service.ts:71-74.

Now both the configured PROJECTS_EXCLUDED_PATHS and the project worktrees are normalized via the existing worktreeKey() helper before comparison. This correctly handles:

  • trailing separators (/home/user/repo vs /home/user/repo/)
  • Windows separators (C:\Repo vs C:/Repo)
  • case-insensitivity on Windows (C:\Repo vs c:\repo)

Used a Set<string> of normalized keys for efficiency and updated the hiddenExcluded logging.

As requested I added dedicated tests in tests/app/services/project-service.test.ts:

  • filtering when excluded path has trailing slash
  • filtering when worktree has trailing slash
  • Windows casing differences
  • Windows mixed separators
  • combined trailing + casing case

Verification locally: npm run lint && npm test && npm run build all passed (1229 tests, +5 new).

Fix published in commit 4d6767c on branch feat/projects-excluded-paths. Let me know if you'd like any further adjustments!

@grinev
grinev merged commit 79c0241 into grinev:main Aug 31, 2026
1 check passed
rubenperezrial added a commit to primigenum/opencode-telegram-bot that referenced this pull request Sep 10, 2026
* feat(i18n): add Korean locale (grinev#211)

Co-authored-by: ashcastle <ashcastle@users.noreply.github.com>

* fix(bot): retry transient Telegram server errors instead of dropping responses (grinev#196)

* fix(telegram): prevent duplicate messages after transient errors

* feat(bot): allow /opencode_stop during an active request

* feat(voice): show recognized text as a quote

* fix(logger): stop console writes after EPIPE to prevent crash loop (grinev#209)

Co-authored-by: Iago Durán Romera <iagorobo24-hub@users.noreply.github.com>

* chore: strict tsconfig (grinev#212)

* feat(telegram): raise stream edit interval on long runs to avoid 429

* chore(release): v0.24.1

* feat(docker): add containerized deployment (grinev#213)

Co-authored-by: Iago Durán Romera <iagorobo24-hub@users.noreply.github.com>

* feat(docker): add Desktop compose and in-container command warnings

* feat(OTB-63): switching to a session adopts the agent, model and variant it last ran with

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* feat(OTB-62): picking a model opens the variant picker when the model offers a choice

* chore: gitignore updated

* feat(bot): accept incoming Telegram rich formatted messages

* feat(bot): accept incoming Telegram rich formatted messages

* feat(status): show bot version in /status

* chore: update e2e screenshots dir

* fix(subagent): stop replaying finished subagent runs in later messages

* feat: add PROJECTS_EXCLUDED_PATHS to hide unwanted projects from /projects (grinev#197)

Co-authored-by: Johell1NS <alessio.perilli@me.com>

* fix(OTB-59): diff file attachments open as readable UTF-8 text (grinev#221)

* chore(release): v0.25.0

* feat(OTB-69): add local json commands support

* feat(settings): add option to delete compact progress on finish (grinev#223)

* fix(queue): support voice and media prompts (grinev#219)

Signed-off-by: Mathias L. Baumann <mathias.baumann@frequenz.com>

* fix(queue): count rich photos and text files toward the 20 MiB media limit

* fix(OTB-54): restore settings from backup in installed mode

* fix(OTB-77): do not show command or prompt errors after detach

* feat(OTB-74): apply the agent's configured model and variant on pick

* feat(OTB-75): show the subagent variant on the Model line

* feat(OTB-78): show the variant beside the model on /status and the pinned dashboard

* chore(release): v0.25.1

* test: install the model-selection mock the merge dropped

The session/message command tests define getStoredModelMock but the
vi.mock registration for model-selection-service was lost while resolving
the sync conflicts. The tests then read the real getStoredModel, which is
environment-dependent (local .env vs CI defaults), so the keyboard model
assertions failed on CI while passing locally.

---------

Signed-off-by: Mathias L. Baumann <mathias.baumann@frequenz.com>
Co-authored-by: AshCastle <119788134+ashcastle@users.noreply.github.com>
Co-authored-by: ashcastle <ashcastle@users.noreply.github.com>
Co-authored-by: Haochen <38915833+hcsum@users.noreply.github.com>
Co-authored-by: Ruslan Grinev <grinevruslan@gmail.com>
Co-authored-by: Iago Durán Romera <iagorobo24@gmail.com>
Co-authored-by: Iago Durán Romera <iagorobo24-hub@users.noreply.github.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Johell1NS <78345296+Johell1NS@users.noreply.github.com>
Co-authored-by: Johell1NS <alessio.perilli@me.com>
Co-authored-by: Renan Rodrigo Vignato <renanvignato@gmail.com>
Co-authored-by: Mathias L. Baumann <Marenz@users.noreply.github.com>
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.

3 participants