# setText vs keypress in pi-computer-use: Action Types Explained

> Understand the difference between setText and keypress action types in pi-computer-use. Learn when to use direct assignment versus simulating keystrokes for your automation needs.

- Repository: [injaneity/pi-computer-use](https://github.com/injaneity/pi-computer-use)
- Tags: deep-dive
- Published: 2026-07-16

---

**`setText` directly assigns a string to an editable element without simulating keystrokes, while `keypress` synthesizes native keyboard events to replicate human typing character-by-character.**

The `injaneity/pi-computer-use` repository defines a minimal set of UI automation primitives for controlling computer interfaces programmatically. When automating text input, choosing between **`setText`** and **`keypress`** determines whether your automation performs atomic value assignment or realistic keystroke simulation. Understanding these architectural differences ensures your scripts interact correctly with form validation, autocomplete, and other event-driven UI components.

## The `setText` Action

`setText` performs **direct value assignment** to an editable element. When invoked, the backend writes the entire string to the target in a single operation without generating intermediate keyboard events, bypassing the browser or platform's input event queue.

In [`src/platform/types.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/platform/types.ts), the request shape is defined as:

```ts
{ action: "setText"; params: { text: string } }

```

The bridge implementation in [`src/bridge.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/bridge.ts) routes this to `cdpTypeForContext`, which immediately sets the element's value. Because this approach does not simulate hardware input, it executes faster than keystroke simulation but does not trigger listeners monitoring for `keydown`, `keyup`, or `keypress` events.

### Focus and Foreground Handling

According to `prepareAction` in [`src/actions.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/actions.ts) (lines 100-106), `setText` operates with `establishesFocus: false` and `needsForeground: false`. This means the action does not require the target element to have focus before execution and does not bring the application to the foreground, making it ideal for batch form population behind the scenes.

## The `keypress` Action

`keypress` simulates **realistic keyboard input** by synthesizing native key-down and key-up events for each character in the sequence. This action replicates human typing behavior exactly, triggering any UI listeners that react to individual keystrokes, including autocomplete suggestions, inline validation, and keyboard shortcuts.

The type definition in [`src/platform/types.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/platform/types.ts) specifies:

```ts
{ action: "keypress"; params: { keys: string[] } }

```

The backend delegates this to `cdpKeypressForContext` in [`src/bridge.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/bridge.ts), which iterates through the `keys` array and fires separate hardware events for each entry.

### Focus Requirements

Unlike `setText`, `keypress` depends on focus state. As implemented in [`src/actions.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/actions.ts) (lines 95-96), this action sets `usesCurrentFocus: true`, meaning keystrokes are sent to whichever element currently has focus unless you explicitly provide a `ref` parameter. The action does not establish focus automatically, so the target must be focused beforehand for input to register correctly.

## Key Differences

The fundamental distinction lies in how each action interacts with the platform event system:

| Aspect | `setText` | `keypress` |
|--------|-----------|------------|
| **Event Generation** | No intermediate events; value changes atomically | Generates key-down/up events for each character |
| **Performance** | Faster; single operation | Slower; scales with string length |
| **UI Reactivity** | Bypasses autocomplete, validation, and keystroke listeners | Triggers all keyboard event handlers |
| **Focus Handling** | Works without focus (`needsForeground: false`) | Requires focused element (`usesCurrentFocus: true`) |
| **Use Case** | Setting final values, bulk data entry | Realistic typing, keyboard shortcuts, incremental validation |

## Implementation Details

The public API surface is defined in [`src/contract.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/contract.ts), which exports the `UiAction` type exposing both `"setText"` and `"keypress"` as valid action strings. The JSON schema in [`extensions/computer-use.ts`](https://github.com/injaneity/pi-computer-use/blob/main/extensions/computer-use.ts) surfaces these actions to the extension UI, allowing the computer-use extension to serialize requests for the platform backend.

When the platform receives a `setText` request, [`src/bridge.ts`](https://github.com/injaneity/pi-computer-use/blob/main/src/bridge.ts) routes it through `cdpTypeForContext` with an immediate write flag. For `keypress`, the same file routes to `cdpKeypressForContext`, managing the event synthesis loop for the provided key array.

## Code Examples

### Setting Text Directly

Use `setText` when you need to populate a field instantly and do not require intermediate events:

```ts
await actUi({
  actions: [
    {
      action: "setText",
      ref: "emailField",
      text: "alice@example.com"
    }
  ]
});

```

### Simulating Keystrokes

Use `keypress` when you need to trigger per-character event handlers or simulate human typing patterns:

```ts
await actUi({
  actions: [
    {
      action: "keypress",
      keys: ["a", "l", "i", "c", "e", "@", "e", "x", "a", "m", "p", "l", "e", ".", "c", "o", "m"]
    }
  ]
});

```

Note that omitting the `ref` property causes the keystrokes to target the currently focused element.

## Summary

- **`setText`** assigns string values directly to editable elements via `cdpTypeForContext` without generating keyboard events or requiring focus, making it optimal for high-speed data entry where intermediate state does not matter.
- **`keypress`** synthesizes native keyboard events character-by-character through `cdpKeypressForContext`, requiring a focused target but correctly triggering UI listeners for autocomplete, validation, and shortcuts.
- Choose **`setText`** for speed and reliability when you only need the final value; choose **`keypress`** when the application logic depends on per-keystroke event handling.

## Frequently Asked Questions

### Does `setText` trigger `input` or `change` events?

Typically, `setText` writes the value directly to the DOM element via `cdpTypeForContext`, which may or may not dispatch semantic events depending on the backend implementation. Unlike `keypress`, it does not generate discrete key events, so handlers listening specifically for `keydown` or `keyup` will not fire. However, some backends may emit a single `change` or `input` event after the atomic assignment.

### Can I send special keys like Enter or ArrowUp with `setText`?

No. **`setText` accepts only plain strings** and writes them literally to the element's value property. To send special keys or keyboard shortcuts like `Enter`, `ArrowUp`, or `Control+c`, you must use **`keypress`** with the appropriate key identifiers in the `keys` array.

### Why would `keypress` fail to input text?

`keypress` requires the target element to maintain focus throughout the operation. If the `ref` is omitted and no element currently has focus, or if the window loses focus during execution, the synthesized keystrokes will not register in the intended field. Ensure the element is focused before dispatching the action, or explicitly provide a `ref` to a focusable element as shown in the `setText` example.

### Is there a performance difference between `setText` and `keypress`?

Yes. **`setText`** executes in constant time regardless of string length because it performs a single atomic write via the CDP backend. **`keypress`** scales linearly with the number of characters in the `keys` array because it synthesizes separate hardware events for each entry. For large text blocks, `setText` is significantly more efficient.