Hide file content

Overview

Per-project settings page that marks specific lines or character ranges of a source file as hidden from the agent file tools. When the model calls read_file the hidden lines or characters come back as [hidden], and search_files silently skips any match that lands inside a hidden range or character span. The on-disk file is never modified, so the redaction stays purely on the model-facing side.

Usage

Open Settings → This project → More settings → Hide file content, or navigate directly to #/settings/project/hide.

  1. Tap + Add file, or tap a saved file row to edit it.

  2. The file opens in the real CodeMirror text editor (Select hidden content, dark theme, line numbers, syntax highlighting) with the original content. It is read-only — the text cannot be edited, only marked.

  3. Whole-line hiding — tap a line number in the toggle gutter (the column left of the text) to hide that line; tap it again to show it. Hidden lines get a highlighted background and a ✓ in the gutter. Each gutter cell is exactly as tall as the line it belongs to and 2rem wide, so a tap always lands on the line you aimed at.

  4. Character-range hiding — drag to select text inside the editor. The status bar updates with the column range, and Hide selected text in the sticky footer becomes enabled. Tap it to mark that span; tap it again with the same selection to clear it. A span on a single line hides the exact columns; a span that crosses line breaks hides the full middle lines plus the boundary columns.

  5. For larger whole-line selections, expand Enter line ranges manually and enter inclusive From / To numbers. Invalid values are explained rather than silently changed. Adjacent and overlapping ranges are merged on save; the same is done for character spans.

  6. Tap Save. Every action (hide selection, cancel, save) lives in the sticky footer, so it stays reachable and tappable no matter how far the editor or the manual ranges scroll. The editor returns to the file list only after saving succeeds. A failed save keeps the selection available for retry, and controls are disabled while a save is in progress.

Removing a hiding

Every file row on the list carries its own Remove action, so a file can be un-hidden without opening the editor:

GoalAction
Un-hide one saved lineTap the line number again in the editor gutter, then Save.
Un-hide one saved manual rangeEnter line ranges manually → × on that row → Save.
Un-hide selected textRe-select the same span and tap Hide selected text again (an exact match removes it).
Un-hide a whole fileTap Remove on its row and confirm Stop hiding content in <path>?
Un-hide everythingRemove each row, or clear the selection in every editor.

Button layout

The footer is the only interactive band: it is position: sticky; bottom: 0 and owns every control of this view. The editor and its help line scroll underneath it, and the footer — not the content — wins taps in that band.

┌─────────────────────────────┐
│ editor (read-only, scrolls) │
│ …help line (non-interactive)│
├─────────────────────────────┤  ← sticky footer starts here
│ [Hide selected text]  Cancel Save │
└─────────────────────────────┘

Do not move an action back into the editor body: a control rendered outside the footer can overlap the footer band and swallow taps meant for Cancel/Save.
The preview uses the existing 1 MiB file-editor read limit; if a file cannot be previewed, manual ranges remain available.

Back retains an unsaved selection in memory for a return visit to the same file and project. Cancel asks before discarding changes. Drafts contain only paths and ranges, not file content; they do not survive a reload, which warns while an editor has unsaved changes. To stop hiding a file, remove its ranges and save; removing all saved ranges and characters requires confirmation.

Protection limits

This is not a security boundary. Only read_file and search_files are filtered. Shell, MCP, and other access can still read the original content. These limits are visible on the list and editor, not hidden in a help popup. Rules track line numbers and column positions, not text, so review them after editing or moving file content.

# Settings → Project → More settings → Hide file content
src/secrets.js  →  Lines 3 · Text on line 1, cols 18–25

After saving, a read_file call on that file returns the hidden content replaced by a marker:

# File: src/secrets.js
# Lines: 1-4
const apiKey = "[hidden]";
const normal = 1;
[hidden]

And a search_files call for text that falls only inside a hidden range or character span returns no match for that line, even when the rest of the line is visible.

Labels

Every summary label comes from one helper, describeHidden({ ranges, chars }), so the list and the editor can never disagree about what is hidden:

Hidden contentLabel
lines onlyLines 3–5
selected text onlyText on line 8, cols 4–9
selected text across linesText on lines 4–7
lines and textLines 3–5 · Text on line 8, cols 4–9
nothingfile list: Nothing hidden yet…; editor: Tap a line number, or select text and tap Hide selected text.

Behavior

{
  "hideFileContent": [
    {
      "path": "src/secrets.js",
      "ranges": [ { "start": 3, "end": 3 } ],
      "chars":  [ { "startLine": 1, "endLine": 1, "startCol": 18, "endCol": 25 } ]
    }
  ]
}