SLOPSHOPPER

show-paths

Put the file path on every Read, Edit, Write, Glob, and Grep row in the transcript, so you never expand a row just to learn which file it touched.

newrowscommand
v0.1.0MITupdated 2026-10-09MDmubarak786/claude-mods/mods/show-paths
A shopper browsing a rack in a slop shop
Preview · a replayed session in a sandbox
claude · ~/work/app · show-paths
› fix the failing auth test and add an audit log call ⏺ Read(src/auth.ts) ⎿ Read 6 lines ⟨Claude Code's own drawing⟩ src/auth.ts ⏺ Bash(bun test) ⎿ 3 pass, 1 fail ● Done. refresh now rejects expired claims and logs an audit event. ✻ Worked for 42s · done 4:20 PM › /show-paths ⎿ show-paths: show-paths on. /show-paths off or /show-paths on ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────── › ? for shortcuts

Draws

Tool row
⟨Claude Code's own drawing⟩ src/auth.ts
README

show-paths

Put the file path on every Read, Edit, Write, Glob, and Grep row in the transcript. Claude Code draws Read 1 file (ctrl+o to expand); this mod keeps that row and adds src/app.ts beside it, relative to the project root, so you never expand a row just to learn which file it touched.

The request behind it is one of the most-reacted open issues on the Claude Code tracker (anthropics/claude-code#21151): no indication of which file, so you can't audit a session by scrolling it.

Install

/plugin marketplace add MDmubarak786/claude-mods
/plugin install show-paths@modhub

Try it for one session without installing:

claude --plugin-dir ./mods/show-paths

Use it

Nothing to do. Rows for these tools gain a dim path after Claude Code's own text:

ToolWhat's shown
Read, Edit, Write, MultiEditThe file path, relative to the project root when it's inside it
NotebookEditThe notebook path
GlobThe pattern, and the directory if one was given
GrepThe pattern, and the directory if one was given

Bash and every other tool are drawn the way Claude Code draws them.

CommandWhat it does
/show-pathsShow whether it's on.
/show-paths offDraw rows the way Claude Code does. Remembered across sessions.
/show-paths onTurn it back on.

What it touches

From claude plugin validate ./mods/show-paths:

hooks: session.start, command.run{command=show-paths}, ui.render{component=ToolUse}
calls: $.command.register, $.session.root (via loadSettings), $.store.get (via loadSettings), $.store.set, $.ui.invalidate, $.ui.log, $.ui.resolve

It changes nothing Claude reads. The only saved value is the on/off flag.

Tested with

  • Claude Code 2.1.295, claude plugin validate --strict and claude plugin test pass. The row layout is verified by mount tests in the terminal surface; the mod has no command output to check under claude -p, so the rows haven't been seen on screen by the author yet. Screenshots welcome.

Limitations

  • A collapsed group of calls ("Read 3 files") is its own render site, ToolGroup, and isn't labeled yet.
  • A refused call's reason is drawn by Claude Code in the result row, not by this mod.
  • A path outside the project root is shown in full.

License

MIT, see the repository root.

Source 1 files
hooks/register.ts 96 lines
1// show-paths: put the file path on every Read, Edit, Write, Glob, and Grep row.
2//
3//   /show-paths        show whether it's on
4//   /show-paths off    draw rows the way Claude Code does
5//   /show-paths on     turn it back on
6//
7// Claude Code draws a tool row like "Read 1 file (ctrl+o to expand)". This mod
8// keeps that row and adds the path, relative to the project root, beside it.
9// It changes nothing Claude reads; it only changes what you see.
10
11let root = ''
12let enabled = true
13
14// The input field that names what each tool touched.
15function pathOf(tool: string, input): string | null {
16  if (!input || typeof input !== 'object') return null
17  switch (tool) {
18    case 'Read':
19    case 'Edit':
20    case 'Write':
21    case 'MultiEdit':
22      return typeof input.file_path === 'string' ? input.file_path : null
23    case 'NotebookEdit':
24      return typeof input.notebook_path === 'string' ? input.notebook_path : null
25    case 'Glob':
26    case 'Grep': {
27      const pattern = typeof input.pattern === 'string' ? input.pattern : null
28      if (!pattern) return null
29      const where = typeof input.path === 'string' ? input.path : ''
30      return where ? pattern + ' in ' + where : pattern
31    }
32    default:
33      return null
34  }
35}
36
37function relative(path: string): string {
38  if (root && path.startsWith(root + '/')) return path.slice(root.length + 1)
39  return path
40}
41
42async function loadSettings($) {
43  try {
44    root = await $.session.root()
45  } catch {
46    root = ''
47  }
48  try {
49    enabled = (await $.store.get('enabled')) !== false
50  } catch {
51    enabled = true
52  }
53}
54
55export function register(on) {
56  on('session.start', async ($, e, next) => {
57    await loadSettings($)
58    try {
59      await $.command.register({
60        name: 'show-paths',
61        description: 'Show file paths on tool rows',
62        argumentHint: '[on | off]',
63        immediate: true,
64      })
65    } catch (error) {
66      $.ui.log('could not register /show-paths: ' + error)
67    }
68    return next(e)
69  })
70
71  on('command.run', { command: 'show-paths' }, async ($, e) => {
72    const args = e.args.trim()
73    if (args === 'on' || args === 'off') {
74      enabled = args === 'on'
75      await $.store.set('enabled', enabled)
76      $.ui.invalidate('ui.render')
77      return { text: enabled ? 'show-paths on.' : 'show-paths off. Rows are drawn the way Claude Code draws them.' }
78    }
79    return { text: (enabled ? 'show-paths on' : 'show-paths off') + '. /show-paths off or /show-paths on' }
80  }).catch(async () => ({ text: 'show-paths: the command failed, so nothing changed.' }))
81
82  // Keep Claude Code's row and add the path beside it.
83  on('ui.render', { component: 'ToolUse' }, async ($, e, next) => {
84    if (!enabled) return next(e)
85    const path = pathOf(e.props.tool, e.props.input)
86    if (!path) return next(e)
87    const { Box, Text } = $.ui.resolve(e)
88    const theirs = await next(e)
89    return Box({
90      flexDirection: 'row',
91      columnGap: 1,
92      children: [theirs, Text({ dimColor: true, wrap: 'truncate-start', children: [relative(path)] })],
93    })
94  })
95}
96