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-mono

25.1.3 Install Dependencies

npm install --ignore-scripts

The --ignore-scripts flag disables dependency lifecycle scripts during install, consistent with how Pi is distributed to end users.

25.1.4 Build

npm run build

25.1.5 Run Locally

After building, use the test script to run your local build:

/path/to/pi-mono/pi-test.sh

Or link the package globally:

cd pi-mono
npm link
pi --version

25.1.6 Development Workflow

# Watch mode for automatic rebuilds
npm run dev

# Run tests
npm test

# Lint
npm run lint

# Type check
npm run typecheck

25.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 --version

25.2.5 Forking Checklist

Note

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 --debug

This 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 --continue

25.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 -- --coverage

25.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

  1. Follow the existing code style (enforced by linter)
  2. Add tests for new features
  3. Update documentation for API changes
  4. Keep extensions and core separate—new features should be extensions when possible
  5. Maintain backward compatibility for SDK and extension APIs

25.7.2 Pull Request Process

  1. Fork the repository
  2. Create a feature branch
  3. Write tests for your changes
  4. Ensure all tests pass: npm test
  5. Ensure linting passes: npm run lint
  6. 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.

Tip

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.