singularity-forge/docs/pi-ui-tui/14-tool-rendering-custom-tool-display.md
Lex Christopherson 9f4bf8c452 fix: restore PR files lost during merge conflict resolution
Files added by PR #2008 that were not in main were dropped during
the merge. Restore all src/, docs/, and scripts/ files from the
pre-merge PR head.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 22:39:33 -06:00

2.6 KiB

Tool Rendering — Custom Tool Display

Tools can control how their calls and results appear in the message area.

renderCall — How the Tool Call Looks

import { Text } from "@mariozechner/pi-tui";

pi.registerTool({
  name: "my_tool",
  // ...

  renderCall(args, theme) {
    // args = the tool call arguments
    let text = theme.fg("toolTitle", theme.bold("my_tool "));
    text += theme.fg("muted", args.action);
    if (args.text) text += " " + theme.fg("dim", `"${args.text}"`);
    return new Text(text, 0, 0);  // 0,0 padding — the wrapping Box handles padding
  },
});

renderResult — How the Tool Result Looks

import { Text } from "@mariozechner/pi-tui";
import { keyHint } from "@mariozechner/pi-coding-agent";

pi.registerTool({
  name: "my_tool",
  // ...

  renderResult(result, { expanded, isPartial }, theme) {
    // result.content — the content array sent to the LLM
    // result.details — your custom details object
    // expanded — whether user toggled expand (Ctrl+O)
    // isPartial — streaming in progress (onUpdate was called)

    // Handle streaming state
    if (isPartial) {
      return new Text(theme.fg("warning", "Processing..."), 0, 0);
    }

    // Handle errors
    if (result.details?.error) {
      return new Text(theme.fg("error", `Error: ${result.details.error}`), 0, 0);
    }

    // Default view (collapsed)
    let text = theme.fg("success", "✓ Done");
    if (!expanded) {
      text += ` (${keyHint("expandTools", "to expand")})`;
    }

    // Expanded view — show details
    if (expanded && result.details?.items) {
      for (const item of result.details.items) {
        text += "\n  " + theme.fg("dim", item);
      }
    }

    return new Text(text, 0, 0);
  },
});

Key Hints for Keybindings

import { keyHint, appKeyHint, editorKey, rawKeyHint } from "@mariozechner/pi-coding-agent";

// Editor action hint (respects user's keybinding config)
keyHint("expandTools", "to expand")    // e.g., "Ctrl+O to expand"
keyHint("selectConfirm", "to select")  // e.g., "Enter to select"

// Raw key hint
rawKeyHint("Ctrl+O", "to expand")      // Always shows "Ctrl+O to expand"

Fallback Behavior

If renderCall or renderResult is not defined or throws:

  • renderCall → shows tool name
  • renderResult → shows raw text from content

Best Practices

  • Return Text with padding (0, 0) — the wrapping Box handles padding
  • Support expanded for detail on demand
  • Handle isPartial for streaming progress
  • Keep the default (collapsed) view compact
  • Use \n for multi-line content within a single Text