Pi runtime extension package that integrates Morph into Pi as real tools, commands, hooks, and compaction behavior, with file-based configuration for consistent setup.
This package is not just a prompt snippet or a thin skill wrapper. It installs as a normal Pi package and runs an active extension that registers Morph tools, lifecycle hooks, status commands, and Morph-first routing guidance.
pi-morphllm-plugin makes Morph a practical part of everyday Pi coding sessions.
Use it when you want Pi to:
- apply larger or multi-location edits through
morph_fastapply - search the current workspace with natural language through
warpgrep_codebase_search - inspect public GitHub repositories through
warpgrep_github_search - compact long conversations with Morph before falling back to Pi
- keep Morph configuration in one JSON file instead of scattered runtime environment variables
In short, this plugin turns Morph into a real Pi runtime integration instead of a manual workflow.
This plugin is a good fit if you use Pi regularly and want Morph to be part of your default workflow, especially for:
- refactoring or editing larger files safely
- searching unfamiliar codebases with natural language
- inspecting public GitHub repositories without cloning them locally
- reducing long session context with Morph compaction
- standardizing Morph setup across projects with file-based config
If you only need a one-off note about Morph or a manual prompt pattern, this package is probably more than you need.
morph_fastapplyfor Fast Apply style file merging with dry-run previewwarpgrep_codebase_searchfor local exploratory code searchwarpgrep_github_searchfor public GitHub source lookup- Morph compaction integration for large conversations
- File-based
baseUrl/baseApiendpoint configuration - Single-key and multiple-key Morph API configuration
- Prompt-level Morph-first routing guidance without blocking native Pi tools
pi install npm:pi-morphllm-pluginThis is the main installation path and does not require cloning the repository.
pi -e npm:pi-morphllm-pluginThis loads the package temporarily for the current Pi run without adding it to your installed package list.
pi -e .This loads the package manifest from package.json, so Pi discovers both the Morph extension and the bundled prompt resource.
pi -e ./extensions/morph/index.jsUse the extension entrypoint directly only when you intentionally want to test the extension file by itself. That path does not load the package prompt resource from prompts/morph-tools.md.
Pi Morph uses guidance, not runtime blocking.
- Small exact replacements should use native
edit. - Brand new files should use native
write. - Large files, multi-location edits, and whitespace-sensitive merges should use
morph_fastapply. - If the model chooses a workable native tool anyway, the extension allows it and continues instead of blocking.
Pi Morph uses JSON config files only.
Config lookup order:
~/.pi/agent/morph.jsonas the default global Pi config.pi/morph.jsonin the current projectmorph.config.jsonin the current project
The recommended setup is global config in ~/.pi/agent/morph.json.
Pi Morph auto-creates that file on first runtime load when no existing Morph config is found. Installing the package alone does not create it; the extension must actually be loaded by Pi.
A repo example is available at .pi/morph.json.example.
You can also create the global config manually:
mkdir -p ~/.pi/agent
cp .pi/morph.json.example ~/.pi/agent/morph.jsonExample config:
{
"apiKey": "sk-...",
"editEnabled": true,
"warpgrepEnabled": true,
"warpgrepGithubEnabled": true,
"autoCompactEnabled": true,
"routing": {
"editMode": "force",
"codebaseSearchMode": "force",
"githubSearchMode": "force",
"fallbackToNativeTools": true
},
"compactContextThreshold": 0.7,
"compactPreserveRecent": 1,
"compactRatio": 0.3,
"timeoutMs": 30000,
"warpGrepTimeoutMs": 60000,
"compactTimeoutMs": 60000
}Pi Morph also supports rotation across multiple Morph API keys.
Set apiKey to "multiple", point apiKeyFile at a text file, and choose an apiKeyStrategy.
Only add baseUrl when you want to use a custom Morph-compatible endpoint.
{
"apiKey": "multiple",
"apiKeyFile": "~/.pi/agent/morph.env",
"apiKeyStrategy": "round-robin"
}Example morph.env:
sk-key-1
sk-key-2
sk-key-3Supported strategies:
round-robin- rotate sequentially between configured keysrandom- choose a random configured key for each client call
The key file parser also ignores blank lines and # comments.
If a line contains pipe-delimited metadata like name|label|sk-key, Pi Morph uses the third field as the API key.
All runtime settings come from JSON config files only.
Routing config lives inside morph.json:
routing.editMode-prefer,strong, orforcefor prompt-level Morph-first edit guidance; default isforcerouting.codebaseSearchMode-prefer,strong, orforcefor prompt-level local WarpGrep guidance; default isforcerouting.githubSearchMode-prefer,strong, orforcefor prompt-level public GitHub WarpGrep guidance; default isforcerouting.fallbackToNativeTools- whentrue, Morph tool failures explicitly fall back to native Pi tools
Invalid routing mode strings automatically fall back to safe defaults:
routing.editMode->forcerouting.codebaseSearchMode->forcerouting.githubSearchMode->force
/morph_statusshows the loaded config path, API key status, live API probe result, SDK status, base URL, feature flags, routing mode state, and whether Morph-first guidance is active./morph_settingsopens a simple interactive menu for updating routing settings inmorph.json./morph_selftestruns end-to-end checks for the API probe, FastApply, local WarpGrep, GitHub WarpGrep, and compact using temporary files and sample queries./morph-compactis explicit and Morph-only: the manual command requires Morph compaction and reports a clear warning when compaction cannot run.- Automatic compaction is Morph-first when
autoCompactEnabledis enabled, then falls back to Pi if Morph cannot produce a result. - When
autoCompactEnabledisfalse, automatic compaction skips Morph entirely and leaves compaction to Pi.
Example /morph_status fields:
Morph plugin version: 0.1.7Morph config: ~/.pi/agent/morph.jsonMorph API key: configuredMorph API key source: single key,3 keys (round-robin), orkey file: ~/.pi/agent/morph.envdepending on your configurationMorph API live test: ok,failed (authentication error: ...),failed (request timeout: ...),failed (network/base URL error: ...), orskipped (...)Morph FastApply enabled: trueAuto compaction policy: Morph first, Pi fallbackManual /morph-compact policy: Morph requiredRouting edit mode: forceRouting codebase search mode: forceRouting GitHub search mode: forceMorph FastApply-first guidance active: trueMorph-first local search guidance active: trueMorph-first GitHub search guidance active: trueFallback to native tools: trueManual /morph-compactwill report a warning if there are no older messages available to compact.
/morph_status is the main summary view. Use /morph_settings when you want to change config interactively instead of editing JSON by hand. Reload the extension or session after credential or key-file changes so Morph clients are rebuilt with the new config. The footer also shows MorphLLM plus the loaded API key count, including the active strategy when multiple keys are configured.
morph_fastapplyhandles large or scattered edits in existing files using// ... existing code ...markers and supportsdry_runpreviews.warpgrep_codebase_searchanswers exploratory questions about the current workspace.warpgrep_github_searchsearches public GitHub repositories without cloning them locally.- Tool preference strength and fallback behavior are controlled by
routinginmorph.json. - In
forcemode, the extension applies the strongest Morph-first guidance in prompts and tool descriptions, but native tools remain available. - In
strongmode, the extension strongly prefers Morph tools for suitable cases. - In
prefermode, the extension gives a softer recommendation without changing tool availability.
Example morph_fastapply diff preview:
Example morph_fastapply preview call:
{
"target_filepath": "src/utils/math.ts",
"instructions": "I am adding input validation to the add function.",
"code_edit": "function add(a: number, b: number): number {\n if (typeof a !== 'number' || typeof b !== 'number') {\n throw new TypeError('Both arguments must be numbers.');\n }\n // ... existing code ...\n}",
"dry_run": true
}Use dry_run: true first when you want to inspect the diff preview without writing the file. Then rerun the same tool call with dry_run: false or omit it to apply the edit.
This package uses Pi extension hooks rather than command aliases alone.
session_startandsession_shutdownmanage Morph runtime status in the UI.before_agent_startinjects Morph routing hints into the system prompt based onroutingconfig.tool_callnormalizes tool input before execution.tool_resultadds Morph metadata such as provider and base URL.model_selecttracks the active model context window.session_before_compactruns Morph compaction before Pi falls back to its normal compactor, so automatic compaction stays Morph-first while preserving Pi as the safety net wheneverautoCompactEnabledis on.- When
autoCompactEnabledis off,session_before_compactskips Morph and leaves automatic compaction to Pi. /morph-compactuses the same hook-based path and always requires Morph compaction instead of silently falling back to Pi.
Clone the repository only if you want to work on the package itself.
Copy .pi/morph.json.example to .pi/morph.json or create ~/.pi/agent/morph.json, fill in apiKey, then run:
pi -e .Useful development modes:
pi -e .loads the full package manifest, extension, and bundled prompt resource.pi -e ./extensions/morph/index.jsloads only the extension entrypoint.npm testruns the package tests.
- Default Morph endpoint is
https://api.morphllm.com. - Set
baseUrlorbaseApiin JSON when you want a custom endpoint. - The package manifest in
package.jsonallows Pi to auto-discover the extension and prompt resource. - Automatic config creation happens on first runtime load, not during
pi install. - Automatic config creation only targets the global
~/.pi/agent/morph.jsonpath, never a project-local file by default.
Run:
npm test