Skip to content

feat(cli): add --project and --search filters to workspaces list#4455

Merged
saddlepaddle merged 2 commits into
mainfrom
cli-filtering-options
May 12, 2026
Merged

feat(cli): add --project and --search filters to workspaces list#4455
saddlepaddle merged 2 commits into
mainfrom
cli-filtering-options

Conversation

@saddlepaddle
Copy link
Copy Markdown
Collaborator

@saddlepaddle saddlepaddle commented May 12, 2026

Summary

  • superset workspaces list was getting long once you've accumulated workspaces across multiple projects.
  • Adds --project <name|uuid> — case-insensitive exact name match, UUID-shape input routed to projectId. Project slugs aren't surfaced anywhere in the UI, so name (as shown in the desktop sidebar) is the natural ergonomic key.
  • Adds --search <substring> / -s — matches workspace name OR branch as %pattern%, same shape as the existing tasks list --search.
  • Extends v2Workspace.list tRPC input and @superset/sdk WorkspaceListParams in 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 to projectId, 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 typecheck both clean across the monorepo

Summary by cubic

Adds --project and --search filters to superset workspaces list to 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 to projectId.
    • --search <substring> / -s matches workspace name or branch and composes with --host/--local.
    • Added projectId, projectName, and search to v2Workspace.list and @superset/sdk WorkspaceListParams.
  • Bug Fixes

    • Escape \, %, and _ in search before ILIKE to prevent unintended wildcards.
    • Use lower(name) = lower(input) for projectName to enforce true exact match.

Written for commit 1004a0c. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Enhanced workspace filtering: filter by project ID (UUID), project name, or perform text searches across workspace names and branches.
    • CLI improvements: the --project option now accepts either a UUID (treated as project ID) or a name (treated as project name), and a --search option is supported for substring matches.

Review Change Stack

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-ai
Copy link
Copy Markdown

capy-ai Bot commented May 12, 2026

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.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 55299e3e-d49b-4d44-859f-e8fb17330868

📥 Commits

Reviewing files that changed from the base of the PR and between ce94f74 and 1004a0c.

📒 Files selected for processing (1)
  • packages/trpc/src/router/v2-workspace/v2-workspace.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/trpc/src/router/v2-workspace/v2-workspace.ts

📝 Walkthrough

Walkthrough

Adds 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 --project into ID vs name and forwards search.

Changes

Workspace Filtering

Layer / File(s) Summary
SDK interface contract
packages/sdk/src/resources/workspaces.ts
WorkspaceListParams interface gains optional projectId, projectName, and search filters.
tRPC router list endpoint filtering
packages/trpc/src/router/v2-workspace/v2-workspace.ts
Import or/sql, extend v2WorkspaceRouter.list input schema, escape search into a %...% pattern, compose or ilike checks for name and branch, and extend the DB where clause with projectId and case-insensitive projectName predicate.
CLI command project/search option handling
packages/cli/src/commands/workspaces/list/command.ts
Add UUID_RE regex to detect whether --project is a UUID or name, route it as projectId or projectName, and pass search to ctx.api.v2Workspace.list.query.

🎯 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
Loading

🐰 I hopped through code with nimble pace,
Project name or id — I know your case,
I nibble search strings, escape each trace,
Workspaces found in their branching place. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and accurately summarizes the main changes: adding --project and --search filters to the workspaces list command.
Description check ✅ Passed The PR description comprehensively covers the changes, includes a detailed test plan, and addresses the template sections adequately despite not following the exact template structure.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cli-filtering-options

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.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 12, 2026

Greptile Summary

This PR adds --project <name|uuid> and --search <substring> filters to superset workspaces list, wiring them through the tRPC router and SDK WorkspaceListParams in lockstep. The CLI correctly dispatches UUID-shaped input to projectId and plain text to projectName, keeping the two mutually exclusive at the call site.

  • CLI (command.ts): UUID detection regex correctly routes the single --project flag to either projectId or projectName; both are passed correctly to the tRPC query.
  • tRPC (v2-workspace.ts): projectId and search filters are implemented correctly; the projectName filter uses ilike without escaping LIKE metacharacters (%, _), which breaks the stated "exact match" semantics for any project whose name contains an underscore.
  • SDK (workspaces.ts): New fields are properly typed and documented on WorkspaceListParams; no logic changes here.

Confidence Score: 3/5

The 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.

Important Files Changed

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

Comment on lines +164 to +165
input.projectName
? ilike(v2Projects.name, input.projectName)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 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.

Comment on lines +130 to +136
const searchPattern = input.search ? `%${input.search}%` : null;
const searchMatch = searchPattern
? or(
ilike(v2Workspaces.name, searchPattern),
ilike(v2Workspaces.branch, searchPattern),
)
: undefined;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 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.

Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 12, 2026

🧹 Preview Cleanup Complete

The following preview resources have been cleaned up:

  • ✅ Neon database branch

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.
Copy link
Copy Markdown
Contributor

@cubic-dev-ai cubic-dev-ai Bot left a comment

Choose a reason for hiding this comment

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

No issues found across 3 files

@saddlepaddle saddlepaddle merged commit 7fb1d35 into main May 12, 2026
17 checks passed
@saddlepaddle saddlepaddle mentioned this pull request May 12, 2026
3 tasks
saddlepaddle added a commit that referenced this pull request May 12, 2026
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.
@saddlepaddle saddlepaddle mentioned this pull request May 13, 2026
3 tasks
saddlepaddle added a commit that referenced this pull request May 13, 2026
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`.
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.

1 participant