- Renamed npm package scope from @mariozechner to @oh-my-pi across all packages for consistent branding.
- Removed packages/pods directory and all related pod management functionality.
- Updated import paths and module declarations throughout codebase to reflect new package names.
- Reformatted code with consistent trailing comma removal and ternary operator alignment.
- Added MCP (Model Context Protocol) support with stdio and HTTP transports for external tool integration.
- Implemented plugin system with install, enable, configure, and doctor commands for extensibility.
- Added 22 Exa MCP tools for web search, LinkedIn, company research, and websets operations.
- Introduced LSP tool with rust-analyzer support for code intelligence (diagnostics, hover, references, code actions).
- Added task tool for delegating work to specialized subagents with parallel execution support.
- Implemented web_search and web_fetch tools with Anthropic and Perplexity provider support.
- Added git context loading to system prompt to provide AI with repository state awareness.
- Implemented automatic detection of main/master branch to support varied repository conventions.
- Included current branch, git status, and recent commits snapshot for contextual understanding.
- Added emergency terminal restore function to reset terminal state on crashes without requiring instance access.
- Implemented crash handlers for SIGTERM, SIGHUP, uncaught exceptions, and unhandled rejections to ensure clean terminal exit.
- Added active terminal tracking to enable blind restore when no instance is available.
- Implemented a new welcome screen component for startup.
- Introduced a powerline-style footer with integrated git status, model info, and token usage.
- Consolidated extension loading messages into a new `/status` command.
- Added `?` hotkey to display shortcuts when the editor is empty.
Merged 53 commits from pi/main including:
- Export HTML rewrite with tree sidebar and /share command
- Hooks API enhancements (custom status, editor, session management)
- Edit diff preview before tool execution
- TUI fixes (Unicode format chars, OSC 8 hyperlinks, emoji optimization)
- Gemini CLI rate limit retry with server-provided delay
- Various bug fixes and documentation updates
Resolved conflicts by preserving Bun migration (spawn→Bun.spawn,
fs→Bun.file) while accepting upstream's new features and APIs.
- Migrated from Node.js to Bun runtime to leverage native TypeScript execution and faster startup times.
- Replaced npm with bun package manager and updated lockfile format.
- Converted Node.js APIs (child_process, fs, readline) to Bun equivalents across all packages.
- Updated shebang lines from node/tsx to bun for CLI entry points.
- Removed TypeScript build step by using source files directly as package entry points.
- Updated CI workflows to use Bun instead of Node.js for installation and testing.
The initial render of a session, and any re-draws caused by terminal
resizing are noticeably slow, especially on conversations with 20+
turns and many tool calls.
From profiling with `bun --cpu-prof` (available since bun 1.3.2), the
majority of the rendering (90%) is spent on detection of emojis in the
string-width library, running the expensive `/\p{RGI_Emoji}$/v`
regular expression on every individual grapheme cluster in the entire
scrollback. I believe it essentially expands to a fixed search against
every possible emoji sequence, hence the amount of CPU time spent in it.
This change replaces the `stringWidth` from string-width with a
`graphemeWidth` function that performs a similar check, but avoids
running the `/\p{RGI_Emoji}$/v` regex for emoji detection unless it
contains codepoints that could be emojis.
The `visibleWidth` function also has two more optimisations:
- Short-circuits string length detection for strings that are entirely
printable ASCII characters
- Adds a cache for non-ASCII segments to avoid recomputing string length
when resizing
BorderedLoader receives theme as a parameter but was creating
DynamicBorder() without passing it, causing DynamicBorder to
fall back to the global theme variable which is undefined when
loaded via jiti (separate module cache).
Added doc comment to DynamicBorder explaining the jiti issue.
Move line count from header to footer to avoid changing the first line
during streaming, which was triggering full screen re-renders in the
TUI's differential rendering logic.
Transfers context to a new focused session instead of compacting.
User provides a goal, hook generates a prompt with relevant context,
creates a new session with parent tracking, and loads the prompt
as a draft in the editor for review.
Inspired by Amp's handoff feature.
CustomToolContext now has:
- isIdle() - check if agent is streaming
- hasQueuedMessages() - check if user has queued messages
- abort() - abort current operation (fire-and-forget)
Changed abort() signature from Promise<void> to void in both
HookContext and CustomToolContext. The abort is fire-and-forget:
it calls session.abort() without awaiting, so the abort signal
is set immediately while waitForIdle() runs in the background.
Fixes#388
HookContext (all events):
- isIdle() - read-only state check
- hasQueuedMessages() - read-only state check
- abort() - fire-and-forget, does not wait
HookCommandContext (slash commands only):
- waitForIdle() - waits for agent to finish
- newSession(options?) - create new session
- branch(entryId) - branch from entry
- navigateTree(targetId, options?) - navigate session tree
Session control methods moved from HookAPI (pi.*) to HookCommandContext (ctx.*)
because they can deadlock when called from event handlers that run inside
the agent loop (tool_call, tool_result, context events).
HookAPI additions:
- pi.newSession(options?) - create new session with optional setup callback
- pi.branch(entryId) - branch from a specific entry
- pi.navigateTree(targetId, options?) - navigate the session tree
HookContext additions:
- ctx.isIdle() - check if agent is streaming
- ctx.waitForIdle() - wait for agent to finish
- ctx.abort() - abort current operation
- ctx.hasQueuedMessages() - check for queued user messages
These enable hooks to programmatically manage sessions (handoff, templates)
and check agent state before showing interactive UI.
Fixes#388
- Remove session_before_new and session_new hook events
- Add reason: 'new' | 'resume' to session_before_switch and session_switch events
- Remove 'new' reason from custom tool onSession (use 'switch' for both /new and /resume)
- Rename reset() to newSession(options?) in AgentSession
- Add NewSessionOptions with optional parentSession for lineage tracking
- Rename branchedFrom to parentSession in SessionHeader
- Rename RPC reset command to new_session with optional parentSession
- Update example hooks to use new event structure
- Update documentation and changelog
Based on discussion in #293
Strip all Unicode format characters (category Cf) before passing to
string-width. These are invisible control characters that crash
string-width but have no visible width anyway.
Closes#390
- Add optional 'export' section to theme JSON with pageBg, cardBg, infoBg
- If not specified, colors are auto-derived from userMessageBg
- Add export colors to dark.json and light.json
- Update theme-schema.json and TypeBox schema
- Add documentation to docs/theme.md
- Add margin-top back to tool-output for spacing between header and content
- Add theme property to HookUIContext interface
- Implement in interactive, RPC, and no-op contexts
- Add status-line.ts example hook
- Document styling with theme colors in hooks.md
The white-space: pre-wrap on .tool-output was preserving template
literal whitespace (newlines and indentation). The pre elements
inside still have pre-wrap for actual code content.
* Add ctx.ui.setStatus(key, text) API for hooks to display status in footer
- Add setStatus to HookUIContext interface
- Implement in interactive mode (FooterComponent)
- Implement in RPC mode (fire-and-forget)
- Add no-op implementations for headless contexts
- Multiple statuses displayed on single line, sorted by key
- Supports ANSI styling (hooks handle their own colors)
* Remove setStatus from changelog for now
* Fix hook status API to follow TUI rules
- Sanitize status text: replace newlines, tabs, carriage returns with spaces
- Truncate combined status line to terminal width using truncateToWidth
- Update JSDoc to document sanitization and truncation behavior
- Remove unused createHookUIContext method
- Add missing setStatus to test mock
* Add setStatus to changelog
* Use dim ellipsis for hook status truncation for consistency with footer style
---------
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
- Use BorderedLoader for /share command so Escape cancels gist creation
- Add CHANGELOG entries for /share command and HTML export improvements
- Add todo.md with remaining export-html issues