ModsCodeMERGEBLE LLC Search Claude Code Mods

ModsCode / Gallery / Designs / File tree with changes

File tree with changes

A project tree in Box and Text: muted glyphs, bold folders, and one column of git status letters, adds and deletes in the theme's colours.

File tree with changesFile tree with changes
Code and CI · 380×336 · sample data
hooks/designs/file-tree.mjs
// file-tree: a working tree with its git status, as Box and Text only. 18 rows counting the root:
// the tree glyphs (4 columns a level) are muted so the names carry the shape, folders are bold, and
// the status letter sits alone at column 48 so the changes read down one column, as in git status
// --short: M plain, A success, D error, ? subtle. M is not in warning: six Claude orange letters would be six
// accents and drown the adds and deletes. Unchanged files get no letter, so the column is sparse
// enough to scan. The rows are drawn from a nested list, so a glyph is never typed by hand.
// 6 changed (M), 2 added, 2 deleted, 1 untracked; the footer is counted from the rows.
// Same frame as the other text designs: the root is the bold subject line with a muted SAMPLE at
// column 48, and a muted summary closes it. Sample data only.
const ROOT = 'agent-pool/'
const WIDTH = 48
const TAG = 'SAMPLE'

// [name, status] for a file, [name, [children]] for a folder
const TREE = [
  ['.claude/', [['settings.json', 'M']]],
  ['src/', [
    ['agents/', [['budget.ts', 'A'], ['pool.ts', 'M'], ['retry.ts', 'D']]],
    ['hooks/', [['pre-commit.ts', 'M']]],
    ['index.ts', ''],
    ['tokens.ts', 'M'],
  ]],
  ['test/', [['budget.spec.ts', 'A'], ['pool.spec.ts', 'M'], ['retry.spec.ts', 'D']]],
  ['CLAUDE.md', 'M'],
  ['scratch.log', '?'],
]
const STATUS = { M: null, A: 'success', D: 'error', '?': 'subtle' }
const WORD = { M: 'changed', A: 'added', D: 'deleted', '?': 'untracked' }

// Depth-first rows: the glyphs above a row are '│   ' while that ancestor has later siblings
function rows(items, lead = '', out = []) {
  items.forEach(([name, rest], i) => {
    const last = i === items.length - 1
    const folder = Array.isArray(rest)
    out.push({ glyph: lead + (last ? '└── ' : '├── '), name, folder, status: folder ? '' : rest })
    if (folder) rows(rest, lead + (last ? '    ' : '│   '), out)
  })
  return out
}
const ROWS = rows(TREE)
const SUMMARY = Object.keys(WORD)
  .map(s => `${ROWS.filter(r => r.status === s).length} ${WORD[s]}`)
  .join(', ')

export default {
  id: 'file-tree',
  title: 'File tree with changes',
  category: 'code',
  description: 'A project tree in Box and Text: muted glyphs, bold folders, and one column of git status letters, adds and deletes in the theme\'s colours.',
  element: ui => {
    const { Box, Text } = ui
    return Box({
      flexDirection: 'column',
      children: [
        Text({
          key: 'root',
          children: [
            Text({ key: 'name', bold: true, children: [ROOT.padEnd(WIDTH - TAG.length)] }),
            Text({ key: 'tag', dimColor: true, children: [TAG] }),
          ],
        }),
        ...ROWS.map((r, i) => Text({
          key: `r${i}`,
          children: [
            Text({ key: 'g', dimColor: true, children: [r.glyph] }),
            r.status
              ? Text({ key: 'n', children: [r.name.padEnd(WIDTH - 1 - r.glyph.length)] })
              : Text({ key: 'n', bold: r.folder, children: [r.name] }),
            r.status && Text({ key: 's', ...(STATUS[r.status] && { color: STATUS[r.status] }), children: [r.status] }),
          ],
        })),
        Text({ key: 'sum', dimColor: true, children: [`-- ${SUMMARY} --`] }),
      ],
    })
  },
}

To use it in a mod: copy the file to your mod's hooks/designs/ and return its element(ui) from a pane's ui.render. How a pane is built.

Code: PolyForm Noncommercial License 1.0.0: noncommercial use only. Required Notice: Copyright 2026 Haruki Nakada (https://modscode.com).