Skip to content

feat(app): directory autocomplete for the new-session path pickers - #1077

Open
chphch wants to merge 2 commits into
slopus:mainfrom
chphch:feat/44-filepath-autocomplete
Open

chphch wants to merge 2 commits into
slopus:mainfrom
chphch:feat/44-filepath-autocomplete

Conversation

@chphch

@chphch chphch commented Apr 15, 2026 •

Copy link
Copy Markdown
Contributor

Asked for twice, and the live request is still open.

"I have to switch back to my laptop terminal to find the path. I would be completely blocked here if I was away from my computer."
— GrocerPublishAgent, #44, 2025-08-24 (with a screenshot and a recorded walkthrough)

"the path input field requires typing the full directory path manually … As the user types in the path field, show filtered suggestions matching the input."
— cruzanstx, #970, 2026-04-03

A note on #44, since it reads as resolved: it was closed on 2026-01-22 by merge commit 6e7c2a7, whose message is Merge pull request #45 from CodingCanuck/vuln-restrict-file-access — Fix #44: Restrict file access in RPC handlers. That commit hardens RPC file access (pathSecurity.ts plus handlers, 5 files under cli/src) and has nothing to do with path autocomplete. Its Fix #44 refers to an issue in that contributor's fork (the merge came from their PR #45), so it closed our #44 by number collision. The request itself was never addressed; #970 is the live one.


Closes #970. (It was first requested in #44; see the note above.)

Live subdirectory autocomplete in the new-session Project path picker. As the user types a path, the picker lists matching subdirectories from the selected machine and shows them above the existing Recent list; tapping a suggestion appends / so you can keep drilling down.

How it works

User types: ~/proj
        ↓
split → parentDir = ~/        prefix = proj
        ↓
resolve → /home/user/         (via resolveAbsolutePath + machine.metadata.homeDir)
        ↓
machineBash: ls -1ap "/home/user/" | grep '/$' | grep -v '^\.\.\?/$'
        ↓
filter by prefix → ["projects/", "project-alpha/"]
        ↓
suggestion tapped → value becomes ~/projects/   ← user's own form preserved

Debounced 250 ms, with a per-(machineId, resolvedParentDir) cache (10 s TTL). No network or disk hit when no machine is selected or the field is empty.

Two details the feature depends on:

  • ~ is resolved before the shell sees it. Bash does not expand ~ inside double quotes, so passing the user's typed parent straight into ls -1ap "${dir}" silently returns nothing for every ~/… path, and ~/… is what this field shows by default because it renders home-relative. The parent is resolved through resolveAbsolutePath(parentDir, homeDir) (homeDir comes from machine.metadata) before it reaches machineBash, while the user-typed parent is preserved in the returned fullPath so drill-down stays home-relative. The cache is keyed on the resolved parent so ~/ and /home/user/ can't compete for one slot.

  • The unrestricted machine-level RPC this depends on is already upstream. apiMachine.ts used to validate incoming bash calls against process.cwd(), the directory the daemon happened to be started from (typically a project subdir). validatePath then rejected any cwd outside that subtree, and autocomplete died the moment you typed ~/ or /Users/…. Upstream removed that boundary outright in d1cdc796 (registerCommonHandlers(this.rpcHandlerManager, null)) for an unrelated symptom (worktree creation reporting Not a Git repository). This PR changes no behaviour there. It only adds a two-line comment recording that new-session autocomplete depends on the RPC staying unrestricted, so that a future re-sandboxing does not silently break it.

The pure split/resolve logic lives in useDirSuggestions.utils.ts so it is unit-testable; the hook itself transitively imports react-native through @/sync/ops, which the test environment can't parse.

Proof

Real happy-cli daemon, no mocks: standalone happy-server (PGlite) + Expo web + a paired daemon started from a deep subdirectory of $HOME — the cwd that broke autocomplete before upstream lifted the machine-level path boundary.

directory autocomplete

Frames: empty ~ → ~/ha (narrowed to happy* worktrees) → ~/happy- (full worktree list). Every suggestion comes from a real ls -1ap over the WebSocket RPC. The daemon log confirms ls -1ap "/home/hyunwoojung/" ran with cwd: '/home/hyunwoojung' and returned success: true, stdoutLen: 1565 — i.e. path validation now allows targets outside the daemon's launch directory.

Scope

App + CLI. No new dependencies, no server or schema change.

  • useDirSuggestions.ts / .utils.ts — the hook and its pure helpers
  • new/index.tsx — machineId threaded to all three PathPickerContent call sites (including the native mobile picker; machineId is optional, so omitting it type-checks and would have quietly disabled autocomplete on native)
  • apiMachine.ts — a two-line comment only; the boundary itself is upstream's (d1cdc796), and no behaviour changes here

Not covered: on phones a new-session tap now opens the home dock first, and its Enter custom path… prompt (HomeDock.tsx) stays a plain text field. Autocomplete there would be a follow-up.

Verification

On this head, rebased onto main at 24d340d, typecheck is clean for app, cli and server, and the CLI suite passes (997 tests). The app suite passes with its 11 new cases apart from two files that fail on main itself: sessionPresentation.test.ts (does not load, __DEV__ is not defined; #1864 fixes it) and messageMeta.test.ts (still expects the old Codex default; #1891 fixes it). The CLI Smoke Test's smoke-test-linux (20) job fails on every PR that touches the CLI since 2026-10-15, because npm 10 (the npm Node 20 ships) crashes on a vitest peer-version mix that has nothing to do with this change; #1905 fixes it.

  • useDirSuggestions.spec.ts has 11 cases: tilde paths (~/proj, ~/projects/hap, ~/, bare ~), absolute paths, relative/no-slash input, missing homeDir (machine offline), and a Windows-style homeDir separator.

@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch 3 times, most recently from 0781ed8 to 0f1bee5 Compare April 29, 2026 06:53
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from 0f1bee5 to e194376 Compare May 3, 2026 18:00
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from e194376 to 764c9c7 Compare May 8, 2026 18:00
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch 2 times, most recently from 4f35abb to dbbcefe Compare May 22, 2026 18:00
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from 50b1007 to 014f108 Compare June 5, 2026 18:00
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from 014f108 to ef6e5e0 Compare July 5, 2026 13:07
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from ef6e5e0 to 546a9d9 Compare July 18, 2026 13:20
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch 2 times, most recently from e000ed4 to 04f1bd1 Compare July 26, 2026 22:35
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from 04f1bd1 to 2f1431c Compare August 7, 2026 21:17
@chphch chphch changed the title feat(app): directory autocomplete for new session path picker feat(app): directory autocomplete for the new-session path pickers Aug 7, 2026
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch 5 times, most recently from b490a58 to f146b93 Compare August 28, 2026 00:22
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from f146b93 to 3b38a4f Compare September 14, 2026 06:12
chphch and others added 2 commits October 19, 2026 10:26
When a user types a project path in the new session screen, the path
picker now shows filesystem directory suggestions fetched from the
selected machine via `machineBash`. Suggestions are debounced (250ms),
cached per (machineId, parentDir) pair for 10s, and filtered by the
current typed prefix. Tapping a suggestion appends `/` so the user can
keep drilling down.

New hook: `useDirSuggestions(machineId, pathText)`
Closes: slopus#44

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
The machine-level RPC no longer validates paths at all on main
(`d1cdc796`), so these cases pinned a boundary that does not exist, and
the PR changes no behaviour there. `pathSecurity.test.ts` is back to
main's version.

Generated with [Claude Code](https://claude.ai/code)
via [Happy](https://happy.engineering)

Co-Authored-By: Claude <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
@chphch
chphch force-pushed the feat/44-filepath-autocomplete branch from a8a0d57 to b0ead3a Compare October 19, 2026 01:27

This branch has not been deployed

No deployments
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.

[Feature Request] Search/filter folder names when typing path in new chat

1 participant