Skip to content

feat(cli): launch completion — shell completions (bash/zsh/fish) with dynamic completion#232

Merged
YosefHayim merged 3 commits into
mainfrom
feat/222-completion
Jun 21, 2026
Merged

feat(cli): launch completion — shell completions (bash/zsh/fish) with dynamic completion#232
YosefHayim merged 3 commits into
mainfrom
feat/222-completion

Conversation

@YosefHayim

@YosefHayim YosefHayim commented Jun 20, 2026

Copy link
Copy Markdown
Owner

User description

What

Adds the launch completion command group:

  • launch completion <bash|zsh|fish> — prints the completion script to stdout.
  • launch completion install [--shell <s>] — idempotently wires the script into the shell's rc file via a fenced # launch-completion start/end managed block (re-running never duplicates), or prints the manual step when it can't safely edit (e.g. fish without ~/.config/fish).
  • Hidden __complete callback that computes candidates by walking the live commander tree — new commands appear with no reinstall, and dynamic values resolve through existing core loaders: app handles (-a/--app), -p/--profile, plan/drift surfaces, and snapshot diff/export names.

Why (developer journey)

59 commands + ~30 flags with no tab-completion = an invisible surface. Tab-completion is how a newcomer discovers commands (launch <Tab>) and how the daily user avoids typos on handles/flags. It's the discoverability on-ramp for everything else. Part of #180.

Design

  • Callback model (same as gh/kubectl/helm): the emitted script is tiny and stable; it shells back to launch completion __complete on every <Tab>. Keeps the static script future-proof and lets dynamic values stay live.
  • CLI stays thin per AGENTS.md — all script generation, rc-file splicing (pure spliceManagedBlock), and candidate resolution live in core/completion.ts. The command file is pure commander wiring.
  • scripts/gen-docs.ts now flattens via commander's visibleCommands(), so the internal __complete never leaks into the public reference or llms.txt.
  • New Shell type added to core/types.ts (single source of truth).

Tests

core/completion.test.ts covers each shell's script output, install idempotency (running twice yields one block), spliceManagedBlock surgery, shell detection, and the candidate resolver's precedence; CLI integration test beside it. Full gate green: typecheck, lint, 1632 tests, build, format:check, docs:check (in sync).

Closes #222

🤖 Generated with Claude Code


Summary by cubic

Add launch completion with dynamic tab-completion for bash, zsh, and fish so commands, flags, and app-specific values are discoverable without reinstall. Fixes improve mid-line and nested subcommand completion and correct flag-value vs positional detection. Implements #222.

  • New Features

    • launch completion <bash|zsh|fish> prints the script; defaults to $SHELL when omitted.
    • launch completion install adds a managed # launch-completion start/end block; safe to re-run and prints a manual step if it can’t edit (e.g. fish without ~/.config/fish).
    • Hidden __complete walks the live commander tree; completes -a/--app, -p/--profile, plan/drift surfaces, and snapshot diff/export.
    • Docs gen skips hidden commands via visibleCommands(); command ref shows 61 commands and badges show 1651 tests.
  • Bug Fixes

    • Bash: slice COMP_WORDS to COMP_CWORD for correct mid-line completion.
    • Zsh: pass words[2,CURRENT] with (@) so tokens stay separate; fixes nested subcommands.
    • Treat values after value-taking flags as non-positionals, so dynamic positional suggestions still appear (e.g. after --app web).

Written for commit c8042ef. Summary will update on new commits.

Review in cubic


CodeAnt-AI Description

Add shell tab completion for the Launch CLI

What Changed

  • Added launch completion to print completion scripts for bash, zsh, and fish, plus an install command to wire them into the shell config
  • Completion now suggests command names, flags, app handles, profiles, plan/drift surfaces, and snapshot names as you type
  • Re-running install keeps a single managed block in the shell config instead of duplicating it
  • The internal completion callback stays out of the public command reference and generated docs

Impact

✅ Faster command discovery
✅ Fewer typos in flags and app handles
✅ No duplicate shell setup lines

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

Summary by CodeRabbit

  • New Features

    • Added launch completion to provide shell tab-completion, including automatic script output and an install option for bash, zsh, and fish (with a manual fallback when rc updates aren’t possible).
  • Documentation

    • Updated CLI command docs to include new help [command] coverage and refreshed generated command listings.
    • Updated CI test-count badges across all README language variants to 1651 passing.
  • Tests

    • Added/expanded comprehensive Vitest coverage for completion command wiring, completion resolution behavior, and managed-block installation logic.

…th dynamic completion

Add `launch completion <bash|zsh|fish>` (prints the script), `launch completion
install` (idempotently wires it into the shell rc via a fenced managed block,
or prints the manual step), and a hidden `__complete` callback that resolves
candidates by walking the live commander tree — so new commands appear with no
reinstall, and dynamic values (app handles, -p/--profile, plan/drift surfaces,
snapshot names) resolve through the existing core loaders.

CLI stays pure commander wiring; all script generation, rc-file splicing, and
candidate resolution live in core/completion.ts. gen-docs now flattens via
commander's visibleCommands() so the internal __complete never leaks into the
public reference or llms.txt.

Closes #222

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@YosefHayim YosefHayim added the enhancement New feature or request label Jun 20, 2026
@qodo-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@changeset-bot

changeset-bot Bot commented Jun 20, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c8042ef

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@codeant-ai

codeant-ai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@coderabbitai

coderabbitai Bot commented Jun 20, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 930e9a3f-cec8-4170-82fd-126f14620f15

📥 Commits

Reviewing files that changed from the base of the PR and between 76c2183 and c8042ef.

📒 Files selected for processing (14)
  • README.de.md
  • README.es.md
  • README.fr.md
  • README.ja.md
  • README.ko.md
  • README.md
  • README.pt-BR.md
  • README.ru.md
  • README.zh-CN.md
  • docs/commands.md
  • llms.txt
  • src/core/completion.test.ts
  • src/core/completion.ts
  • src/core/types.ts
✅ Files skipped from review due to trivial changes (11)
  • README.md
  • README.ja.md
  • README.ko.md
  • README.de.md
  • README.zh-CN.md
  • README.pt-BR.md
  • README.ru.md
  • README.es.md
  • README.fr.md
  • llms.txt
  • docs/commands.md
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/core/types.ts
  • src/core/completion.test.ts
  • src/core/completion.ts

📝 Walkthrough

Walkthrough

Adds launch completion CLI command supporting bash, zsh, and fish tab-completion. A new src/core/completion.ts module handles shell detection, per-shell script generation, idempotent rc-file installation, and dynamic candidate resolution via the Commander tree. The CLI registrar and program wiring are added alongside comprehensive tests. gen-docs.ts is fixed to skip hidden subcommands, triggering regeneration of docs/commands.md and llms.txt. Test-count badges in all nine README localizations are updated from 1620 to 1651.

Changes

Shell Completion Feature

Layer / File(s) Summary
Shell type and core completion constants
src/core/types.ts, src/core/completion.ts
Exports the Shell union type ("bash" | "zsh" | "fish"), declares SHELLS constant, managed-block fence markers, the hidden COMPLETE_SUBCOMMAND token, and parseShell/detectShell helpers.
Per-shell script generators and rc-file installation
src/core/completion.ts
Implements bashCompletionScript, zshCompletionScript, fishCompletionScript, completionScript dispatcher, spliceManagedBlock for idempotent fenced-block splicing, and installCompletion returning discriminated installed/manual results.
Dynamic completion candidate resolution
src/core/completion.ts
Implements resolveCompletions, which descends the Commander tree and applies precedence: flag names for --prefixed tokens, dynamic -a/--app or -p/--profile values, positional candidates from plan/snapshot registries, or subcommand names and flags. Failures are swallowed via safe().
Core completion module tests
src/core/completion.test.ts
273-line Vitest suite covering all of parseShell, detectShell, completionScript, spliceManagedBlock, installCompletion, and resolveCompletions including config-loading, app-discovery, fish-fallback, and no-config paths.
CLI completion command and program wiring
src/cli/commands/completion.ts, src/cli/program.ts
Adds registerCompletionCommand attaching completion [shell], completion install, and hidden __complete subcommands; wires it into buildProgram() alongside other register*Command calls.
CLI completion command registration tests
src/cli/commands/completion.test.ts
Vitest suite asserting command group registration, optional shell argument, install's --shell option, and __complete hidden-from-help behavior.
Documentation generation fix and regenerated docs
scripts/gen-docs.ts, docs/commands.md, llms.txt
Fixes toSpec to use visibleCommands instead of command.commands, preventing __complete from appearing in generated docs. Regenerates docs/commands.md with help [command] subsections for all groups and launch completion documentation; updates llms.txt to reflect 61 commands.

README Test-Count Badge Update

Layer / File(s) Summary
Test-count badge bump across all localized READMEs
README.md, README.de.md, README.es.md, README.fr.md, README.ja.md, README.ko.md, README.pt-BR.md, README.ru.md, README.zh-CN.md
Single-line change in each localized README updating the CI "tests passing" badge from 1620 to 1651.

Sequence Diagram(s)

sequenceDiagram
  participant User as User Shell
  participant LaunchCLI as launch CLI
  participant CompletionCore as src/core/completion.ts
  participant ConfigApps as launch.config.ts / apps/

  rect rgba(100, 150, 200, 0.5)
  Note over User,ConfigApps: Install completion to shell rc file
  User->>LaunchCLI: launch completion install [--shell zsh]
  LaunchCLI->>CompletionCore: installCompletion({ shell })
  CompletionCore->>CompletionCore: detectShell() or parseShell()
  CompletionCore->>CompletionCore: spliceManagedBlock(rcContents, block)
  CompletionCore-->>LaunchCLI: InstallResult { status: "installed" | "manual" }
  LaunchCLI-->>User: logs outcome or prints manual step
  end

  rect rgba(200, 150, 100, 0.5)
  Note over User,ConfigApps: Print completion script
  User->>LaunchCLI: launch completion zsh
  LaunchCLI->>CompletionCore: completionScript("zsh")
  CompletionCore-->>LaunchCLI: zsh script string
  LaunchCLI-->>User: process.stdout.write(script)
  end

  rect rgba(150, 200, 100, 0.5)
  Note over User,ConfigApps: Resolve tab-completion candidates
  User->>LaunchCLI: __complete [typed words...]
  LaunchCLI->>CompletionCore: resolveCompletions(words, program)
  CompletionCore->>ConfigApps: load profile / discover apps / query registry
  ConfigApps-->>CompletionCore: candidate values[]
  CompletionCore-->>LaunchCLI: string[] candidates
  LaunchCLI-->>User: newline-separated completions
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Poem

🐇 Hop, hop, <Tab> away,
No more typing every day!
launch completion install — done in a flash,
Bash and zsh and fish make a dash.
The rabbit typed launch and the shells all said:
"We know every flag, every app, every thread!" 🎉

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main feature: introduction of launch completion command with shell completions for bash/zsh/fish and dynamic completion support.
Linked Issues check ✅ Passed The PR fully addresses all coding requirements from #222: implements launch completion command, supports bash/zsh/fish shells with dynamic app/profile/surface completion, uses callback model, and includes comprehensive tests.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the completion feature: new completion modules, updated documentation generation, test badges, and command tree registration.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ 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 feat/222-completion

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.

@codeant-ai codeant-ai Bot added the size:XL This PR changes 500-999 lines, ignoring generated files label Jun 20, 2026
Comment thread src/core/completion.ts
Comment on lines +285 to +305
export type InstallResult =
| {
/** Launch wrote the managed block into the rc file. */
readonly status: "installed";
/** The shell that was wired up. */
readonly shell: Shell;
/** Absolute path to the rc file that was written. */
readonly rcFile: string;
/** Whether an existing managed block was replaced (`true`) vs. a fresh block appended (`false`). */
readonly updated: boolean;
}
| {
/** Launch could not safely edit the rc file; the user should add {@link line} by hand. */
readonly status: "manual";
/** The shell the steps are for. */
readonly shell: Shell;
/** Absolute path to the rc file the line belongs in. */
readonly rcFile: string;
/** The exact line to add to the rc file. */
readonly line: string;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Move this exported result shape to src/core/types.ts and import it here, so domain-level public types stay centralized instead of being defined in a feature module. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This is a public domain-level shape exported from a feature module, which matches the rule requiring shared domain shapes and provider interfaces to live in src/core/types.ts rather than being defined inline elsewhere. The violation is real and directly visible in the existing code.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/core/completion.ts
**Line:** 285:305
**Comment:**
	*Custom Rule: Move this exported result shape to `src/core/types.ts` and import it here, so domain-level public types stay centralized instead of being defined in a feature module.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src/core/completion.ts
Comment on lines +308 to +313
export interface InstallOptions {
/** The shell to wire up. Defaults to {@link detectShell}; throws when neither is resolvable. */
shell?: Shell;
/** Home directory to resolve the rc file under — overridable so tests don't touch the real `~`. */
home?: string;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Relocate this exported options interface to src/core/types.ts and consume it via import in this module to follow the single-source rule for shared type definitions. [custom_rule]

Severity Level: Minor ⚠️

Why it matters? 🤔

This exported interface is defined directly in src/core/completion.ts instead of being centralized in src/core/types.ts, which violates the rule against redefining shared domain shapes outside the core types file. The suggestion accurately identifies that real violation.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/core/completion.ts
**Line:** 308:313
**Comment:**
	*Custom Rule: Relocate this exported options interface to `src/core/types.ts` and consume it via import in this module to follow the single-source rule for shared type definitions.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src/core/completion.ts Outdated
Comment on lines +82 to +83
words=("\${COMP_WORDS[@]:1}")
candidates="$(launch completion ${COMPLETE_SUBCOMMAND} -- "\${words[@]}" 2>/dev/null)"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Bash completion passes all tokens after launch, not the tokens up to the cursor position. Since the resolver assumes the last token is the active one, completions become wrong when the user triggers tab completion in the middle of a command line. Slice COMP_WORDS using COMP_CWORD (or otherwise pass cursor-aware tokens) so the callback receives only the active prefix context. [api mismatch]

Severity Level: Major ⚠️
- ⚠️ Bash mid-line completion suggests candidates for wrong token.
- ⚠️ Editing long commands interactively becomes confusing and error-prone.
Steps of Reproduction ✅
1. Bash users enable completion via `launch completion bash`, which invokes
`bashCompletionScript()` defined in `src/core/completion.ts:78-88`; the emitted script
defines `_launch_complete` and wires it with `complete -o default -F _launch_complete
launch` at line 86.

2. The `_launch_complete` function in that script sets `words=("${COMP_WORDS[@]:1}")` and
then calls the Node callback as `candidates="$(launch completion ${COMPLETE_SUBCOMMAND} --
"${words[@]}" 2>/dev/null)"` (lines 82-83 in `src/core/completion.ts`), forwarding ALL
tokens after `launch`, regardless of the current cursor position.

3. In an interactive bash session, consider a line `launch snapshot diff prod other` where
the user moves the cursor back to the `"prod"` word and presses `<Tab>`. Bash sets
`COMP_WORDS=("launch" "snapshot" "diff" "prod" "other")` and `COMP_CWORD=3`, but
`_launch_complete` still forwards `words=("snapshot" "diff" "prod" "other")` to `launch
completion __complete`, so the Node handler in `src/cli/commands/completion.ts:55-61`
receives `["snapshot","diff","prod","other"]`.

4. `resolveCompletions` at `src/core/completion.ts:225-241` uses `current =
words[words.length - 1]` (line 227), which in this mid-line case becomes `"other"` instead
of the word under the cursor (`"prod"`). This causes the resolver to compute candidates
based on the trailing context rather than the active token, so the suggestions the user
sees while editing the middle of a command reflect `"other"` and not `"prod"`, leading to
incorrect or missing completions for mid-line edits.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/core/completion.ts
**Line:** 82:83
**Comment:**
	*Api Mismatch: Bash completion passes all tokens after `launch`, not the tokens up to the cursor position. Since the resolver assumes the last token is the active one, completions become wrong when the user triggers tab completion in the middle of a command line. Slice `COMP_WORDS` using `COMP_CWORD` (or otherwise pass cursor-aware tokens) so the callback receives only the active prefix context.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src/core/completion.ts Outdated
return `# launch (zsh) completion — eval with: source <(launch completion zsh)
_launch_complete() {
local -a candidates
candidates=("\${(@f)$(launch completion ${COMPLETE_SUBCOMMAND} -- "\${words[2,-1]}" 2>/dev/null)}")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: The zsh callback forwards ${words[2,-1]} inside double quotes, which collapses multiple typed tokens into a single argument before invoking __complete. That breaks command-tree descent for nested commands because the resolver receives one space-joined token instead of separate words. Expand the array as separate arguments (zsh array-safe expansion) so each token is passed individually. [api mismatch]

Severity Level: Critical 🚨
- ❌ Zsh completion fails for nested commands and subcommands.
- ⚠️ Dynamic values mis-resolved when multiple tokens typed.
Steps of Reproduction ✅
1. The main CLI registers the completion group via `registerCompletionCommand(program)` in
`src/cli/program.ts:12-17`, which is invoked for the default program instance.

2. `registerCompletionCommand` wires the hidden callback `completion __complete
[words...]` at `src/cli/commands/completion.ts:55-61`, whose action calls
`resolveCompletions(words, program)` and writes the candidates.

3. On zsh, a user enables completion by running `launch completion zsh` (implemented by
`zshCompletionScript()` in `src/core/completion.ts:94-103`) and sourcing the emitted
script, which defines `_launch_complete` and the line `candidates=("${(@f)$(launch
completion ${COMPLETE_SUBCOMMAND} -- "${words[2,-1]}" 2>/dev/null)}")` at
`src/core/completion.ts:98`.

4. In zsh, when the user types `launch snapshot d` and presses `<Tab>`, the completion
system sets `words=("launch" "snapshot" "d")`; `${words[2,-1]}` expands to `snapshot d`,
and the quoting `"${words[2,-1]}"` passes that as a SINGLE argument to `launch completion
__complete --`, so the `words` array received by the Node handler in
`src/cli/commands/completion.ts:58-59` is `["snapshot d"]`. `resolveCompletions(["snapshot
d"], program)` (see `src/core/completion.ts:225-241`) calls `descend()` at
`src/core/completion.ts:199-208`, which cannot match a subcommand literally named
`"snapshot d"`, so it treats this as the root command and returns only top-level
commands/flags instead of suggesting the `diff` subcommand of `snapshot`. This
demonstrates that multiple CLI tokens after `launch` are merged into one argument,
breaking nested-command completion for zsh.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/core/completion.ts
**Line:** 98:98
**Comment:**
	*Api Mismatch: The zsh callback forwards `${words[2,-1]}` inside double quotes, which collapses multiple typed tokens into a single argument before invoking `__complete`. That breaks command-tree descent for nested commands because the resolver receives one space-joined token instead of separate words. Expand the array as separate arguments (zsh array-safe expansion) so each token is passed individually.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

Comment thread src/core/completion.ts Outdated
Comment on lines +249 to +251
function hasPositional(words: string[], pathLength: number): boolean {
const afterCommand = words.slice(pathLength, -1); // drop the command path and the in-progress word
return afterCommand.some((word) => !word.startsWith("-"));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Suggestion: Positional detection currently treats any non-flag token after the command path as a positional argument, but that also includes values belonging to options (for example after --app). This causes dynamic positional completion to be incorrectly disabled once a flag value is present. Update positional detection to skip option-value pairs (or parse known value-taking flags) instead of only checking startsWith("-"). [incorrect condition logic]

Severity Level: Major ⚠️
- ❌ Plan and snapshot positional completions disabled when flags used.
- ⚠️ Users must remember surfaces and snapshots without shell hints.
Steps of Reproduction ✅
1. The hidden completion callback `completion __complete [words...]` is wired in
`src/cli/commands/completion.ts:55-61` and calls `resolveCompletions(words, program)` at
line 59; this command is registered on the main CLI via
`registerCompletionCommand(program)` in `src/cli/program.ts:12-17,151`.

2. `resolveCompletions` in `src/core/completion.ts:225-241` uses `ARGUMENT_SOURCES` at
`src/core/completion.ts:182-187` to provide dynamic positional candidates for commands
like `"plan"` (backed by `planSurfaceIds` at lines 156-160) and `"snapshot
diff"`/`"snapshot export"` (backed by `snapshotNames` at lines 162-163).

3. When the user types a command like `launch plan --app atlas <Tab>`, the callback
receives `words=["plan", "--app", "atlas", ""]` (command path `["plan"]` with flags and
values afterward). `resolveCompletions` computes `path=["plan"]` via `descend()` at
`src/core/completion.ts:199-208` and then looks up `argumentSource =
ARGUMENT_SOURCES.get("plan")` at lines 237-238.

4. Before using the dynamic positional source, `resolveCompletions` calls
`hasPositional(words, path.length)` at `src/core/completion.ts:238-239`. `hasPositional`
(lines 249-251) slices `afterCommand = words.slice(1, -1)``["--app", "atlas"]` and then
returns `true` because `"atlas"` does not start with `"-"`. This incorrectly treats the
flag value `"atlas"` as a positional argument, causing `argumentSource &&
!hasPositional(...)` to short-circuit and skip positional completion; as a result, dynamic
`plan` surface suggestions (e.g. `"catalog"`, `"listing"`, verified by
`resolveCompletions` tests in `src/core/completion.test.ts:79-83`) no longer appear
whenever any value-taking flag (like `--app`) is present.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/core/completion.ts
**Line:** 249:251
**Comment:**
	*Incorrect Condition Logic: Positional detection currently treats any non-flag token after the command path as a positional argument, but that also includes values belonging to options (for example after `--app`). This causes dynamic positional completion to be incorrectly disabled once a flag value is present. Update positional detection to skip option-value pairs (or parse known value-taking flags) instead of only checking `startsWith("-")`.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
👍 | 👎

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/core/completion.ts (1)

359-359: 💤 Low value

Consider using dirname for clarity.

Using dirname(rcFile) is more idiomatic than join(rcFile, "..") for resolving the parent directory. Both are functionally equivalent.

+import { dirname, join } from "node:path";
 ...
-const rcDir = join(rcFile, "..");
+const rcDir = dirname(rcFile);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/completion.ts` at line 359, Replace the idiomatic but less clear
`join(rcFile, "..")` pattern with the built-in `dirname(rcFile)` function for
resolving the parent directory of rcFile. Update the rcDir variable assignment
to use dirname instead of join with the ".." parent directory reference, and
ensure dirname is imported from the path module if it is not already.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@src/core/completion.ts`:
- Line 359: Replace the idiomatic but less clear `join(rcFile, "..")` pattern
with the built-in `dirname(rcFile)` function for resolving the parent directory
of rcFile. Update the rcDir variable assignment to use dirname instead of join
with the ".." parent directory reference, and ensure dirname is imported from
the path module if it is not already.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 21fdc6fa-6269-4148-a9aa-66e5d0a8a739

📥 Commits

Reviewing files that changed from the base of the PR and between fe5143f and 76c2183.

📒 Files selected for processing (18)
  • README.de.md
  • README.es.md
  • README.fr.md
  • README.ja.md
  • README.ko.md
  • README.md
  • README.pt-BR.md
  • README.ru.md
  • README.zh-CN.md
  • docs/commands.md
  • llms.txt
  • scripts/gen-docs.ts
  • src/cli/commands/completion.test.ts
  • src/cli/commands/completion.ts
  • src/cli/program.ts
  • src/core/completion.test.ts
  • src/core/completion.ts
  • src/core/types.ts

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

3 issues found across 18 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread src/core/completion.ts Outdated
Comment thread src/core/completion.ts Outdated
Comment thread src/core/completion.ts Outdated
YosefHayim and others added 2 commits June 20, 2026 20:53
Resolve generated-doc collisions with #229 (app-extension signing) and #231
(deferred audit probes) by regenerating docs/commands.md, llms.txt, and the
README badge rows from the merged source. No source conflicts (types.ts
auto-merged). Full gate green: 1668 tests, docs in sync.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…itional detection

Review fixes (cubic P1/P1/P2, codeant) to the completion logic:
- bash: slice COMP_WORDS to COMP_CWORD so mid-line completion resolves the word
  under the cursor, not the trailing word.
- zsh: pass words[2,CURRENT] with the (@) flag so each token is a separate arg;
  the old quoted "${words[2,-1]}" joined them into one string and broke
  command-tree descent for nested commands (e.g. `snapshot diff`).
- resolveCompletions: a value following a value-taking flag (e.g. `--app web`)
  is no longer miscounted as a positional, so dynamic positional completion is
  not wrongly skipped after flags. Adds valueTakingFlags() (walks ancestors).

Tests lock in the cursor slice, the (@) token splitting, and the
positional-after-flag-value case. InstallResult/InstallOptions stay local to
the module (feature-local operation shapes, like the ASC *Resource types) —
only the shared Shell enum lives in types.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@YosefHayim

Copy link
Copy Markdown
Owner Author

Addressed the review in c8042ef:

Real bugs fixed (cubic P1/P1/P2, codeant):

  • bash — slice COMP_WORDS[@]:1:COMP_CWORD so mid-line completion resolves the word under the cursor.
  • zsh"${(@)words[2,CURRENT]}" passes each token as a separate arg (the old "${words[2,-1]}" joined them, breaking nested-command descent like snapshot diff).
  • positional detection — a value after a value-taking flag (--app web) is no longer miscounted as a positional; added valueTakingFlags() (walks ancestors). Regression test added for plan --app atlas <Tab>.

Type location (codeant, Minor): keeping InstallResult/InstallOptions local to core/completion.ts — they're feature-local operation shapes, matching the repo's existing pattern where ASC *Resource/*Query types live in ascClient.ts rather than types.ts. The genuinely shared Shell enum does live in types.ts.

@YosefHayim YosefHayim merged commit ed77bac into main Jun 21, 2026
8 checks passed
YosefHayim added a commit that referenced this pull request Jun 21, 2026
Rollup release covering the feature surface landed since v0.27.0:
snapshot restore + App ID capabilities capture & housekeeping (#191),
plan/drift offers & screenshots surface planners (#140), shell completions
(#232), testflight feedback (#234), and the maximalist agent skills +
collapsible README features (#237).

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@YosefHayim YosefHayim deleted the feat/222-completion branch June 22, 2026 12:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(cli): launch completion — shell completions (bash/zsh/fish) with dynamic app/profile/surface completion

1 participant