Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
**Date:** 2026-03-07
**Status:** Living Standard
**Authors:** Termprompt Contributors
**Canonical URL:** https://github.com/nichochar/termprompt/blob/main/SPEC.md
**Canonical URL:** https://github.com/seeden/termprompt/blob/main/SPEC.md
**License:** MIT

---
Expand Down Expand Up @@ -956,7 +956,7 @@ New message types or optional fields do not require a version increment.
https://sw.kovidgoyal.net/kitty/protocol-extensions/

- **[termprompt]** Reference implementation of OSC 7770.
https://github.com/nichochar/termprompt
https://github.com/seeden/termprompt

---

Expand All @@ -965,7 +965,7 @@ New message types or optional fields do not require a version increment.
### Plain Text

> OSC 7770: Structured Terminal Prompts, Version 1.0.0, 2026.
> https://github.com/nichochar/termprompt/blob/main/SPEC.md
> https://github.com/seeden/termprompt/blob/main/SPEC.md

### BibTeX

Expand All @@ -977,7 +977,7 @@ New message types or optional fields do not require a version increment.
month = mar,
type = {Living Standard},
version = {1.0.0},
url = {https://github.com/nichochar/termprompt/blob/main/SPEC.md},
url = {https://github.com/seeden/termprompt/blob/main/SPEC.md},
note = {Specification for structured interactive prompt
announcements over terminal escape sequences}
}
Expand All @@ -987,13 +987,13 @@ New message types or optional fields do not require a version increment.

Termprompt Contributors. (2026). *OSC 7770: Structured terminal prompts*
(Version 1.0.0) [Living Standard].
https://github.com/nichochar/termprompt/blob/main/SPEC.md
https://github.com/seeden/termprompt/blob/main/SPEC.md

### Chicago

Termprompt Contributors. "OSC 7770: Structured Terminal Prompts."
Version 1.0.0. Living Standard, March 2026.
https://github.com/nichochar/termprompt/blob/main/SPEC.md.
https://github.com/seeden/termprompt/blob/main/SPEC.md.

---

Expand Down
6 changes: 3 additions & 3 deletions apps/docs/content/docs/advanced/osc-protocol.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ If nothing intercepts the sequences, the user gets the normal TUI. Zero degradat
</Callout>

<Callout title="Full specification">
The formal specification lives at [SPEC.md](https://github.com/nichochar/termprompt/blob/main/SPEC.md) in the repository root. It includes ABNF grammar, RFC 2119 requirement levels, security considerations, and extensibility rules. This page is a practical summary for implementors.
The formal specification lives at [SPEC.md](https://github.com/seeden/termprompt/blob/main/SPEC.md) in the repository root. It includes ABNF grammar, RFC 2119 requirement levels, security considerations, and extensibility rules. This page is a practical summary for implementors.
</Callout>

## Encoding
Expand Down Expand Up @@ -262,5 +262,5 @@ All payloads include `"v": 1`. Future versions may increment this number. Termin

## Further Reading

- [PROTOCOL.md](https://github.com/nichochar/termprompt/blob/main/PROTOCOL.md) - Implementor-friendly protocol reference
- [SPEC.md](https://github.com/nichochar/termprompt/blob/main/SPEC.md) - Formal specification with ABNF grammar, RFC 2119 requirement levels, security considerations, and extensibility rules
- [PROTOCOL.md](https://github.com/seeden/termprompt/blob/main/PROTOCOL.md) - Implementor-friendly protocol reference
- [SPEC.md](https://github.com/seeden/termprompt/blob/main/SPEC.md) - Formal specification with ABNF grammar, RFC 2119 requirement levels, security considerations, and extensibility rules
23 changes: 23 additions & 0 deletions packages/termprompt/src/__tests__/input.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,29 @@ describe("input", () => {
expect(await promise).toBe("hello ");
});

it("does not insert literal key-name tokens like 'up' or 'down'", async () => {
const streams = createTestStreams();
const promise = testInput({ message: "Name?" }, streams);

// Simulates hosts that send literal key names instead of escape sequences.
streams.input.write(Buffer.from("up"));
streams.input.write(Buffer.from("down"));
streams.pressKey("return");

expect(await promise).toBe("");
});

it("does not insert unknown escape sequences as text", async () => {
const streams = createTestStreams();
const promise = testInput({ message: "Name?" }, streams);

// Unhandled CSI variant (for example Alt+Up in some terminals)
streams.input.write(Buffer.from("\x1b[1;3A"));
streams.pressKey("return");

expect(await promise).toBe("");
});

it("handles space", async () => {
const streams = createTestStreams();
const promise = testInput({ message: "Name?" }, streams);
Expand Down
23 changes: 22 additions & 1 deletion packages/termprompt/src/prompts/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,20 @@ type InputState = {
error: string | null;
};

const NON_TEXT_KEY_NAMES = new Set([
"up",
"down",
"left",
"right",
"return",
"tab",
"backspace",
"delete",
"home",
"end",
"escape",
]);

export async function input(config: InputConfig): Promise<string | Cancel> {
const { message, placeholder, initialValue = "", validate } = config;

Expand Down Expand Up @@ -158,7 +172,14 @@ export async function input(config: InputConfig): Promise<string | Cancel> {
}

// Multi-byte characters (emoji, etc.)
if (key.raw.length > 1 && !key.ctrl && !key.meta && key.name.length > 1) {
if (
key.raw.length > 1 &&
!key.raw.startsWith("\x1b") &&
!key.ctrl &&
!key.meta &&
key.name.length > 1 &&
!NON_TEXT_KEY_NAMES.has(key.name)
) {
s.text =
s.text.slice(0, s.cursorPos) + key.name + s.text.slice(s.cursorPos);
s.cursorPos += key.name.length;
Expand Down