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.

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.
/plugin marketplace add MDmubarak786/claude-mods
/plugin install show-paths@modhub
Try it for one session without installing:
claude --plugin-dir ./mods/show-paths
Nothing to do. Rows for these tools gain a dim path after Claude Code's own text:
| Tool | What's shown |
|---|---|
| Read, Edit, Write, MultiEdit | The file path, relative to the project root when it's inside it |
| NotebookEdit | The notebook path |
| Glob | The pattern, and the directory if one was given |
| Grep | The pattern, and the directory if one was given |
Bash and every other tool are drawn the way Claude Code draws them.
| Command | What it does |
|---|---|
/show-paths | Show whether it's on. |
/show-paths off | Draw rows the way Claude Code does. Remembered across sessions. |
/show-paths on | Turn it back on. |
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.
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.ToolGroup, and isn't labeled yet.MIT, see the repository root.
hooks/register.ts 96 lines1// 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