Introduction
Pi (@earendil-works/pi-coding-agent) is an open-source terminal coding agent that exposes four tools to the model it's connected to: read (read files), write (create or overwrite files), edit (patch files), and bash (run shell commands). The agent runs directly in your project directory — no Docker layer, no build step, no IDE integration required. Every model call goes exclusively to whichever backend you configure, and nowhere else.
Pi connects to any OpenAI-compatible API endpoint via a models.json config file. This makes it straightforward to wire it up to Crusoe Managed Inference: once configured, all of Pi's model traffic routes to your Crusoe account, keeping your prompts, code context, and outputs within the Crusoe platform rather than through a third-party provider.
This guide walks you through installing Pi and configuring it to use Crusoe Managed Inference, so you can run models like Nemotron 3 Ultra 550B as your coding agent backend directly from the terminal.
ℹ️ Note: Pi is third-party, community-maintained open-source software. It is not built, maintained, or endorsed by Crusoe. Review the package and its source before installing. Crusoe support covers the Managed Inference endpoint — the API, your API keys, and the
baseUrl— not the Pi client itself. The steps below were validated against@earendil-works/pi-coding-agent; other similarly named packages may behave differently.
Prerequisites
- Active Crusoe Cloud Account With Access to Managed Inference
- macOS or Linux Machine With a Terminal
- Node.js 18 or Later
- Access to the Crusoe Cloud Console at https://console.crusoecloud.com
Instructions
Step 1: Install Pi
Run the following command to install Pi globally via npm:
npm install -g --ignore-scripts @earendil-works/pi-coding-agent
⚠️ Warning: The
--ignore-scriptsflag prevents npm from running any postinstall scripts bundled in the package — a common attack vector with third-party CLI tools. Keep this flag unless you have a specific reason to allow install scripts.
💡 Tip: To keep the steps below behaving as documented — particularly the
/loginflow in Step 5 — pin to the version you validated rather than always pulling latest:npm install -g --ignore-scripts @earendil-works/pi-coding-agent@<VERSION>. Future releases may change the authentication flow.
Verify the installation:
pi --help
ℹ️ Note: Pi requires Node.js 18 or later. If installation fails, check your Node version with
node --versionand upgrade if needed. Visit nodejs.org or use nvm.
Step 2: Create a Managed Inference API Key
- Log in to the Crusoe Cloud Console.
- In the top right, click Apps and select Intelligence Foundry.
- In the left navigation, select API Keys.
- Click Create API Key in the top right.
- Give the key a name (e.g.
pi-dev) and click Create. - Copy the key immediately — it is only shown once.
⚠️ Warning: Treat this key like a password. Do not commit
models.jsonto source control if it contains the key directly. Add~/.pi/to your global gitignore as a precaution.
Step 3: Export Your API Key as an Environment Variable
Add the following to your shell profile (~/.zshrc, ~/.bashrc, or equivalent):
export CRUSOE_API_KEY="your-api-key-here"
Reload your profile:
source ~/.zshrc # or source ~/.bashrc
Confirm the variable is set:
echo $CRUSOE_API_KEY
⚠️ Warning: The command above echoes your API key in plaintext to the terminal. Avoid running this in a shared terminal or screen recording. As an alternative, use:
[ -n "$CRUSOE_API_KEY" ] && echo "Set" || echo "Not set"
Step 4: Configure Pi to Use Crusoe
Create or open ~/.pi/agent/models.json and add the following:
{
"providers": {
"crusoe": {
"baseUrl": "https://api.inference.crusoecloud.com/v1",
"api": "openai-completions",
"apiKey": "your-crusoe-api-key-here",
"defaultHeaders": {
"Accept": "text/event-stream"
},
"compat": {
"supportsDeveloperRole": false,
"supportsResponseFormat": false,
"supportsTools": true,
"supportsStreamOptions": false,
"supportsMaxCompletionTokens": false,
"supportsStore": false,
"supportsReasoningEffort": true
},
"models": [
{
"id": "nvidia/NVIDIA-Nemotron-3-Ultra-550B",
"name": "Nemotron 3 Ultra 550B",
"contextWindow": 262144,
"maxTokens": 8192,
"reasoning": true,
"modality": "text",
"features": ["tool_calling", "structured_outputs", "json_mode", "reasoning", "prompt_cache", "seed"]
},
{
"id": "openai/gpt-oss-120b",
"name": "GPT-OSS 120B",
"contextWindow": 131072,
"maxTokens": 8192,
"reasoning": true,
"modality": "text",
"features": ["tool_calling", "structured_outputs", "json_mode", "reasoning", "prompt_cache", "seed"]
}
]
}
}
}
Replace your-crusoe-api-key-here with the API key generated in Step 2. See the models.json Configuration Reference section below for a full breakdown of each field.
💡 Tip: To list all models available in your Managed Inference account, run:
curl https://api.inference.crusoecloud.com/v1/models \ -H "Authorization: Bearer $CRUSOE_API_KEY" | jq '.data[].id'
Step 5: Authenticate in the Pi Terminal
Pi supports two authentication methods. For Crusoe Managed Inference, use the API key method — Crusoe does not use subscription-based login.
Method 1: API Key in models.json (recommended for Crusoe)
Set the apiKey field in ~/.pi/agent/models.json directly (as shown in Step 4). Pi reads this value on launch and uses it for all requests to the configured provider. No in-terminal login step is needed.
⚠️ Warning: Pi resolves credentials in this priority order: 1) the
--api-keyCLI flag, 2)~/.pi/agent/auth.json, 3) environment variables, 4) theapiKeyfield inmodels.json. This means a key stored by/logininauth.jsontakes precedence over theapiKeyinmodels.json. If you previously ran/loginand later change the key inmodels.json, Pi will keep using the staleauth.jsonvalue silently. Pick one method, or deleteauth.jsonif you switch to themodels.jsonapproach.
Method 2: Interactive Login via /login → Use an API key
If you prefer not to store the key in models.json, you can authenticate interactively from inside a Pi session. Start Pi and run the login command:
pi /login
Pi displays the authentication method selection:
/login ? Select authentication method (use arrow keys) > Use a subscription Use an API key
Select Use an API key. Pi then shows the provider list:
? Select a provider (use arrow keys) anthropic openai > crusoe ✓ configured google
Select crusoe. Pi prompts for the key:
Login to crusoe Enter API key: ________________________
Enter your Crusoe Managed Inference API key when prompted. Once authenticated, credentials are written to ~/.pi/agent/auth.json and loaded automatically on every subsequent launch — no environment variable or manual key entry needed going forward.
ℹ️ Note:
auth.jsonstores credentials in plaintext. Do not commit it to source control, and restrict file permissions to your user:chmod 600 ~/.pi/agent/auth.json.
To verify which provider and model are active in a running session, type /model. This lists your configured models and lets you switch between them mid-session.
Step 6: Launch Pi
Navigate to your project directory and start Pi:
cd /your/project pi
Pi loads your models.json (and auth.json if present) and connects to Crusoe Managed Inference. Use /model to select or switch models at any point during the session.
Example
A developer working on a Python data pipeline wants to use Pi for code generation and debugging without sending any source code to a third-party provider. They configure Pi to use NVIDIA-Nemotron-3-Ultra-550B on Crusoe, with DeepSeek-V4-Pro and gpt-oss-120b available as alternatives.
Their ~/.pi/agent/models.json:
{
"providers": {
"crusoe": {
"baseUrl": "https://api.inference.crusoecloud.com/v1",
"api": "openai-completions",
"apiKey": "crusoe",
"defaultHeaders": {
"Accept": "text/event-stream"
},
"compat": {
"supportsDeveloperRole": false,
"supportsResponseFormat": false,
"supportsTools": true,
"supportsStreamOptions": false,
"supportsMaxCompletionTokens": false,
"supportsStore": false,
"supportsReasoningEffort": true
},
"models": [
{
"id": "nvidia/NVIDIA-Nemotron-3-Ultra-550B",
"name": "Nemotron 3 Ultra 550B",
"contextWindow": 262144,
"maxTokens": 8192,
"reasoning": true,
"modality": "text",
"features": ["tool_calling", "structured_outputs", "json_mode", "reasoning", "prompt_cache", "seed"]
},
{
"id": "deepseek-ai/DeepSeek-V4-Pro",
"name": "DeepSeek V4 Pro",
"contextWindow": 1048576,
"maxTokens": 8192,
"reasoning": true,
"modality": "text",
"features": ["tool_calling", "structured_outputs", "json_mode", "reasoning", "prompt_cache", "seed"]
},
{
"id": "openai/gpt-oss-120b",
"name": "GPT-OSS 120B",
"contextWindow": 131072,
"maxTokens": 8192,
"reasoning": true,
"modality": "text",
"features": ["tool_calling", "structured_outputs", "json_mode", "reasoning", "prompt_cache", "seed"]
}
]
}
}
}Replace your-crusoe-api-key-here with the API key generated in Step 2.
They launch Pi from their repo root, use /model to select Nemotron 3 Ultra 550B for the main session, and switch to DeepSeek-V4-Pro for quick edits mid-session.
models.json Configuration Reference
The ~/.pi/agent/models.json file defines every model provider Pi can connect to. Each entry under providers is an independently configured backend. You can define multiple providers and switch between them at runtime using /model.
-
providers(object, required) — Top-level map of named provider configurations. The key (e.g.crusoe) is an arbitrary label used internally by Pi. -
baseUrl(string, required) — Base URL of the OpenAI-compatible API endpoint. For Crusoe:https://api.inference.crusoecloud.com/v1. Must end with/v1— no trailing slash. -
api(string, required) — API protocol. Set toopenai-completionsfor any OpenAI-compatible endpoint including Crusoe Managed Inference. -
apiKey(string, required) — Authentication token sent as a Bearer header with every request. For Crusoe, this is the API key generated in Intelligence Foundry. Can be left empty if credentials are managed via/loginandauth.json. -
models(array, required) — List of models to expose from this provider. Each entry requires anidand aninputarray. -
models[].id(string, required) — The model name sent verbatim to the API as themodelparameter. Must match the exact identifier used by your Crusoe Managed Inference endpoint (verify with the curl command in Step 4). Pi imposes no format of its own — values likeopenai/gpt-oss-120bare whatever Crusoe's API expects. -
models[].input(array, required) — Supported input modalities. Use["text"]for text-only models or["text", "image"]for multimodal models.
Troubleshooting
| Problem | Fix |
|---|---|
| 401 authentication error | Run echo $CRUSOE_API_KEY to confirm the variable is set. Verify the key in models.json matches what was issued in the Console. If using /login, check that ~/.pi/agent/auth.json exists and was written successfully. |
| Model not found / 404 | Confirm the id field matches the exact model identifier in your Managed Inference account. Use the curl command in Step 4 to list available model IDs. |
| Connection refused or timeout | Confirm baseUrl ends with /v1 with no trailing slash. Test connectivity with: curl https://api.inference.crusoecloud.com/v1/models -H "Authorization: Bearer $CRUSOE_API_KEY"
|
pi command not found |
Ensure the npm global bin directory is in your PATH. Run npm root -g to find the global modules directory, then add the corresponding bin to your shell profile (e.g. export PATH="$(npm root -g)/../bin:$PATH"). |
Model doesn't appear in /model list |
Confirm ~/.pi/agent/models.json is valid JSON and saved at the correct path. Restart Pi after any config changes. |
/login credentials not persisting |
Re-run /login inside Pi, select Use an API key, and re-enter your key. Check that ~/.pi/agent/auth.json exists and is readable (ls -la ~/.pi/agent/). |
| Auth works but uses the wrong/old key |
auth.json takes precedence over the apiKey in models.json. If you have a stale key from a previous /login, delete ~/.pi/agent/auth.json (or re-run /login with the correct key) so the intended credential is used. |