feat(cli): add --project and --search filters to workspaces list#4455
Conversation
The list was getting long once you've accumulated workspaces across multiple projects. Adds `--project <name|uuid>` (case-insensitive name match, UUID-shape input routed to projectId) and `--search <substring>` (matches workspace name or branch) on `superset workspaces list`. The underlying v2Workspace.list tRPC input and SDK WorkspaceListParams are extended in lockstep so the SDK keeps mirroring the CLI.
|
Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds optional projectId/projectName and search filters to workspace listing: SDK param types updated, tRPC router accepts and applies project/search filters with LIKE-safe matching and case-insensitive project name comparison, and CLI routes ChangesWorkspace Filtering
🎯 3 (Moderate) | ⏱️ ~20 minutes sequenceDiagram
participant CLI as CLI
participant Router as v2WorkspaceRouter
participant DB as Database
CLI->>Router: list(projectId?, projectName?, search?)
Router->>Router: escape search -> build "%search%" pattern
Router->>Router: build OR(name ILIKE, branch ILIKE)
Router->>DB: query with projectId?/lower(projectName)=lower(...) and searchMatch
DB-->>Router: filtered workspaces
Router-->>CLI: return results
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
Greptile SummaryThis PR adds
Confidence Score: 3/5The CLI and SDK layers are clean, but the tRPC router's projectName filter doesn't escape LIKE metacharacters, so the stated exact-match contract silently breaks for any project whose name contains an underscore. The projectName ilike filter passes the raw user string as a LIKE pattern. Because _ is a single-character wildcard in PostgreSQL ILIKE, a project named my_project also matches myXproject. Underscore-bearing project names are common, so the broken semantics are likely to surface in real usage. packages/trpc/src/router/v2-workspace/v2-workspace.ts — both the projectName ilike filter and the search pattern interpolation need LIKE metacharacter escaping.
|
| Filename | Overview |
|---|---|
| packages/trpc/src/router/v2-workspace/v2-workspace.ts | Adds projectId, projectName, and search filter conditions to the list query. projectName uses ilike without escaping wildcards, breaking the promised exact-match semantics; search has the same metacharacter issue for _. |
| packages/cli/src/commands/workspaces/list/command.ts | Adds --project and --search CLI flags with correct UUID detection logic; correctly enforces mutual exclusivity between projectId and projectName before sending to the API. |
| packages/sdk/src/resources/workspaces.ts | Extends WorkspaceListParams with projectId, projectName, and search fields, consistent with the tRPC schema addition. |
Prompt To Fix All With AI
Fix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
packages/trpc/src/router/v2-workspace/v2-workspace.ts:164-165
**`projectName` filter silently over-matches due to unescaped LIKE metacharacters**
`ilike(v2Projects.name, input.projectName)` passes the user-supplied string directly as the LIKE pattern. PostgreSQL's `ILIKE` treats `%` and `_` as wildcards, so a project named `my_project` would also match `myXproject`, `my.project`, etc. Similarly, passing `--project foo%` matches every project whose name starts with `foo`. The PR description explicitly promises "case-insensitive exact match" semantics, so any project name containing `_` or `%` violates that contract. Use a case-folded equality expression instead, for example: `` sql`lower(${v2Projects.name}) = lower(${input.projectName})` ``.
### Issue 2 of 2
packages/trpc/src/router/v2-workspace/v2-workspace.ts:130-136
**`search` pattern interpolation doesn't escape LIKE metacharacters**
`%${input.search}%` embeds the raw user string into the LIKE pattern. If the search term contains `_`, each underscore acts as a wildcard matching any single character — `feat_my-branch` in the search field would match `feat-my-branch`, `featXmy_branch`, etc., producing false positives. While `%` as a wildcard is arguably intentional for substring search, stray `_` characters (very common in branch names and workspace names) will broaden results unexpectedly. Consider escaping `_` and `\` before interpolating.
Reviews (1): Last reviewed commit: "feat(cli): add --project and --search to..." | Re-trigger Greptile
| input.projectName | ||
| ? ilike(v2Projects.name, input.projectName) |
There was a problem hiding this comment.
projectName filter silently over-matches due to unescaped LIKE metacharacters
ilike(v2Projects.name, input.projectName) passes the user-supplied string directly as the LIKE pattern. PostgreSQL's ILIKE treats % and _ as wildcards, so a project named my_project would also match myXproject, my.project, etc. Similarly, passing --project foo% matches every project whose name starts with foo. The PR description explicitly promises "case-insensitive exact match" semantics, so any project name containing _ or % violates that contract. Use a case-folded equality expression instead, for example: sql`lower(${v2Projects.name}) = lower(${input.projectName})`.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/src/router/v2-workspace/v2-workspace.ts
Line: 164-165
Comment:
**`projectName` filter silently over-matches due to unescaped LIKE metacharacters**
`ilike(v2Projects.name, input.projectName)` passes the user-supplied string directly as the LIKE pattern. PostgreSQL's `ILIKE` treats `%` and `_` as wildcards, so a project named `my_project` would also match `myXproject`, `my.project`, etc. Similarly, passing `--project foo%` matches every project whose name starts with `foo`. The PR description explicitly promises "case-insensitive exact match" semantics, so any project name containing `_` or `%` violates that contract. Use a case-folded equality expression instead, for example: `` sql`lower(${v2Projects.name}) = lower(${input.projectName})` ``.
How can I resolve this? If you propose a fix, please make it concise.| const searchPattern = input.search ? `%${input.search}%` : null; | ||
| const searchMatch = searchPattern | ||
| ? or( | ||
| ilike(v2Workspaces.name, searchPattern), | ||
| ilike(v2Workspaces.branch, searchPattern), | ||
| ) | ||
| : undefined; |
There was a problem hiding this comment.
search pattern interpolation doesn't escape LIKE metacharacters
%${input.search}% embeds the raw user string into the LIKE pattern. If the search term contains _, each underscore acts as a wildcard matching any single character — feat_my-branch in the search field would match feat-my-branch, featXmy_branch, etc., producing false positives. While % as a wildcard is arguably intentional for substring search, stray _ characters (very common in branch names and workspace names) will broaden results unexpectedly. Consider escaping _ and \ before interpolating.
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/trpc/src/router/v2-workspace/v2-workspace.ts
Line: 130-136
Comment:
**`search` pattern interpolation doesn't escape LIKE metacharacters**
`%${input.search}%` embeds the raw user string into the LIKE pattern. If the search term contains `_`, each underscore acts as a wildcard matching any single character — `feat_my-branch` in the search field would match `feat-my-branch`, `featXmy_branch`, etc., producing false positives. While `%` as a wildcard is arguably intentional for substring search, stray `_` characters (very common in branch names and workspace names) will broaden results unexpectedly. Consider escaping `_` and `\` before interpolating.
How can I resolve this? If you propose a fix, please make it concise.
🧹 Preview Cleanup CompleteThe following preview resources have been cleaned up:
Thank you for your contribution! 🎉 |
`ilike` on the raw user string lets `%` and `_` act as wildcards, so `--project my_project` would also have matched `myXproject`, and `--search cli_x` would have matched `cli-x` etc. Switch projectName to a case-folded equality (`lower(name) = lower(input)`) for true exact match, and escape `\\`, `%`, `_` in the search input before wrapping with `%…%`. Caught by Greptile review on #4455.
Changes since v0.2.14: - workspaces: `superset workspaces list` now accepts `--project` and `--search` filters, matching the desktop list view. (#4455) - cli-framework: `--help` on a subcommand now shows the global options (e.g. `--json`, `--quiet`, `--api-key`) instead of hiding them. (#4424) - host-service: attachment upload no longer rejects unknown mediaType values returned by some hosts. (#4439) - host-service: PR fetch is now per-branch, avoiding 504s on repos with large numbers of open PRs. (#4268) Push cli-v0.2.15 after this lands to fire the release pipeline.
Changes since alpha.9: - workspaces.list accepts `projectId`, `projectName`, and `search` to filter the listing — matches the desktop list view. (#4455) - chore(deps): pin exact dev versions (`bun-types` 1.3.11, `typescript` 5.9.3). (#4436) - BREAKING: `automations.create` / `automations.update` / `AutomationSummary` rename `agentConfig` -> `agent` (string id of a host agent instance or preset, e.g. `claude`, `codex`, `superset`). The `AgentConfig` type is removed from the public surface. The host now resolves the live agent config on every run, so client-side snapshots no longer drift from `Settings → Agents` edits. (#4481) After merge: `cd packages/sdk && bun run build && cd dist && npm publish --access public`.
Summary
superset workspaces listwas getting long once you've accumulated workspaces across multiple projects.--project <name|uuid>— case-insensitive exact name match, UUID-shape input routed toprojectId. Project slugs aren't surfaced anywhere in the UI, so name (as shown in the desktop sidebar) is the natural ergonomic key.--search <substring>/-s— matches workspace name OR branch as%pattern%, same shape as the existingtasks list --search.v2Workspace.listtRPC input and@superset/sdkWorkspaceListParamsin lockstep so the SDK keeps mirroring the CLI 1:1.Test plan
Verified against the local API with three projects (Superset, openclaw, mastra-superset) and ~30 workspaces:
--project openclaw→ only the 1 openclaw row--project SUPERSET(uppercase) → Superset rows (case-insensitive name match)--project 9ee3c9b7-…(UUID) → routed toprojectId, returned the openclaw row--search cli→ 3 workspaces, all matching name or branch substring (cli-deep-links,cli-filtering-options,align-sdk-cli-mcp-…)--project Superset --search cli→ AND-composes correctly--project DoesNotExist/--search xyzqqzxyz→[]bun run lint,bun run typecheckboth clean across the monorepoSummary by cubic
Adds
--projectand--searchfilters tosuperset workspaces listto quickly narrow workspaces. Also hardens server-side filtering to ensure exact project-name matches and safe substring search.New Features
--project <name|uuid>filters by project; case-insensitive exact name match, or UUID routed toprojectId.--search <substring>/-smatches workspace name or branch and composes with--host/--local.projectId,projectName, andsearchtov2Workspace.listand@superset/sdkWorkspaceListParams.Bug Fixes
\,%, and_insearchbeforeILIKEto prevent unintended wildcards.lower(name) = lower(input)forprojectNameto enforce true exact match.Written for commit 1004a0c. Summary will update on new commits.
Summary by CodeRabbit