Research: should DropTerm’s path provider complete bare argument words (cd src, no ./)?

Date: 2026-11-06

TL;DR

Every completion-capable system surveyed completes bare argument words as paths — fish, zsh, bash, Warp, VS Code, and the ghost feeders ble.sh and Clink — and every one of them does it as a fallback: files answer a bare word only when the command’s own completions do not claim the seat, never in competition with them; DropTerm should adopt exactly that carve (design D), extending it to both provider twins (ghost and menu), with directories-only for cd/pushd, riding the existing shell gate and autosuggestions_paths_enabled — not menu-only rows (A), not a curated path-command allowlist (B), and not unconditioned fish-parity ghosting (C). The pivotal precedent lands harder than the 2026-10-21 crosscheck spelled out: fish’s autosuggestion ghost draws on the completion engine, and the engine’s default file policy is perform file completion unless the command’s completions say skip — so cd sr ghosts c/ in fish today (pinned at FileCompletionPolicy::Inherit, the default, and the ghost’s empty-token carve, src/complete.rs @ d92ccd4f8f6f). What fish never does is let files contend with a specced seat: git co offers no cwd files because git’s completion script declares --no-files throughout (share/completions/git.fish:120,1055) — seat ownership is declared data, not rank order. That last fact is why C is wrong for DropTerm as stated: the merge ranks Path above Specs (source_rank, src/terminal/suggest.rs:493), so unconditioned bare-word ghosting would ghost nfigure/ over mmit for git co in any repo with a configure file. The fallback carve — path answers a bare word only when the specs table does not own the command and the generator seat is not claimed — is fish’s semantic, Warp’s CompletionsFallbackStrategy::FilePaths default, and VS Code’s no-items condition, all pinned below. CDPATH stays out (shell state DropTerm cannot read — the alias-resolution verdict’s class).

What DropTerm has today

Grounded in the working tree at HEAD c48c5267a35d (2026-11-06):

Findings

All source pins fetched 2026-11-06.

1. fish — the ghost draws on the completion engine, and the engine’s default is files

fish @ master d92ccd4f8f6f08cfc8a0d9fa17333153e2922af1 (2026-11-03):

2. zsh — the fallback chain ends at _files; cd is directories-only

zsh @ master 30e8be913521523d226789e53a4a2202dabff61c (2026-11-01):

3. bash — filename completion is the documented default fallback

Bash Reference Manual, Edition 5.3 (18 May 2025; Chet Ramey’s official mirror at tiswww.case.edu, read 2026-11-06):

4. Warp — a named, default-on FilePaths fallback, condition-gated

Warp is open source (AGPL-3.0; survey-only, no code copying) @ master f7fc2f2a08a3aa446baa23960710e630c5defd6e (2026-11-06):

5. Fig / Amazon Q — path arguments are declared per-argument; the fallback is the engine’s, not the format’s

6. VS Code terminal suggest — files-and-folders fallback for bare words, menu-surface, setting-gated

microsoft/vscode @ main 03d396a6e01bf958211fde9f2b279619881d68b2 (2026-11-06):

7. carapace — no stated file fallback; unknown commands delegate to the shell’s default

carapace-bin @ master 63b7842024e8c5651e8a61fcbb799778235ca4e4 (2026-11-06): an unknown command fails completers.Lookup (“unknown completer/variant”, cmd/carapace/cmd/completers/completers.go:304-314), and invokeCompleter then returns an empty snippet — carapace contributes nothing (cmd/carapace/cmd/invoke.go). Neither the README nor the docs site states a file-fallback policy (both checked, read 2026-11-06); the effective behavior for unknown commands is the host shell’s own default — filename completion in every supported shell (findings 1-3). Weaker pin, honestly so: carapace neither confirms nor contradicts the fallback consensus; it sidesteps it.

8. Terminal emulators — still nobody else completes; re-verified

The verdict table

Design Verdict Basis
A. Menu-only bare-word rows Rejected as the answer; its safety insight is kept No surveyed system restricts bare-word file completion to a list surface; VS Code’s fallback is list-surface but it has no ghost at all — DropTerm does, and fish (the cited parity) ghosts bare words. A also splits the path twins’ shared gates against the provider-seam pattern, and still needs the same seat stand-down for correct row order.
B. Curated path-argument commands Rejected as the gate; its data notion survives as the growth path Fig’s per-argument template: filepaths/folders and VS Code’s cd.ts are declarations of known path arguments, but every one of those engines still falls back to files for everything un-declared; an allowlist cannot answer mycmd src and duplicates filesystem truth in data. The directories-only carve and any future per-argument types belong in the completions.toml tier, not as the v1 gate.
C. fish-parity ghost, unconditioned Rejected — wrong for DropTerm’s merge specifically fish settles seats by per-command --no-files data inside one engine pass (git never file-completes); DropTerm merges independent providers by rank with Path above Specs (source_rank) — unconditioned, git co over a cwd configure ghosts the file. Made safe, C becomes D.
D. Fallback-only bare-word paths (recommended) Adopt The unanimous shape: fish’s Inherit policy (files unless the command’s completions claim/skip the seat), Warp’s !arg_has_spec FilePaths default, VS Code’s no-items condition, zsh’s _default → _files, bash’s documented filename fallback. Ghost + menu twins together, existing rules intact.

Recommendation

Adopt D, in one module:

  1. The carve: the path provider accepts a bare argument word — the trailing token when it is non-empty, not in command position, not --prefixed, and not path-shaped — with cwd as parent and the whole token as the component. This must be a new carve, not a loosening of is_path_shaped: the catalog and command-position logic key on that predicate (src/terminal/suggest.rs:601,1465), and path-shaped tokens keep their explicit-parent behavior unchanged.
  2. Both twins take it (path_candidate and path_candidates): the ghost reuses its existing trust envelope whole — unique completes (directories suffixed /), ambiguous completes the shared prefix, no extension silences, dotfiles follow the shell convention, the suffix rides escape_for_shell. No new floors: the common-prefix rule already bounds one-character bare words exactly as it bounds ~/s today, and the menu dissolves floors by design. An empty trailing token never completes — fish’s own ghost carve (src/complete.rs:980-983), already true here by construction.
  3. The fallback gate — the seat stand-down: the bare-word carve is silent whenever the specs table has the command (its data owns the command’s seats, the flat-table analog of fish’s per-command -f) or generator_context claims the seat. Path-shaped tokens are unaffected. Consequence: git co keeps ghosting mmit and listing subcommands only; cat sr, vim ha, codeinte … — any un-specced command — gain both surfaces. History keeps outranking everything (rank 0), as in fish.
  4. Directories-only for cd and pushd: a built-in reviewed carve (the GeneratorSeat precedent), matching fish’s core special-case, zsh’s _cd, Fig’s folders template for cd, and VS Code’s cd.ts. CDPATH stays out: it is shell state DropTerm cannot read without the injection verdict’s machinery — the alias-resolution rejection’s exact class; cd completes cwd’s directories. fish’s descend-unique-hierarchy cd ghost (src/wildcard.rs:965-978) is a named, accepted delta — DropTerm’s ghost stops at directory boundaries everywhere by existing ruling.
  5. Engine change: resolve_token_parent gains the bare-word arm — no /, not ~ → parent is the cwd (the ""-relative join already exists), component is the whole token; the listing cache keys on the canonical cwd, so cd sr reads once per directory as today (src/terminal/engine.rs:769-844).
  6. No new config key: the carve rides autosuggestions_paths_enabled and the standing shell gate (paths_eligible) — both false-positions keep restoring today’s behavior exactly. docs/autosuggestions.md:25 is rewritten when this ships (the toggle’s documented promise stays true).
  7. Growth path (named, not v1): a per-argument tier in completions.toml — Fig’s template notion — so specced commands can declare path/folder arguments and re-enable or shape path answers at their seats; the seed-audit conversion rules would then decide what crosses from withfig specs. Until that tier exists, a specced command’s seats belong to its specs alone.

Rejected, and why

Relation to prior records

Sources

All fetched 2026-11-06.