25 Development
25.1 Setup
25.1.1 Prerequisites
- Node.js (latest LTS recommended)
- npm or compatible package manager (pnpm, yarn, bun)
- Git
25.1.2 Clone the Repository
git clone https://github.com/earendil-works/pi-mono.git
cd pi-mono25.1.3 Install Dependencies
npm install --ignore-scriptsThe --ignore-scripts flag disables dependency lifecycle scripts during install, consistent with how Pi is distributed to end users.
25.1.4 Build
npm run build25.1.5 Run Locally
After building, use the test script to run your local build:
/path/to/pi-mono/pi-test.shOr link the package globally:
cd pi-mono
npm link
pi --version25.1.6 Development Workflow
# Watch mode for automatic rebuilds
npm run dev
# Run tests
npm test
# Lint
npm run lint
# Type check
npm run typecheck25.2 Forking and Rebranding
Pi is designed to be forkable. You can create your own distribution with a different name, configuration directory, and branding.
25.2.1 What to Change
When forking Pi, change these fields in package.json:
| Field | Description | Example |
|---|---|---|
name |
Package name | @myorg/my-pi |
bin |
CLI command name | my-pi |
piConfig.configDir |
Config directory name | .my-pi |
25.2.2 package.json Example
Original:
{
"name": "@earendil-works/pi-coding-agent",
"bin": {
"pi": "./dist/cli.js"
},
"piConfig": {
"configDir": ".pi"
}
}Forked:
{
"name": "@myorg/my-coding-agent",
"bin": {
"my-pi": "./dist/cli.js"
},
"piConfig": {
"configDir": ".my-pi"
}
}25.2.3 Config Directory
The configDir field in piConfig controls where Pi looks for configuration files:
Default (~/.pi/agent/) |
Forked (~/.my-pi/agent/) |
|---|---|
settings.json |
settings.json |
auth.json |
auth.json |
sessions/ |
sessions/ |
extensions/ |
extensions/ |
skills/ |
skills/ |
prompts/ |
prompts/ |
themes/ |
themes/ |
models.json |
models.json |
Project-local config also changes:
Default (.pi/) |
Forked (.my-pi/) |
|---|---|
settings.json |
settings.json |
extensions/ |
extensions/ |
skills/ |
skills/ |
prompts/ |
prompts/ |
themes/ |
themes/ |
25.2.4 Binary Name
The bin field in package.json controls the CLI command name. After forking:
npm install -g --ignore-scripts @myorg/my-coding-agent
my-pi --version25.2.5 Forking Checklist
When forking, sessions and settings are NOT shared between Pi and your fork. Each uses its own config directory. This is intentional—it allows Pi and forks to coexist on the same machine.
25.3 Path Resolution
Pi resolves configuration paths in a specific order:
25.3.1 Config Directory Resolution
1. CLI flag (--config-dir /path/to/config)
2. package.json piConfig.configDir
3. Environment variable (PI_CONFIG_DIR)
4. Default: ~/.pi/agent/
25.3.2 Working Directory Resolution
1. CLI flag (--cwd /path/to/project)
2. process.cwd()
25.3.3 Session Directory Resolution
1. CLI flag (--session-dir /path/to/sessions)
2. Settings: sessionDir
3. <configDir>/sessions/
25.3.4 Extension Path Resolution
Extensions are loaded from multiple paths, resolved in order:
1. CLI flags (-e /path/to/extension.ts)
2. Settings: extensions array
3. <configDir>/extensions/*.ts (global)
4. <configDir>/extensions/*/index.ts (global, directory)
5. <cwd>/.pi/extensions/*.ts (project-local)
6. <cwd>/.pi/extensions/*/index.ts (project-local, directory)
7. Package extensions (from installed pi packages)
25.4 Debug Command
Pi includes a debug command for troubleshooting:
pi --debugThis enables verbose logging, showing:
- Configuration file paths
- Extension loading order
- Model resolution
- API request/response details
- Tool execution details
- Session file operations
25.4.1 Debug Specific Areas
# Debug model resolution
pi --debug models --list-models
# Debug extensions
pi --debug extensions --verbose
# Debug session
pi --debug session --continue25.5 Testing
25.5.1 Running Tests
# All tests
npm test
# Specific test file
npm test -- test/extensions.test.ts
# Watch mode
npm test -- --watch
# Coverage
npm test -- --coverage25.5.2 Test Structure
Tests are organized by module:
test/
├── extensions/
│ ├── events.test.ts
│ ├── tools.test.ts
│ └── commands.test.ts
├── sessions/
│ ├── tree.test.ts
│ └── compaction.test.ts
├── models/
│ └── resolution.test.ts
├── tools/
│ ├── read.test.ts
│ ├── write.test.ts
│ └── bash.test.ts
└── cli/
├── args.test.ts
└── modes.test.ts
25.5.3 Writing Tests
import { describe, test, expect } from "vitest";
import { createAgentSession } from "../src/index";
describe("AgentSession", () => {
test("should create a session with default settings", async () => {
const session = await createAgentSession({
model: "test-model",
provider: "test",
apiKey: "test-key",
cwd: "/tmp",
});
expect(session.getModel()).toBe("test-model");
expect(session.getActiveTools()).toContain("read");
await session.shutdown();
});
});25.6 Project Structure
pi-mono/
├── packages/
│ ├── pi-coding-agent/ # Main package
│ │ ├── src/
│ │ │ ├── cli/ # CLI entry point
│ │ │ ├── agent/ # Agent loop and session
│ │ │ ├── tools/ # Built-in tools
│ │ │ ├── extensions/ # Extension system
│ │ │ ├── sessions/ # Session management
│ │ │ ├── models/ # Model resolution
│ │ │ ├── providers/ # Provider implementations
│ │ │ ├── tui/ # Terminal UI
│ │ │ ├── rpc/ # RPC mode
│ │ │ ├── json/ # JSON mode
│ │ │ └── sdk/ # SDK exports
│ │ ├── test/ # Tests
│ │ ├── examples/ # Example extensions
│ │ └── package.json
│ ├── pi-ai/ # AI utilities
│ ├── pi-tui/ # TUI component library
│ └── shared/ # Shared types and utilities
├── docs/ # Documentation source
├── scripts/ # Build and release scripts
├── pi-test.sh # Local test runner
└── package.json # Workspace root
25.6.1 Key Directories
| Directory | Description |
|---|---|
packages/pi-coding-agent/src/cli/ |
CLI argument parsing and entry point |
packages/pi-coding-agent/src/agent/ |
Core agent loop and session management |
packages/pi-coding-agent/src/tools/ |
Built-in tool implementations (read, write, edit, bash) |
packages/pi-coding-agent/src/extensions/ |
Extension loading, event system, API |
packages/pi-coding-agent/src/tui/ |
Terminal rendering and input handling |
packages/pi-coding-agent/src/sdk/ |
Public SDK API exports |
packages/pi-ai/ |
Shared AI utilities, types, API clients |
packages/pi-tui/ |
Reusable TUI component library |
25.7 Contributing
25.7.1 Development Guidelines
- Follow the existing code style (enforced by linter)
- Add tests for new features
- Update documentation for API changes
- Keep extensions and core separate—new features should be extensions when possible
- Maintain backward compatibility for SDK and extension APIs
25.7.2 Pull Request Process
- Fork the repository
- Create a feature branch
- Write tests for your changes
- Ensure all tests pass:
npm test - Ensure linting passes:
npm run lint - Submit a pull request
25.7.3 Reporting Issues
Use the GitHub issue tracker to report bugs or request features. For security issues, follow the repository’s Security Policy instead of opening a public issue.
Pi is open source under the MIT License. Contributions are welcome. The project values keeping the core small—feature requests that can be implemented as extensions are encouraged as such.