- Merged theme.md content into themes.md
- Added hot reload documentation
- Updated all references from theme.md to themes.md
- Fixed outdated info (vars not defs, complete example with all 50 tokens)
- Removed dev-focused Implementation section
* fix(coding-agent): HTML export sidebar click scrolls instead of truncating branch
Previously, clicking a message in the sidebar tree would set that message
as the new leaf, causing getPath() to only return messages up to that point
and hiding all messages below it.
Now handleTreeNodeClick() checks if the clicked entry is on the current path:
- If yes: just scrolls to it without re-rendering
- If no: finds the actual leaf of that branch and navigates to it, then
scrolls to the clicked message
Added childrenMap for parent->children lookup and findBranchLeaf() to
traverse down to a branch's leaf.
* fix(coding-agent): HTML export sidebar click scrolls instead of truncating branch
Previously, clicking a message in the sidebar tree would set that message
as the new leaf, causing getPath() to only return messages up to that point
and hiding all messages below it.
Now handleTreeNodeClick() checks if the clicked entry is on the current path:
- If yes: scrolls to it and updates the active marker
- If no: finds the branch's leaf, navigates to it, then scrolls to clicked message
Adds currentTargetId to track the selected entry separately from currentLeafId
(which branch to display), so the active marker follows user selection.
* most recent path wins
* reuse method
* revert
* feat(coding-agent): highlight active path in HTML export sidebar
- Add subtle accent background tint to in-path nodes
- Dim off-path nodes to 50% opacity (restore on hover)
- Makes current branch visually distinct in tree navigation
* docs(coding-agent): move changelog entry to Unreleased and add attribution
* chore(coding-agent): remove dead code and fix changelog attribution
- Remove unused childrenMap, findBranchLeaf, handleTreeNodeClick, scrollToEntry
- Split changelog entry: navigation (#853 by @mitsuhiko), highlighting (#929 by @hewliyang)
Extensions calling setWorkingMessage() in agent_start handlers previously
had no effect because the loading animation didn't exist yet. Now the
message is queued and applied once the loader is created.
Fixes#935
- Add resetApiProviders() to clear and re-register built-in providers
- Add createAssistantMessageEventStream() factory for extensions
- Add streamSimple support in ProviderConfig for custom API implementations
- Call resetApiProviders() on /reload to clean up extension providers
- Add custom-provider.md documentation
- Add custom-provider.ts example with full Anthropic implementation
- Update extensions.md with streamSimple config option
When set to true, the skill is hidden from the system prompt, preventing
agentic invocation. Users can still invoke explicitly via /skill:name.
Also fixes pre-existing test bug where source expectation was wrong.
Fixes#927
- Package deduplication: same package in global+project, project wins
- Collision detection for skills, prompts, and themes with ResourceCollision type
- PathMetadata tracking with parent directory lookup for file paths
- Display improvements: section headers, sorted groups, accent colors for packages
- pi list shows full paths below package names
- Extension loader discovers files in directories without index.ts
- In-memory SettingsManager properly tracks project settings
fixes#645
For extension development, reloading now rebuilds the full chat history
so updated component rendering is visible immediately, not just in new
messages.
Also removes broken test for deleted chalk-logger.ts extension (npm
dependency resolution is already covered by with-deps test).
- Add PackageSource type for npm/git sources with optional filtering
- Migrate npm:/git: sources from extensions to packages array
- Add getPackages(), setPackages(), setProjectPackages() methods
- Update package-manager to resolve from packages array
- Support selective loading: extensions, skills, prompts, themes per package
- Update pi list to show packages
- Add migration tests for settings
closes#645
- Add ParsedSkillBlock interface and parseSkillBlock() function
- Change skill expansion to use XML-style <skill> tags
- Add SkillInvocationMessageComponent for collapsible display
- Collapsed: single line with skill name and expand hint
- User message rendered separately after skill block
Fixes#894
Header values in models.json now resolve using the same logic as apiKey:
- Environment variable names are resolved to their values
- Shell commands prefixed with ! are executed
- Literal values are used directly
This is a minor breaking change: if a header value accidentally matches
an env var name, it will now resolve to that env var's value.
Fixes#909
- Add ResourceLoader interface and DefaultResourceLoader implementation
- Add PackageManager for npm/git extension sources with install/remove/update
- Add session.reload() and session.bindExtensions() APIs
- Add /reload command in interactive mode
- Add CLI flags: --skill, --theme, --prompt-template, --no-themes, --no-prompt-templates
- Add pi install/remove/update commands for extension management
- Refactor settings.json to use arrays for skills, prompts, themes
- Remove legacy SkillsSettings source flags and filters
- Update SDK examples and documentation for ResourceLoader pattern
- Add theme registration and loadThemeFromPath for dynamic themes
- Add getShellEnv to include bin dir in PATH for bash commands
Error messages for missing credentials and shell config now use
getAuthPath() and getSettingsPath() instead of hardcoded ~/.pi/agent/
paths, so they correctly reflect PI_CODING_AGENT_DIR when set.
* feat(extensions): add inline-bash example for expanding !{command} in prompts
Adds an example extension that expands inline bash commands within user
prompts before sending to the agent. Uses the `input` event to transform
patterns like `!{pwd}` or `!{git status}` into their output.
Preserves existing `!command` whole-line bash behavior.
* docs(extensions): add inline-bash to README
* chore: fix stupid bug
* ⏺ feat(tui): show session name in terminal title and footer
- Add updateTerminalTitle() method that sets terminal title to
"π - session-name - dirname" (or "π - dirname" if no name)
- Update title when session name changes via /name or extension API
- Display session name in footer after git branch with bullet separator
* chore: update CHANGELOG
getResolvedThemeColors and getThemeExportColors now fall back to
currentThemeName before getDefaultTheme(), so exports respect the
user's selected theme.
Add markdown.codeBlockIndent setting to customize indentation prefix for
rendered code blocks. Default remains 2 spaces for visual clarity, but
setting to empty string removes indentation for easier copy/paste of
code snippets to scripts, editors, or other tools.
Changes:
- tui: add optional codeBlockIndent to MarkdownTheme interface
- coding-agent: add MarkdownSettings with codeBlockIndent property
- coding-agent: compose theme with settings at call sites (no global state)
- coding-agent: update message components to accept optional MarkdownTheme
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>
Fixes OpenAI Responses 400 error 'reasoning without following item' by
skipping errored/aborted assistant messages entirely rather than filtering
at the provider level. This covers openai-responses, openai-codex-responses,
and future providers.
Removes strictResponsesPairing compat option (no longer needed).
Closes#838
Split OpenAICompat into OpenAICompletionsCompat and OpenAIResponsesCompat
for type-safe API-specific compat settings. Added strictResponsesPairing
option to suppress orphaned reasoning/tool calls on incomplete turns,
fixing 400 errors on Azure's Responses API which requires strict pairing.
Closes#768
* Support shell command execution for API key resolution in models.json
Add ! prefix support to apiKey field in models.json to execute shell commands
and use stdout as the API key. This allows users to store API keys in secure
credential managers like macOS Keychain, 1Password, Bitwarden, or HashiCorp Vault.
Example: "apiKey": "!security find-generic-password -ws 'anthropic'"
The apiKey field now supports three formats:
- !command - executes shell command, uses trimmed stdout
- ENV_VAR_NAME - uses environment variable value
- literal - uses value directly
fixes#697
* feat(coding-agent): cache API key command results for process lifetime
Shell commands (! prefix) are now executed once and cached. Environment
variables and literal values are not cached, so changes are picked up.
Addresses review feedback on #762.
---------
Co-authored-by: Mario Zechner <badlogicgames@gmail.com>