Skip to content

feat(extensions): add session-scoped keyboard modes - #708

Merged
benvinegar merged 4 commits into
mainfrom
feat/session-scoped-extension-keyboard-modes
Aug 11, 2026
Merged

feat(extensions): add session-scoped keyboard modes#708
benvinegar merged 4 commits into
mainfrom
feat/session-scoped-extension-keyboard-modes

Conversation

@benvinegar

@benvinegar benvinegar commented Aug 11, 2026

Copy link
Copy Markdown
Member

Summary

  • add extension API v4 session-scoped keyboard modes with guarded activation, routing, and teardown
  • expose frozen key snapshots and synchronous handled / pass / exit decisions without renderer or viewport internals
  • add host-owned Escape, status, and Extensions-menu recovery paths
  • add a public Vim navigation example with atomic counts, Ctrl chords, and a focused : command line
  • document the API and cover registry, lifecycle, precedence, package-consumer, PTY, and TTY behavior

Testing

  • bun run format:check
  • bun run typecheck
  • bun run lint
  • bun run check:docs
  • bun run check:pack
  • bun run test — 2,047 passed, 9 skipped
  • bun run test:integration — 102 passed
  • bun run test:tty-smoke — 9 passed
  • bun run changeset:status
  • website checks, build, and link validation
  • git diff --check

This PR description was generated by Pi using gpt-5.6-sol

@vercel

vercel Bot commented Aug 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
hunk-web Ignored Ignored Preview Aug 11, 2026 2:24pm

Request Review

@benvinegar
benvinegar marked this pull request as ready for review August 11, 2026 13:55
@greptile-apps

greptile-apps Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds extension API v4 session-scoped keyboard modes, including registration, guarded lifecycle management, key routing, host-owned recovery paths, documentation, and a Vim navigation example.

  • Adds activation-scoped keyboard-mode controls and synchronous callback containment.
  • Integrates session modes into App keyboard precedence, status, menus, reload, and teardown.
  • Publishes and tests the API through package-consumer, component, PTY, TTY, and example coverage.
  • The open-menu routing path currently allows an active mode to intercept advertised menu accelerators before command dispatch.

Confidence Score: 4/5

The menu-accelerator routing defect should be fixed before merging because an active extension mode can suppress advertised host menu commands.

Session modes are inserted between menu fallthrough and app-command dispatch, so a mode that handles an advertised accelerator prevents the host command from executing; the remaining accepted feedback is formatting-related.

Files Needing Attention: src/ui/hooks/useAppKeyboardShortcuts.ts, examples/extensions/vim-navigation/index.ts, examples/extensions/vim-navigation/state.ts

Important Files Changed

Filename Overview
src/ui/hooks/useAppKeyboardShortcuts.ts Adds session-mode routing after file-view modes but before app commands; this lets modes intercept open-menu accelerator keys intended for command dispatch.
src/ui/keyboardModes/useKeyboardModeController.ts Implements guarded activation, replacement, stale-registry retirement, synchronous lifecycle containment, and exactly-once teardown.
src/ui/keyboardModes/mode.ts Defines session-mode validity and synchronous key/lifecycle delivery around shared callback containment.
src/extensions/runExtension.ts Adds validated keyboard-mode registration and includes registrations in factory-failure rollback.
src/extensions/apply.ts Resolves keyboard-mode identities with first-registration precedence and duplicate diagnostics.
src/extension-api/types.ts Publishes extension API v4 keyboard-mode registration, contexts, key decisions, and activation-scoped controls.
examples/extensions/vim-navigation/index.ts Demonstrates mode activation and semantic command routing, but violates the mounted TypeScript formatting rule.
examples/extensions/vim-navigation/state.ts Implements atomic Vim counts, prefixes, alignment, and control chords, while sharing the formatting-rule violation.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  K[Terminal key] --> M{Host modal or menu navigation claims key?}
  M -->|yes| C[Consume or route to focused surface]
  M -->|menu accelerator: no| F{Focused input claims key?}
  F -->|yes| I[Deliver to input]
  F -->|no| V{File-view mode active?}
  V -->|handled or exit| C
  V -->|pass or inactive| S{Session mode active?}
  S -->|handled or exit| C
  S -->|pass or inactive| A[Dispatch app command]
  A --> X[Execute accelerator and close menu]
Loading
Prompt To Fix All With AI
### Issue 1
src/ui/hooks/useAppKeyboardShortcuts.ts:555
**Menu accelerators reach session modes**

When a session keyboard mode is active and a dropdown is open, accelerator keys that `handleMenuShortcut` deliberately passes onward reach the session mode before `dispatchAppCommand`. A mode that handles `q`, `r`, `/`, or another advertised accelerator suppresses the host command and leaves the menu open.

### Issue 2
examples/extensions/vim-navigation/index.ts:1-2
**New files violate TypeScript style**

The new Vim example and keyboard-mode implementation use two-space indentation and double-quoted strings throughout, conflicting with the repository requirement for four-space indentation and single quotes and establishing an inconsistent pattern for future extension examples.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Reviews (1): Last reviewed commit: "feat(examples): add Vim command-line nav..." | Re-trigger Greptile

Comment thread src/ui/hooks/useAppKeyboardShortcuts.ts Outdated
handleMenuShortcut,
handleFocusedInputShortcut,
handleFileViewModeShortcut,
handleKeyboardModeShortcut,

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 Menu accelerators reach session modes

When a session keyboard mode is active and a dropdown is open, accelerator keys that handleMenuShortcut deliberately passes onward reach the session mode before dispatchAppCommand. A mode that handles q, r, /, or another advertised accelerator suppresses the host command and leaves the menu open.

Knowledge Base Used:

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/ui/hooks/useAppKeyboardShortcuts.ts
Line: 555

Comment:
**Menu accelerators reach session modes**

When a session keyboard mode is active and a dropdown is open, accelerator keys that `handleMenuShortcut` deliberately passes onward reach the session mode before `dispatchAppCommand`. A mode that handles `q`, `r`, `/`, or another advertised accelerator suppresses the host command and leaves the menu open.

**Knowledge Base Used:**
- [UI App Shell: AppHost, App, and Controller Hooks](https://app.greptile.com/modem/-/custom-context/knowledge-base/modem-dev/hunk/-/docs/ui-app-host.md)
- [Extension System: API, Loading, and Host Integration](https://app.greptile.com/modem/-/custom-context/knowledge-base/modem-dev/hunk/-/docs/extension-system.md)

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fixed in ec38dedb. When an open menu declines a key, an enabled command accelerator now dispatches before focused inputs, file-view modes, and session keyboard modes can claim it. Added an AppHost regression with both extension mode layers handling ?, verifying that Help still opens and the menu closes.

Responded by Pi using openai-codex/gpt-5.6-sol.

This comment was generated by Pi using gpt-5.6-sol

Comment on lines +1 to +2
import type { HunkExtensionAPI } from "hunkdiff/extension";
import { createVimNavigationState, executeVimCommand } from "./state";

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 New files violate TypeScript style

The new Vim example and keyboard-mode implementation use two-space indentation and double-quoted strings throughout, conflicting with the repository requirement for four-space indentation and single quotes and establishing an inconsistent pattern for future extension examples.

Context Used: guidelines.mdc Cursor rule (source)

Prompt To Fix With AI
This is a comment left during a code review.
Path: examples/extensions/vim-navigation/index.ts
Line: 1-2

Comment:
**New files violate TypeScript style**

The new Vim example and keyboard-mode implementation use two-space indentation and double-quoted strings throughout, conflicting with the repository requirement for four-space indentation and single quotes and establishing an inconsistent pattern for future extension examples.

**Context Used:** guidelines.mdc Cursor rule ([source](https://github.com/modem-dev/modem/blob/main/.cursor/rules/guidelines.mdc))

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

No change here. Hunk's repository-local AGENTS.md makes oxfmt authoritative, and this code matches the existing two-space/double-quote format enforced by bun run format:check. The cited style rule belongs to the separate modem repository rather than modem-dev/hunk.

Responded by Pi using openai-codex/gpt-5.6-sol.

This comment was generated by Pi using gpt-5.6-sol

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.

You're right — I misattributed a style rule from the modem repository to modem-dev/hunk. Since oxfmt is the authoritative formatter here and bun run format:check passes, the two-space / double-quote style is correct and my comment was wrong.

Shall I remember this as a rule: "In modem-dev/hunk, treat oxfmt (enforced via bun run format:check) as the authoritative formatter — do not flag two-space indentation or double-quoted strings as style violations"?

@benvinegar
benvinegar merged commit 61cc6b1 into main Aug 11, 2026
12 checks passed
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