Missing readline ctrl+f (forward-char) / ctrl+b (backward-char) #2638

Closed
opened 2026-02-16 17:36:34 -05:00 by yindo · 5 comments
Owner

Originally created by @jdanbrown on GitHub (Nov 6, 2025).

Originally assigned to: @kommander on GitHub.

Description

ctrl+f (forward-char) and ctrl+b (backward-char) are common keybindings from readline that cli tools typically support for line editing. Currently they do nothing in opencode, would be nice to add them.

OpenCode version

1.0.36

Steps to reproduce

No response

Screenshot and/or share link

No response

Operating System

macOS 15.5

Terminal

VS Code terminal

Originally created by @jdanbrown on GitHub (Nov 6, 2025). Originally assigned to: @kommander on GitHub. ### Description `ctrl+f` (forward-char) and `ctrl+b` (backward-char) are common keybindings from readline that cli tools typically support for line editing. Currently they do nothing in opencode, would be nice to add them. - https://www.man7.org/linux/man-pages/man3/readline.3.html#DEFAULT_KEY_BINDINGS ### OpenCode version 1.0.36 ### Steps to reproduce _No response_ ### Screenshot and/or share link _No response_ ### Operating System macOS 15.5 ### Terminal VS Code terminal
yindo added the opentuibug labels 2026-02-16 17:36:34 -05:00
yindo closed this issue 2026-02-16 17:36:35 -05:00
Author
Owner

@github-actions[bot] commented on GitHub (Nov 6, 2025):

This issue might be a duplicate of existing issues. Please check:

  • #3647: Both issues are about missing or broken readline keybindings in OpenCode v1.0+ (opentui system). Issue #3647 reports that most readline keybindings work except for ctrl-u and ctrl-d, while this issue reports missing ctrl+f and ctrl+b. These could potentially be addressed together as part of a comprehensive readline keybinding implementation.

Feel free to ignore if none of these address your specific case.

@github-actions[bot] commented on GitHub (Nov 6, 2025): This issue might be a duplicate of existing issues. Please check: - #3647: Both issues are about missing or broken readline keybindings in OpenCode v1.0+ (opentui system). Issue #3647 reports that most readline keybindings work except for ctrl-u and ctrl-d, while this issue reports missing ctrl+f and ctrl+b. These could potentially be addressed together as part of a comprehensive readline keybinding implementation. Feel free to ignore if none of these address your specific case.
Author
Owner

@jdanbrown commented on GitHub (Nov 6, 2025):

Adding ctrl+f and ctrl+b (and ctrl+u) looks pretty straightforward, but would it be better if they went into opentui rather than opencode? I was sketching this out quickly with an llm to see how much work it would be, but along the way I couldn't find other basic line-editing keys like ctrl+k, ctrl+a, and ctrl+e defined in opencode, so that made me wonder if maybe these things should live in opentui instead.

$ git diff
diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
index c977f731..0a80657e 100644
--- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
+++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx
@@ -566,6 +566,33 @@ export function Prompt(props: PromptProps) {
                   e.preventDefault()
                   return
                 }
+                if (keybind.match("input_forward_char", e)) {
+                  const cursorOffset = input.cursorOffset
+                  if (cursorOffset < input.plainText.length) {
+                    input.cursorOffset = cursorOffset + 1
+                  }
+                  e.preventDefault()
+                  return
+                }
+                if (keybind.match("input_backward_char", e)) {
+                  const cursorOffset = input.cursorOffset
+                  if (cursorOffset > 0) {
+                    input.cursorOffset = cursorOffset - 1
+                  }
+                  e.preventDefault()
+                  return
+                }
+                if (keybind.match("input_kill_line_backward", e)) {
+                  const cursorOffset = input.cursorOffset
+                  if (cursorOffset > 0) {
+                    const text = input.plainText
+                    const newText = text.slice(cursorOffset)
+                    input.setText(newText)
+                    input.cursorOffset = 0
+                  }
+                  e.preventDefault()
+                  return
+                }
                 if (keybind.match("app_exit", e)) {
                   await exit()
                   return
diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts
index c2ee63c6..3be2cfb4 100644
--- a/packages/opencode/src/config/config.ts
+++ b/packages/opencode/src/config/config.ts
@@ -465,6 +465,11 @@ export namespace Config {
       agent_cycle_reverse: z.string().optional().default("shift+tab").describe("Previous agent"),
       input_clear: z.string().optional().default("ctrl+c").describe("Clear input field"),
       input_forward_delete: z.string().optional().default("ctrl+d").describe("Forward delete"),
+      input_kill_line_backward: z
+        .string()
+        .optional()
+        .default("ctrl+u")
+        .describe("Delete from cursor to beginning of line"),
       input_paste: z.string().optional().default("ctrl+v").describe("Paste from clipboard"),
       input_submit: z.string().optional().default("return").describe("Submit input"),
       input_newline: z
@@ -472,6 +477,16 @@ export namespace Config {
         .optional()
         .default("shift+return,ctrl+j")
         .describe("Insert newline in input"),
+      input_forward_char: z
+        .string()
+        .optional()
+        .default("ctrl+f,right")
+        .describe("Move cursor forward one character"),
+      input_backward_char: z
+        .string()
+        .optional()
+        .default("ctrl+b,left")
+        .describe("Move cursor backward one character"),
       history_previous: z.string().optional().default("up").describe("Previous history item"),
       history_next: z.string().optional().default("down").describe("Next history item"),
       session_child_cycle: z

$ git diff --stat
 packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx | 27 +++++++++++++++++++++++++++
 packages/opencode/src/config/config.ts                       | 15 +++++++++++++++
 2 files changed, 42 insertions(+)
@jdanbrown commented on GitHub (Nov 6, 2025): Adding `ctrl+f` and `ctrl+b` (and `ctrl+u`) looks pretty straightforward, but would it be better if they went into opentui rather than opencode? I was sketching this out quickly with an llm to see how much work it would be, but along the way I couldn't find other basic line-editing keys like `ctrl+k`, `ctrl+a`, and `ctrl+e` defined in opencode, so that made me wonder if maybe these things should live in opentui instead. - https://opencode.ai/s/6zF2Y8Cl ```diff $ git diff diff --git a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx index c977f731..0a80657e 100644 --- a/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx @@ -566,6 +566,33 @@ export function Prompt(props: PromptProps) { e.preventDefault() return } + if (keybind.match("input_forward_char", e)) { + const cursorOffset = input.cursorOffset + if (cursorOffset < input.plainText.length) { + input.cursorOffset = cursorOffset + 1 + } + e.preventDefault() + return + } + if (keybind.match("input_backward_char", e)) { + const cursorOffset = input.cursorOffset + if (cursorOffset > 0) { + input.cursorOffset = cursorOffset - 1 + } + e.preventDefault() + return + } + if (keybind.match("input_kill_line_backward", e)) { + const cursorOffset = input.cursorOffset + if (cursorOffset > 0) { + const text = input.plainText + const newText = text.slice(cursorOffset) + input.setText(newText) + input.cursorOffset = 0 + } + e.preventDefault() + return + } if (keybind.match("app_exit", e)) { await exit() return diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index c2ee63c6..3be2cfb4 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -465,6 +465,11 @@ export namespace Config { agent_cycle_reverse: z.string().optional().default("shift+tab").describe("Previous agent"), input_clear: z.string().optional().default("ctrl+c").describe("Clear input field"), input_forward_delete: z.string().optional().default("ctrl+d").describe("Forward delete"), + input_kill_line_backward: z + .string() + .optional() + .default("ctrl+u") + .describe("Delete from cursor to beginning of line"), input_paste: z.string().optional().default("ctrl+v").describe("Paste from clipboard"), input_submit: z.string().optional().default("return").describe("Submit input"), input_newline: z @@ -472,6 +477,16 @@ export namespace Config { .optional() .default("shift+return,ctrl+j") .describe("Insert newline in input"), + input_forward_char: z + .string() + .optional() + .default("ctrl+f,right") + .describe("Move cursor forward one character"), + input_backward_char: z + .string() + .optional() + .default("ctrl+b,left") + .describe("Move cursor backward one character"), history_previous: z.string().optional().default("up").describe("Previous history item"), history_next: z.string().optional().default("down").describe("Next history item"), session_child_cycle: z $ git diff --stat packages/opencode/src/cli/cmd/tui/component/prompt/index.tsx | 27 +++++++++++++++++++++++++++ packages/opencode/src/config/config.ts | 15 +++++++++++++++ 2 files changed, 42 insertions(+) ```
Author
Owner

@kommander commented on GitHub (Nov 12, 2025):

This should work in the latest version?

@kommander commented on GitHub (Nov 12, 2025): This should work in the latest version?
Author
Owner

@cwegener commented on GitHub (Nov 12, 2025):

Started working for me when I installed version 1.0.60 yesterday

@cwegener commented on GitHub (Nov 12, 2025): Started working for me when I installed version `1.0.60` yesterday
Author
Owner

@jdanbrown commented on GitHub (Nov 18, 2025):

Thanks! Confirmed working now as of 1.0.76 (or earlier).

@jdanbrown commented on GitHub (Nov 18, 2025): Thanks! Confirmed working now as of 1.0.76 (or earlier).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: anomalyco/opencode#2638