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

# Code Editor

> Monaco-based code editor with multi-language syntax, autocomplete, find-in-files, refactor support, and a file tree that stays in sync with the agent.

<img src="https://mintcdn.com/tesslate/VT6tbZolrCfpx26M/images/opensail-banner.png?fit=max&auto=format&n=VT6tbZolrCfpx26M&q=85&s=66579c47537b3464fb65b229cc9ab0fd" alt="Tesslate OpenSail" width="4712" height="1612" data-path="images/opensail-banner.png" />

## A real editor

OpenSail ships a full Monaco editor (the engine that powers VS Code), not a chat box with a side panel. You get the same syntax highlighting, autocomplete, command palette, multi-cursor, and refactor shortcuts you expect from a dedicated coding tool.

The editor lives in `app/src/components/CodeEditor.tsx` and composes with the file tree, tab bar, and Design view.

<CardGroup cols={2}>
  <Card title="Multi-language" icon="language">
    TypeScript, JavaScript, Python, Go, Rust, Ruby, Java, C#, SQL, HTML, CSS, Markdown, YAML, JSON, and more.
  </Card>

  <Card title="Autocomplete" icon="wand-magic-sparkles">
    IntelliSense via Monaco's built-in language services. TypeScript gets full type inference.
  </Card>

  <Card title="Find and replace" icon="magnifying-glass">
    In-file and project-wide. Regex, case-sensitive, whole-word.
  </Card>

  <Card title="Refactor support" icon="arrows-rotate">
    Rename symbol, extract function, go to definition, find references.
  </Card>
</CardGroup>

## One tree, two authors

The agent sees the same tree, the same files, and the same shell output you do. Every edit the agent makes is a reviewable diff you can accept, reject, or keep editing. Every command the agent runs shows up in your terminal. The agent's work is your work, in the same checkout.

Files are saved through `POST /api/projects/{slug}/files/save`. The save writes to the database (always), and to the filesystem (Docker) or the volume (Kubernetes). The file-manager pod syncs changes across container restarts. Agents and humans post to the same endpoint.

## File tree

The left sidebar renders the project file tree with expand/collapse, single-click to open, right-click context menu (create file, create folder, rename, delete).

* **Search** filter at the top narrows the tree as you type
* **Empty directory support** directories with no files still render (backend sends entries ending in `/`)
* **Excluded directories** like `node_modules`, `.git`, `.next`, `__pycache__`, `dist`, `build`, `.venv`, `.cache`, `.turbo`, `coverage` never appear
* **Live updates** when the agent creates, renames, or deletes files (WebSocket push, not polling)

## Tabs

Click a file to open it in a tab. Multiple tabs open at once. Close with the `x` or middle-click. Tabs track dirty state (unsaved changes get a dot).

## Autosave

Files autosave after a short debounce when you stop typing. Toast confirmation ("Saved") appears briefly. No need to Cmd+S, but Cmd+S still works and triggers an immediate save.

## Language features

Monaco detects language from the file extension. Supported out of the box:

| Extension                 | Language               |
| ------------------------- | ---------------------- |
| `.ts`, `.tsx`             | TypeScript (JSX-aware) |
| `.js`, `.jsx`             | JavaScript             |
| `.py`                     | Python                 |
| `.go`                     | Go                     |
| `.rs`                     | Rust                   |
| `.rb`                     | Ruby                   |
| `.java`                   | Java                   |
| `.cs`                     | C#                     |
| `.sql`                    | SQL                    |
| `.html`, `.css`, `.scss`  | Web                    |
| `.md`, `.mdx`             | Markdown               |
| `.json`, `.yaml`, `.toml` | Config                 |
| `.sh`, `.bash`            | Shell                  |

## Keyboard shortcuts

All the standard Monaco shortcuts work:

| Shortcut               | Action                      |
| ---------------------- | --------------------------- |
| `Cmd/Ctrl + S`         | Save                        |
| `Cmd/Ctrl + P`         | Quick open file             |
| `Cmd/Ctrl + Shift + P` | Command palette             |
| `Cmd/Ctrl + F`         | Find in file                |
| `Cmd/Ctrl + Shift + F` | Find in project             |
| `Cmd/Ctrl + D`         | Add next match to selection |
| `Cmd/Ctrl + /`         | Toggle line comment         |
| `Cmd/Ctrl + B`         | Toggle file tree            |
| `F2`                   | Rename symbol               |
| `F12`                  | Go to definition            |
| `Alt + Click`          | Add multi-cursor            |

## Terminal beside the editor

Open the terminal panel for a real PTY attached to the running container. The terminal uses xterm.js (fit, weblinks, search addons) and connects over WebSocket.

* **Docker mode** `docker exec` into the container
* **Kubernetes mode** K8s API exec with PTY
* **Desktop local** subprocess with PTY

Shell sessions are persistent. An agent can `shell_open` a session, run a long-lived watcher, and you can attach to that same session from the terminal panel.

## Live preview

The preview iframe sits alongside the editor. HMR flows into the iframe automatically. Save a file, the preview repaints. See [Live Preview](/guides/live-preview) for details.

## Design view integration

Click into the Design view and the same editor stays in play. Clicking an element in the live preview jumps the editor to the JSX line that rendered it. Edits flow back through the same save API. See [Design Engineer](/guides/design-engineer).

## Empty directory handling

The backend sends directories with no files as entries ending in `/` (empty content). `buildFileTree` in `CodeEditor.tsx` treats these as directories:

```ts theme={null}
const isEmptyDir = file.file_path.endsWith('/');
const cleanPath = isEmptyDir ? file.file_path.slice(0, -1) : file.file_path;
```

Auto-select skips directory placeholders when picking the first file to open.

## Performance notes

* Monaco loads lazily (the bundle is large); the editor shows a placeholder until it is ready
* File tree is memoized; it only rebuilds when the files list changes
* Autosave is debounced 1000ms by default

## Related

<CardGroup cols={2}>
  <Card title="Live preview" icon="eye" href="/guides/live-preview">
    The iframe next to the editor.
  </Card>

  <Card title="Design engineer" icon="pen-ruler" href="/guides/design-engineer">
    Click-to-source canvas on top of the preview.
  </Card>

  <Card title="Chat interface" icon="comments" href="/guides/chat-interface">
    The agent edits the same files you do.
  </Card>

  <Card title="Git integration" icon="code-branch" href="/guides/git-integration">
    Diff, commit, push from the panel.
  </Card>
</CardGroup>
