Skip to content

fix(help): hide plural aliases from help output#440

Closed
betegon wants to merge 10 commits intomainfrom
fix/hide-aliases-from-help
Closed

fix(help): hide plural aliases from help output#440
betegon wants to merge 10 commits intomainfrom
fix/hide-aliases-from-help

Conversation

@betegon
Copy link
Member

@betegon betegon commented Mar 17, 2026

Summary

Plural shortcut commands (sentry issues, sentry logs, sentry orgs, etc.) and sentry whoami were showing in the help output alongside the canonical grouped commands (sentry issue list, sentry log list, etc.), making it noisy. Hides them using Stricli's hideRoute — the commands still work, they just don't appear in sentry --help or shell completions.

Test plan

  • Run sentry — plural aliases no longer listed
  • Run sentry --help — same
  • Run sentry issues — still works

Plural shortcut commands (issues, orgs, logs, etc.) and whoami were
cluttering the help output alongside the canonical grouped commands.
Uses Stricli's hideRoute to suppress them from help and completions
while keeping them functional.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@github-actions
Copy link
Contributor

github-actions bot commented Mar 17, 2026

Semver Impact of This PR

🟢 Patch (bug fixes)

📋 Changelog Preview

This is how your changes will appear in the changelog.
Entries from this PR are highlighted with a left border (blockquote style).


New Features ✨

Init

  • Support org/project positional to pin org and project name by MathurAditya724 in #428
  • Show feedback hint after successful setup by betegon in #430
  • Add --team flag to relay team selection to project creation by MathurAditya724 in #403
  • Enforce canonical feature display order by betegon in #388
  • Accept multiple delimiter formats for --features flag by betegon in #386
  • Add git safety checks before wizard modifies files by betegon in #379
  • Add experimental warning before wizard runs by betegon in #378
  • Add init command for guided Sentry project setup by betegon in #283

Issue List

  • Auto-compact when table exceeds terminal height by BYK in #395
  • Redesign table to match Sentry web UI by BYK in #372

Other

  • (auth) Allow re-authentication without manual logout by BYK in #417
  • (trial) Auto-prompt for Seer trial + sentry trial list/start commands by BYK in #399
  • Add --json flag to help command for agent introspection by BYK in #432
  • Add sentry span list and sentry span view commands by betegon in #393
  • Support SENTRY_HOST as alias for SENTRY_URL by betegon in #409
  • Add --dry-run flag to mutating commands by BYK in #387
  • Return-based output with OutputConfig on buildCommand by BYK in #380
  • Add --fields flag for context-window-friendly JSON output by BYK in #373
  • Magic @ selectors (@latest, @most_frequent) for issue commands by BYK in #371
  • Input hardening against agent hallucinations by BYK in #370
  • Add response caching for read-only API calls by BYK in #330

Bug Fixes 🐛

Dsn

Init

  • Align multiselect hint lines with clack's visual frame by MathurAditya724 in #435
  • Make URLs clickable with OSC 8 terminal hyperlinks by MathurAditya724 in #423
  • Remove implementation detail from help text by betegon in #385
  • Truncate uncommitted file list to first 5 entries by MathurAditya724 in #381

Other

  • (api) Convert --data to query params for GET requests by BYK in #383
  • (docs) Remove double borders and fix column alignment on landing page tables by betegon in #369
  • (help) Hide plural aliases from help output by betegon in #440
  • (trace) Show span IDs in trace view and fix event_id mapping by betegon in #400
  • Show human-friendly names in trial list and surface plan trials by BYK in #412
  • Add trace ID validation to trace view + UUID dash-stripping by BYK in #375

Documentation 📚

  • Update AGENTS.md with patterns from span commands work by BYK in #433
  • Update credential storage docs and remove stale config.json references by betegon in #408

Internal Changes 🔧

Init

  • Remove --force flag by betegon in #377
  • Remove dead determine-pm step label by betegon in #374

Tests

  • Consolidate unit tests subsumed by property tests by BYK in #422
  • Remove redundant and low-value tests by BYK in #418

Other

  • (lint) Enforce command output conventions via Biome plugins by BYK in #439
  • (log/list) Convert non-follow paths to return CommandOutput by BYK in #410
  • Unified trace-target parsing and resolution by BYK in #438
  • Centralize slug normalization warning in parseOrgProjectArg by BYK in #436
  • Unify commands as generators with HumanRenderer factory, remove stdout plumbing by BYK in #416
  • Convert list command handlers to return data instead of writing stdout by BYK in #404
  • Split api-client.ts into focused domain modules by BYK in #405
  • Migrate non-streaming commands to CommandOutput with markdown rendering by BYK in #398
  • Convert Tier 2-3 commands to return-based output and consola by BYK in #394
  • Convert remaining Tier 1 commands to return-based output by BYK in #382
  • Converge Tier 1 commands to writeOutput helper by BYK in #376

Other

  • Minify JSON on read and pretty-print on write in init local ops by MathurAditya724 in #396

🤖 This preview updates automatically when you update the PR.

@betegon betegon marked this pull request as ready for review March 17, 2026 08:35
@github-actions
Copy link
Contributor

github-actions bot commented Mar 17, 2026

Codecov Results 📊

111 passed | Total: 111 | Pass Rate: 100% | Execution Time: 0ms

📊 Comparison with Base Branch

Metric Change
Total Tests
Passed Tests
Failed Tests
Skipped Tests

✨ No test changes detected

All tests are passing successfully.

✅ Patch coverage is 100.00%. Project has 1101 uncovered lines.
✅ Project coverage is 95.09%. Comparing base (base) to head (head).

Files with missing lines (2)
File Patch % Lines
arg-parsing.ts 94.41% ⚠️ 19 Missing
view.ts 93.97% ⚠️ 12 Missing
Coverage diff
@@            Coverage Diff             @@
##          main       #PR       +/-##
==========================================
+ Coverage    95.08%    95.09%    +0.01%
==========================================
  Files          165       165         —
  Lines        22390     22402       +12
  Branches         0         0         —
==========================================
+ Hits         21289     21301       +12
- Misses        1101      1101         —
- Partials         0         0         —

Generated by Codecov Action

MathurAditya724 and others added 8 commits March 17, 2026 09:39
## Summary

- Fix misaligned hint lines in the `sentry init` feature multiselect
prompt by prefixing them with clack's `│` bar character

## Problem

The multiselect hint lines ("Error Monitoring is always included" and
"space=toggle, a=all, enter=confirm") were rendered without clack's `│`
bar prefix, causing visual misalignment with the option lines below
them.

**Before:**
```
◆  Select features to enable
  Error Monitoring is always included
  space=toggle, a=all, enter=confirm
│  ◻ Session Replay
│  ◼ Performance Monitoring
└
```

**After:**
```
◆  Select features to enable
│  Error Monitoring is always included
│  space=toggle, a=all, enter=confirm
│  ◻ Session Replay
│  ◼ Performance Monitoring
└
```

## Root Cause

Clack's `multiselect` renderer does not split multi-line `message`
strings and prefix continuation lines with the `│` bar (unlike
`log.message()` which does). The hint lines were embedded in the message
with only manual ` ` padding, missing the `│ ` prefix that clack applies
to option lines.

## Fix

Prefix hint lines with `chalk.gray("│")` (U+2502) to match clack's
visual frame, keeping the bar gray (matching clack's coloring) and the
hint text dim.
Phase 1 of #346: Add structured JSON output to the `help` command so AI
agents can discover CLI commands at runtime.

## What

Three modes of `sentry help --json`:

- **Full tree**: `sentry help --json` → all routes, commands, flags,
positional params as JSON
- **Route group**: `sentry help --json issue` → group metadata with
subcommands
- **Specific command**: `sentry help --json issue list` → single
command's full metadata

Framework-injected flags (`help`, `helpAll`, `log-level`, `verbose`) are
stripped from JSON output so agents see only user-facing flags.

## Architecture

- **`src/lib/introspect.ts`** (new) — shared route-tree introspection
module with types, type guards, extraction functions, and JSON cleaning
utilities. Used at runtime by `help --json` and at build time by
`generate-skill.ts`.
- **`src/commands/help.ts`** — adds `output: "json"` and `--json` flag.
Dynamic imports for the route tree and introspect module to avoid
circular deps.
- **`src/lib/help.ts`** — consolidated to import shared types from
`introspect.ts` instead of duplicating them.
- **`script/generate-skill.ts`** — imports shared types and functions
from `introspect.ts`, removing ~100 lines of duplication. No functional
change to output.

## Tests

- 33 unit tests for introspection functions
- 12 property-based tests (fast-check) for invariants
- 10 integration tests for `help --json` end-to-end
…#436)

## Summary

Moves the slug normalization warning from 5 individual command files
into `parseOrgProjectArg()` itself. Every caller now gets the warning
automatically — no per-command boilerplate, and no risk of future
commands forgetting it.

### Changes

**`src/lib/arg-parsing.ts`** — core change:
- Added private `warnNormalized()` helper that builds a display slug
from the `ParsedOrgProject` variant
- Restructured `parseOrgProjectArg()` to emit the warning internally
before returning
- Improved message now includes the actual normalized value:
`Normalized slug to 'my-org/my-project' (Sentry slugs use dashes, never
underscores)`

**5 command files** — removed duplicate 3-line if-blocks:
- `src/commands/event/view.ts`
- `src/commands/log/view.ts`
- `src/commands/trace/view.ts`
- `src/commands/span/list.ts` (also removed now-unused
`logger.withTag()`)
- `src/commands/span/view.ts` (also removed now-unused `cmdLog`
variable)

**`test/lib/arg-parsing.test.ts`** — 6 new tests:
- Warning emitted for each variant: `project-search`, `explicit`
(org/project), `org-all`
- No warning for `auto-detect` or non-underscored slugs

### Before / After

**Before** — copy-pasted in every command:
```typescript
const parsed = parseOrgProjectArg(targetArg);
if (parsed.type !== "auto-detect" && parsed.normalized) {
  log.warn("Normalized slug (Sentry slugs use dashes, not underscores)");
}
```

**After** — callers just call the parser:
```typescript
const parsed = parseOrgProjectArg(targetArg);
// Warning emitted automatically inside parseOrgProjectArg
```

### Test Plan
- [x] `bun run typecheck` — passes
- [x] `bun run lint` — passes (0 errors)
- [x] `bun test test/lib/arg-parsing.test.ts` — 106 tests pass
- [x] `git grep 'Sentry slugs use dashes' -- 'src/'` — only matches
`arg-parsing.ts`

Closes #431
Enforce PR #433 `buildCommand` conventions via lint rules that run as
part of `bun run lint`:

## GritQL Plugins (new)

Two Biome GritQL plugins in `lint-rules/` ban anti-patterns in
`src/commands/`:

- **`no-stdout-write-in-commands`** — commands should yield
`CommandOutput`, not call `stdout.write()` directly
- **`no-process-stdout-in-commands`** — commands should not access
`process.stdout`

Both use `file($name, $body)` scoping so they only fire on command files
and produce inline editor diagnostics.

> **Note on Biome GritQL:** bare `$filename` / `$program` metavariables
don't work in Biome 2.3.8 plugins (they cause "didn't specify a valid
span" errors). The `file($name, $body)` pattern is the correct approach
— `$name` contains the full absolute path so regex needs `.*` anchors.

## noRestrictedImports (new)

Biome override bans `chalk` imports in `src/commands/**/*.ts`, directing
developers to `colorTag()` from the markdown rendering pipeline which
respects `NO_COLOR` / `SENTRY_PLAIN_OUTPUT`.

## Bug fix

Fix `muted()` usage in `src/commands/issue/view.ts` to use the
`isPlainOutput()` pattern, so span-tree fallback messages don't leak
ANSI codes in plain-output mode.
Extract shared trace-target parsing and resolution into
`src/lib/trace-target.ts`, replacing duplicated positional argument
parsing and target resolution logic across 4 commands.

## New shared module: `src/lib/trace-target.ts`

**`parseTraceTarget(args, usageHint)`** — Parses positional args into a
discriminated union:
- `<trace-id>` → `auto-detect`
- `<org>/<trace-id>` → `org-scoped`
- `<org>/<project>/<trace-id>` → `explicit`
- `<target> <trace-id>` → delegates to `parseOrgProjectArg`

**`resolveTraceOrgProject(parsed, cwd, hint)`** — For commands needing
org+project (span list, span view, trace view)

**`resolveTraceOrg(parsed, cwd, hint)`** — For org-scoped commands
(trace logs)

## Commands migrated

| Command | Lines removed | What changed |
|---------|--------------|--------------|
| `span list` | ~55 | Replaced `parsePositionalArgs` + 4-way switch |
| `span view` | ~40 | Replaced `parsePositionalArgs` + `resolveTarget`
helper |
| `trace view` | ~83 | Replaced `parsePositionalArgs` + switch; kept
swap detection as `preProcessArgs` |
| `trace logs` | ~44 | Replaced custom slash parsing + `resolveOrg` call
|

Net: **-29 lines** (777 added to shared module + tests, 806 removed from
commands)

Closes #434
#428)

## Summary

Redesign `sentry init` to support smart positional arguments for
org/project targeting and directory specification.

### Supported forms

```
sentry init                           # auto-detect everything, dir = cwd
sentry init .                         # dir = cwd, auto-detect org
sentry init ./subdir                  # dir = subdir, auto-detect org
sentry init acme/                     # explicit org, dir = cwd
sentry init acme/my-app               # explicit org + project, dir = cwd
sentry init my-app                    # search for project across orgs → sets org + project
sentry init acme/ ./subdir            # explicit org, dir = subdir
sentry init acme/my-app ./subdir      # explicit org + project, dir = subdir
sentry init ./subdir acme/            # swapped → auto-correct with warning
sentry init ./subdir acme/my-app      # swapped → auto-correct with warning
```

### Design

Two optional positionals with smart disambiguation:
- **Path-like args** (starting with `.` `/` `~` `~/`) are treated as the
**directory**
- **Everything else** is treated as the **org/project target**
- When args are in wrong order (path first, target second), they are
**auto-swapped with a warning** — following the established swap pattern
from view commands
- **Bare slugs** (e.g., `my-app`) are resolved via
`resolveProjectBySlug` to search across all accessible orgs, setting
both org and project from the match
- **Two paths** or **two targets** → error with helpful message
- User-provided org/project slugs are validated via `validateResourceId`
at parse time; API-resolved values from `resolveProjectBySlug` skip
redundant validation

### Files changed

| File | Change |
|---|---|
| `src/lib/arg-parsing.ts` | Add `looksLikePath()` for syntactic path
detection (no filesystem I/O) |
| `src/commands/init.ts` | Two positionals, `classifyArgs()`
disambiguation, `resolveTarget()` with `resolveProjectBySlug` for bare
slugs, `validateResourceId` on user-provided slugs only |
| `src/lib/init/types.ts` | Add `org?` and `project?` to `WizardOptions`
|
| `src/lib/init/local-ops.ts` | Use `options.org`/`options.project` in
`createSentryProject()` to skip interactive org resolution and override
wizard-detected project name |
| `test/commands/init.test.ts` | 26 tests covering all arg combinations,
swap detection, error cases |

### Breaking change

`sentry init <directory>` no longer works for bare directory names
(e.g., `sentry init mydir`). Use path syntax: `sentry init ./mydir`.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Instead of just hiding plural aliases, show them as muted hints next to
their parent command (e.g. "alias: sentry issues" next to issue).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reverts the inline alias hints — aliases should only be excluded from
SKILL.md generation, not decorated in the help output.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

}
}
}
}
Copy link

Choose a reason for hiding this comment

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

Override replaces global restricted imports for command files

Medium Severity

The new noRestrictedImports override for src/commands/**/*.ts only declares @stricli/core and chalk restrictions. Biome overrides replace (not merge) rule configurations for matching files, so the global node:fs and node:process import restrictions are silently dropped for all command files. The intent was to add the chalk restriction on top of the existing ones, but the override loses the other two.

Fix in Cursor Fix in Web

@betegon
Copy link
Member Author

betegon commented Mar 17, 2026

closing this. see #441

@betegon betegon closed this Mar 17, 2026
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