> ## Documentation Index
> Fetch the complete documentation index at: https://sdk.revise.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Documents

> Opening, switching, and closing documents in a multi-document workspace.

## Opening

Documents come in as `File`, `Blob`, or `ArrayBuffer`, in any of the [supported
formats](/guides/formats). Supply them upfront with `initialDocuments`, or open
them at runtime:

```ts theme={null}
const doc = await editor.documents.open(
  { id: "exhibit-a", title: "Exhibit A", docx: file },
  { activate: true },
);
```

`open()` resolves to a `ReviseDocumentHandle` once the document is parsed and
ready. Newly opened documents become active by default; pass
`{ activate: false }` to load one in the background.

<Warning>
  IDs are yours and must be stable and unique within one editor instance.
  Callbacks, tool routing, and `forDocument()` all key off them. Reusing an ID
  for different content will confuse both your code and your agent.
</Warning>

### Per-document options

Anything you can set editor-wide can be overridden per document:

```ts theme={null}
await editor.documents.open({
  id: "exhibit-a",
  docx: file,
  format: "markdown", // optional; inferred from the filename or MIME type
  title: "Exhibit A",
  documentMode: "suggesting",
  readOnly: false,
  zoom: "fit-width",
  defaultCommentsOpen: false,
  agent: { model: "claude-opus-5" },
});
```

## Switching and closing

```ts theme={null}
editor.documents.activate("exhibit-a");
editor.documents.close("exhibit-a");
editor.documents.getActiveId(); // "contract-1"
editor.documents.list();        // [{ id, title, status, active, error }]
```

Closing is a workspace operation, not a save: export first if you need the
bytes.

## Observing the collection

```ts theme={null}
useEffect(
  () =>
    editor.documents.subscribe((state) => {
      setTabs(state.documents);
      setActiveId(state.activeDocumentId);
    }),
  [editor],
);
```

Each entry carries a `status` of `"opening"`, `"ready"`, or `"error"`, plus an
`error` string when parsing failed — enough to render a tab strip with spinners
and error states without tracking it yourself.

## Controlled or uncontrolled

By default the component tracks the active document internally. To drive it
from your own state, pass `activeDocumentId` and handle
`onActiveDocumentChange`:

```tsx theme={null}
<ReviseEditor
  activeDocumentId={activeId}
  onActiveDocumentChange={setActiveId}
  initialDocuments={docs}
/>
```

`defaultActiveDocumentId` sets the initial choice without taking control.

## Exporting

```ts theme={null}
const blob = await editor.tools.exportDocx();               // active document
const other = await editor.tools.exportDocx("exhibit-a");   // a specific one
```

## Reading content

For your own logic — word counts, validation, autosave heuristics — read the
document tree directly:

```ts theme={null}
const doc = editor.getDocument();          // active
const doc2 = editor.getDocument("exhibit-a");
```

`onChange(documentId, document)` fires on every edit, from the user, your
toolbar, or an agent alike.

<Tip>
  `onChange` is chatty by design — it fires per keystroke. Debounce before
  persisting, and prefer `measure_document` or your own cheap heuristics over
  walking the whole tree on every call.
</Tip>
