melkin — ~/lab/decision-tree.mdx

~/lab/decision-tree

decision-tree

Claude's closing question, as a panel of options that I can try first

· claude-code · typescript · repo

claude plugin marketplace add melandres8/claude-mods
decision-tree/hooks/register.tsx
// No -f, -F, --follow or --retry: a fork that follows a file never ends. No
// operand starting with +: the traditional form `tail +5f` follows too.
tail: {
  short: 'qrv',
  shortValue: 'nc',
  count: true,
  long: ['--quiet', '--silent', '--verbose'],
  longValue: ['--lines', '--bytes'],
  operand: word => !word.startsWith('+'),
},

What it does

When a reply from Claude ends with a question, a small model (haiku) reads it and proposes 2 to 4 options. When Claude calls AskUserQuestion, the panel takes the questions in place of the native dialog.

When I pick an option, Claude analyses what it implies. The analysis covers what it would do next, the pros, the cons or risks, and whether the step is reversible.

The ✓ Confirmar button sends the answer as my next message. The ✎ Otra respuesta field adds my own answer as an option.

Install it with the command above, then claude plugin install decision-tree@claude-mods. The code is in melandres8/claude-mods, under the MIT license.

Try an answer in a fork

⑂ Probar en rama starts a fork: a real forked session that inherits the conversation and the permission mode. The fork investigates in read-only mode. It ends with a report: what it would do, the changes it proposes, the risks, and what it does not know yet.

The report appears in the panel, and I decide after I read it. If a new question arrives, decision-tree stops the forks that still work on the old one.

What a fork may call

decision-tree checks every tool call of a fork and refuses everything that is not a read. The refusal asks the fork to describe the change in its report.

  • Allowed: Read, Grep, Glob, LSP, ToolSearch, and Bash with read-only commands.
  • Refused: every other tool, which includes Write, Edit, Agent, and the MCP tools.
  • No network tools: WebFetch and WebSearch are refused too. A fork may read a secret, such as a .env file, and a URL or a search would carry it out.

The guard reads each shell command the way bash or zsh does, word by word. Each binary has a closed list of flags, as the snippet shows for tail. The guard also refuses variable expansion, command substitution, globs, and every redirection except the ones for stderr.

Limits

  • The guard closes the network tools, not every channel. On macOS, a read under /net/<host> makes the automounter resolve that name, and a DNS query can carry data out.
  • git diff, git log -p and git show can run programs that I set in my git config, such as diff.external or textconv. The fork inherits that config.
  • git status can rewrite the .git/index cache. It does not change files or history.
  • A closing question opens the panel on its own only when the panel docks beside the conversation. On the main screen, the status line shows a hint instead.

hire.me

Building something like this? I do it for clients. I reply within 48 h.