Braide includes a built-in file browser and code editor so you can inspect and modify files in the session's worktree without switching to an external editor. The browser opens as a docked panel on the right, and opened files are presented as tabs alongside a non-closeable Session tab — so you can flip between the agent conversation and any number of files while keeping everything mounted and live.
Click the folder icon in the session header toolbar (between the reset button and the GitHub panel button) to toggle the file browser panel. The icon is a single filled folder glyph — the same visual used for folders inside the browser tree itself — so the toggle reads as "show folders" at a glance.
When the panel is open, the toggle button is highlighted with the accent colour to make the active state obvious; when closed, it sits muted among the other toolbar buttons and picks up the standard hover treatment.
The panel slides in from the right, to the left of the GitHub panel. Both panels can be open at the same time.
The tree is rooted at the session's working directory — usually a worktree, or for project-root sessions the project root itself. You can only navigate within it; there is no way to traverse above the root.
What the listing includes depends on whether that working directory is a git repository:
.gitignore. Directories that contain only ignored files are hidden.node_modules/ or build output is included verbatim. Initialising a git repo and adding a .gitignore switches the listing to the filtered behaviour above.Then:
The session worktree is not always the only place you want files from. Notes, scratch projects, reference repositories, or shared assets often live outside the worktree but still belong "next to" the work. Braide lets you mount any number of custom directories alongside the worktree so they appear as additional roots in the file browser.
Custom directories are saved on the project, not the session — every session inside the same project sees the same list. Once added, a directory stays mounted until you explicitly remove it.
Click the Add Directory button in the panel header (the folder-with-plus icon, next to the refresh button). The chosen path is added to the project's preferences and a new root row appears below the worktree the next time the panel re-reads the list (immediately, on success).
Braide refuses to add a directory that overlaps the session worktree (equal to it, inside it, or containing it) or that overlaps a directory you have already added. This keeps the file browser's tree unambiguous — every file in the panel has exactly one path to it. If a candidate path is rejected the call returns a 400 with the conflicting root.
The path must exist and be a directory. Attempts to add a missing path, a regular file, or a symlink that doesn't resolve are rejected with a clear reason.
Each custom directory renders as a sibling root row directly below the worktree, sorted alphabetically by absolute path. The row's label is the full path so you can tell similarly-named directories apart at a glance.
Right-click any custom-directory root row to open its context menu:
Custom directories are read-only inside Braide. The right-click menu items available on worktree files and directories (New file…, Delete…) are not shown for entries inside a custom directory — saves and creates are deliberately restricted to the worktree so the file editor's diff and save flows have a consistent baseline.
The language server attaches to the session worktree, not to custom directories. Files opened from a custom directory load into the code editor without language-server intelligence; you may see warnings about unresolved imports or missing type information when the file would normally rely on a project context that lives elsewhere. The issue tracker accepts this trade-off — custom directories are intended for adjacent reference material, not for full development inside Braide.
Because custom directories are not watched live, the file browser will not surface changes the agent makes inside them in real time. Reload from Disk when you need a fresh view.
Clicking a media file in the worktree browser opens a preview tab rather than the code editor. Three categories are supported:
png, jpg, jpeg, gif, webp, svg, bmp, heic, heif. Rendered scaled-to-fit in the tab. SVGs are shown as their rendered vector image rather than as XML source.mp4, webm, mov, avi, mkv, m4v. Rendered with the browser's native video player (play/pause, scrubber, volume, fullscreen). Seeking works on files of any size — the player requests byte ranges on demand rather than downloading the whole file up front.mp3, wav, ogg, oga, m4a, aac, flac, opus, weba. Rendered with the browser's native audio controls (play/pause, scrubber, volume), with the filename shown above the player for context since audio has no visible frame. Like video, audio supports range-based seeking.Files with extensions outside these three lists open in the code editor as text. Media tabs share the tab bar with file tabs — the same click-to-activate, drag-to-reorder, and ✕-to-close interactions apply.
Drag the vertical handle on the left edge of the file browser panel to resize it. The panel has a minimum width (matching its default size) and a maximum of 50% of the session view's width, so the session content always retains at least half the available space.
When one or more files are open — or an attached GitHub issue or image has been promoted to a tab — a tab bar appears above the session content area. The bar contains:
#N TitleFile, issue, and image tabs share the same bar and the same interactions (click to activate, drag to reorder, ✕ to close). What differs is only the content shown when the tab is active.
Clicking a file in the browser:
In addition to files, any attached item whose pill has a popover can be promoted to a tab:
Opening as a tab closes the originating popover and activates the new tab. Each issue or image gets its own tab — re-opening the same issue or image focuses the existing tab rather than creating a duplicate, the same rule files follow.
If an attached issue or image is later detached from the session while its tab is still open, the tab shows a small placeholder explaining that the item is no longer attached, with a button to close the tab.
Click any tab to make it the active one. Each file editor is kept mounted while you switch between tabs, so unsaved edits, scroll position, and cursor location are preserved.
Close a file tab via either:
Closing the active tab activates the next-right tab, falling back to the previous tab, and finally to the Session tab if no file tabs remain. Closing a file with unsaved changes triggers the unsaved-changes confirmation.
The Session tab has no close button — the agent session is the root of the view and cannot be dismissed from the tab bar.
Drag a file tab horizontally to reorder it. While dragging:
The Session tab is fixed at position 0 and cannot be dragged or displaced by a file tab drop.
When there are more tabs than can fit, the tab bar scrolls horizontally — tabs keep their natural width and the scroll container ensures none are squashed or ellipsised prematurely. A tab label is capped at 16rem to guard against pathologically long filenames.
Switching to a file tab shows the editor for that file. The editor:
Dockerfile and Makefile).⌘F / Ctrl+F inside the editor) immediately.At the top of each file's editor there is a small toolbar showing:
●) when the editor has unsaved changesBecause the Session tab and every file tab are mounted simultaneously, any in-progress agent activity, streaming output, and terminal state keeps running while you are viewing or editing a file, and is immediately up to date the moment you flip back to the Session tab.
The editor shows uncommitted changes relative to the last commit (HEAD) as coloured markers in the line gutter, overview ruler, and minimap, mirroring the pattern VS Code uses for its source-control indicators.
As you type — or as the agent writes to files that are open in a tab — the markers update against the HEAD baseline, giving you an at-a-glance sense of which lines differ from the committed version:
The same colours appear in the overview ruler (the narrow strip on the right edge of the editor, next to the scrollbar) and minimap, so large changes are visible at a glance even in long files.
The markers always reflect the current buffer — including unsaved edits — compared against the version at HEAD that was captured when the tab opened. This gives you a live preview of what git diff will show once you save.
If the file is untracked (not yet added to git) or the session's working directory is not a git repository (for example a scratch session), the baseline is treated as empty and every line shows as an addition.
For extremely large diffs (roughly a multi-thousand-line rewrite) the editor falls back to a single bulk "modified" marker rather than per-region markers, so the editor stays responsive on huge files.
The ● dirty indicator in the editor toolbar and on the file tab tracks unsaved edits since the last load or save — it clears whenever you save. That is distinct from the gutter diff markers, which track differences against HEAD regardless of whether they are saved yet:
● dirty indicator lights up.● indicator clears, but gutter markers remain as long as the saved content still differs from HEAD.Note: the HEAD baseline is captured when the tab opens and is not refreshed while the tab is open. If you commit, amend, reset, or check out another branch from a terminal during an editing session, reopen the file to pick up the new baseline — the dirty indicator and the save flow continue to work correctly in the meantime, they just reflect the old baseline in the gutter.
The gutter markers described above are always on while the plain editor is active, but sometimes you want a full diff view of the file against HEAD. The toolbar includes a diff-view toggle (two-pane icon, next to the save button) that cycles the editor between three states:
git diff presents it. The toggle icon changes to a single framed document.Clicking the toggle advances to the next state; clicking again from inline returns to plain.
In both diff modes:
⌘S / Ctrl+S, the unsaved-changes indicator, and conflict detection all continue to work exactly as in the plain editor.The baseline is captured once when the tab opens, so the diff always compares against the HEAD snapshot at that point — not against what is currently on disk. Reopen the file to pick up a new HEAD.
For untracked files or files in scratch sessions (where there is no git baseline) the toggle is disabled with a tooltip explaining why — showing the entire file as "added" in a diff view is not useful.
The selected view mode is remembered per session and applies to every file tab there, so reloading the app or switching sessions keeps your preferred view.
Save the current file with either:
⌘S / Ctrl+S shortcut while the editor has focusSaves are atomic writes of the full file content to the worktree path. The file on disk is replaced with exactly what you see in the editor — trailing whitespace, final newline, encoding (UTF-8), and all. There is no auto-save, no create/rename/delete, and no live reload if the agent modifies the open file (those behaviors are intentionally out of scope for this release).
Closing a file tab (via either close button) while that file has unsaved edits opens a confirmation dialog asking whether to discard the changes or keep editing. This prevents accidentally losing work. Switching away from a dirty tab does not prompt — the edits stay in memory and the dirty indicator stays on the tab, so you can return and save later.
The agent running in the same session can modify the file you are editing. To avoid silently overwriting the agent's work, the editor checks whether the file on disk has changed since you opened it.
If it has, the save is rejected and a conflict dialog opens with three choices:
Ordinary saves of a file you are the only editor of never trigger a conflict.
The file browser and tab state are remembered per session, so switching sessions in the sidebar — or reloading the app — restores everything as you left it:
Custom directories (see Custom Directories) are saved at the project level rather than per-session. Every session inside the same project sees the same list of custom directories. Removing a custom directory from one session's panel removes it for every session of that project.
The contents of unsaved edits are not preserved — only which files had tabs open. Reopening a session loads each file's current on-disk contents into its tab. Issue and image tabs fetch their content afresh each time the session opens, so edits made to the underlying GitHub issue (new comments, state changes) show up immediately when the tab is restored.