# gstack Command Dispatch Categorization: READ, WRITE, and META Explained

> Understand gstack command dispatch categorization READ WRITE and META. Learn how gstack determines execution paths enforces permissions and filters content for secure operations.

- Repository: [Garry Tan/gstack](https://github.com/garrytan/gstack)
- Tags: internals
- Published: 2026-05-15

---

**The gstack browser daemon categorizes every incoming command into one of three canonical sets—READ, WRITE, or META—to determine the execution path, apply appropriate content filtering, and enforce permission boundaries.**

The **gstack** project (garrytan/gstack) implements a sophisticated command dispatch system that classifies browser automation instructions based on their side effects and scope. This categorization, defined in the source of truth at [`browse/src/commands.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/commands.ts), enables the daemon to route requests through specialized handlers for data extraction, state modification, or meta-level control operations.

## The Three Command Categories

The classification system partitions all available commands into **READ**, **WRITE**, and **META** sets. Each category determines how the server processes the request and whether the operation mutates browser state or daemon configuration.

### READ Commands

**READ** commands extract information from the current page without causing side effects or modifying state. These operations are considered safe for repeated execution and are routed through the `handleReadCommand` path.

The `READ_COMMANDS` set includes: `text`, `html`, `links`, `forms`, `accessibility`, `js`, `eval`, `css`, `attrs`, `console`, `network`, `cookies`, `storage`, `perf`, `dialog`, `media`, `data`, `inspect`.

According to the source in [`browse/src/server.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/server.ts), when a command matches this set, the server applies content-filtering and wrapping before returning untrusted external content to the caller.

### WRITE Commands

**WRITE** commands modify the page, browser state, or environment. These operations trigger the `handleWriteCommand` path and may alter DOM elements, navigation history, cookies, or perform file downloads.

The `WRITE_COMMANDS` set includes: `goto`, `back`, `forward`, `reload`, `load-html`, `click`, `fill`, `select`, `hover`, `type`, `press`, `scroll`, `wait`, `viewport`, `cookie`, `header`, `useragent`, `upload`, `dialog-accept`, `dialog-dismiss`, `style`, `cleanup`, `prettyscreenshot`, `download`, `scrape`, `archive`.

### META Commands

**META** commands control the daemon itself, manage tabs, handle snapshots, or provide auxiliary services. These operations invoke `handleMetaCommand` and can affect the lifecycle of browser instances or orchestrate multi-step workflows.

The `META_COMMANDS` set includes: `tabs`, `tab`, `tab-each`, `newtab`, `closetab`, `status`, `stop`, `restart`, `screenshot`, `pdf`, `responsive`, `chain`, `url`, `snapshot`, `handoff`, `resume`, `connect`, `disconnect`, `focus`, `inbox`, `watch`, `state`, `frame`, `ux-audit`, `domain-skill`, `skill`, `cdp`.

## Runtime Dispatch Implementation

The categorization logic executes at runtime in [`browse/src/server.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/server.ts) using simple set membership checks:

```typescript
if (READ_COMMANDS.has(command)) {
  // Route through read-path: handleReadCommand
} else if (WRITE_COMMANDS.has(command)) {
  // Route through write-path: handleWriteCommand
} else if (META_COMMANDS.has(command)) {
  // Route through meta-path: handleMetaCommand
}

```

This dispatch mechanism ensures that **READ** operations receive appropriate content wrapping for security, **WRITE** operations execute with proper state management, and **META** operations can access privileged daemon APIs. The [`browse/src/token-registry.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/token-registry.ts) file leverages these same categories to map token scopes onto permission checks, ensuring that authorization boundaries align with command classifications.

## Practical Usage Examples

Execute commands through the gstack CLI using the `B` shorthand:

```bash

# READ example – extract clean page text without side effects

$ B text
--- BEGIN UNTRUSTED EXTERNAL CONTENT (source: https://example.com) ---
Lorem ipsum dolor sit amet…
--- END UNTRUSTED EXTERNAL CONTENT ---

```

```bash

# WRITE example – navigate to a new URL (modifies browser state)

$ B goto https://example.com

```

```bash

# META example – create a snapshot of the accessibility tree

$ B snapshot -i
{
  "elements": [ … ],
  "refs": { "@e1": "button.submit", … }
}

```

## Programmatic Category Detection

Import the canonical command sets from [`browse/src/commands.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/commands.ts) to categorize commands programmatically:

```typescript
import { READ_COMMANDS, WRITE_COMMANDS, META_COMMANDS } from './browse/src/commands';

function categorize(cmd: string): 'READ' | 'WRITE' | 'META' | 'UNKNOWN' {
  if (READ_COMMANDS.has(cmd)) return 'READ';
  if (WRITE_COMMANDS.has(cmd)) return 'WRITE';
  if (META_COMMANDS.has(cmd)) return 'META';
  return 'UNKNOWN';
}

```

The test suite in [`test/skill-validation.test.ts`](https://github.com/garrytan/gstack/blob/main/test/skill-validation.test.ts) validates that the union of these three sets covers every documented command, ensuring the categorization remains exhaustive as the API evolves.

## Summary

- **READ commands** (`text`, `html`, `links`, etc.) extract data without side effects and route through `handleReadCommand` with content filtering.
- **WRITE commands** (`goto`, `click`, `fill`, etc.) mutate page or browser state and execute via `handleWriteCommand`.
- **META commands** (`snapshot`, `tabs`, `skill`, etc.) control the daemon lifecycle and tab management through `handleMetaCommand`.
- The canonical definitions live in [`browse/src/commands.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/commands.ts), while the runtime dispatch logic resides in [`browse/src/server.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/server.ts).

## Frequently Asked Questions

### How does gstack determine which handler to use for a command?

The server performs set membership checks against `READ_COMMANDS`, `WRITE_COMMANDS`, and `META_COMMANDS` exported from [`browse/src/commands.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/commands.ts). Depending on which Set contains the command string, the server invokes `handleReadCommand`, `handleWriteCommand`, or `handleMetaCommand` respectively.

### Can I extend the gstack command categories with custom commands?

Yes, you can modify [`browse/src/commands.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/commands.ts) to add entries to the existing Sets, though you must implement corresponding logic in [`browse/src/server.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/server.ts) to handle the new commands. The validation tests in [`test/skill-validation.test.ts`](https://github.com/garrytan/gstack/blob/main/test/skill-validation.test.ts) will help ensure your additions maintain categorization coverage.

### Why does gstack distinguish between READ and WRITE operations?

The separation enables security controls like content filtering for external data (applied to READ results) and permission scoping via the token registry in [`browse/src/token-registry.ts`](https://github.com/garrytan/gstack/blob/main/browse/src/token-registry.ts). It also allows the daemon to optimize caching and logging, since READ operations are idempotent while WRITE operations require state synchronization.