Extension guides
Tool and entry renderers
Transcript renderers replace the default presentation for one tool name or session-entry type. They present Pi data; they do not execute tools or write entries themselves.
Tool renderers
Add a renderer under the exact tool name registered with Pi. It receives the call immediately and an optional result once execution has produced one.
export default defineRenderer({
apiVersion: 1,
tools: {
"db.query": ({ call, result }) => {
const sql = String(call.arguments.sql ?? "");
if (!result) return <QueryProgress sql={sql} />;
if (result.isError) return <QueryError sql={sql} message={result.text} />;
return <QueryResult sql={sql} rows={result.details} />;
},
},
});Render the full lifecycle
- Running:
resultis undefined. Keep the call identity and arguments visible while work is in flight. - Success: show the useful structured result, with raw text available when it helps explain the outcome.
- Failure:
result.isErroris true. Make failure at least as clear as NativePi's default tool container.
Calls may restore from a session long after the package version that created them. Treat arguments and details defensively unless you have narrowed their generic types and preserve compatibility intentionally.
Tool types
interface ToolCall<Arguments extends Record<string, unknown>> {
id: string;
name: string;
arguments: Arguments;
}
interface ToolResult<Details> {
toolName: string;
text: string;
details?: Details;
isError: boolean;
}Entry renderers
Entry renderers are keyed by the top-level entry.type value stored in the Pi session. They receive the complete entry object and current renderer context.
export default defineRenderer({
apiVersion: 1,
entries: {
compaction: ({ entry }) => (
<CompactionSummary summary={String(entry.summary ?? "Session compacted")} />
),
},
});Pi entries created with pi.appendEntry(customType, data) have top-level type custom and carry their extension key inentry.customType. A renderer registered under custom must inspect that field and return a fallback for entries it does not recognize.