---
slug: "arcanemachine-pi-read"
source_type: "readme"
source_url: "https://cdn.jsdelivr.net/gh/arcanemachine/pi-read@main/README.md"
repo: "https://github.com/arcanemachine/pi-read"
source_file: "README.md"
branch: "main"
---
# pi-read

<p align="center">
  <img src="https://raw.githubusercontent.com/arcanemachine/pi-read/main/logo.jpg" alt="pi-read logo" width="250" />
</p>

> Pi's native `read` tool with smaller, configurable text-output limits.

`pi-read` overrides Pi's built-in `read` tool while preserving its native line parameters, image processing, prompt metadata, and TUI behavior. It also adds optional byte paging and separate default and hard limits.

## Why Does This Project Exist?

Pi's built-in read tool truncates text at 2000 lines or 50KB. Those defaults can consume a significant part of the context window. This extension lets you use smaller limits globally or per project.

The extension defaults are 100 lines and 5KB.

## Why Would This Be Better as a First-Party Setting?

An extension cannot adjust the limits on Pi's existing read tool. It must replace the tool's execution function.

That creates unavoidable costs:

- To retain Pi's MIME sniffing, image conversion, resize isolation, model compatibility notes, and future image safeguards without copying private code, `pi-read` first executes the native reader as a probe. Text files are then read again with the configured limits.
- The `readTool` object is not part of Pi's settings API. It cannot appear in `/settings`, participate in SDK in-memory settings, or use Pi's settings validation and migration.
- Another extension can also override `read`; extension load order decides which implementation wins.
- Pi can evolve native text-read behavior independently, so this package must track those changes.

The clean first-party design would add `maxLines` and `maxBytes` to Pi's native `ReadToolOptions` and settings, then pass them to `truncateHead`.

## Features

- Configurable line and byte limits
- Global and trusted project settings with project precedence
- Native `path`, `offset`, and `limit` parameters
- Optional `offsetBytes` and `limitBytes` for exact byte paging
- Smaller defaults with larger configurable on-demand hard caps
- Exact line and byte continuation notices
- Native path normalization, including macOS screenshot filename variants
- Native image MIME sniffing, conversion, resizing, and model compatibility handling
- Native compact TUI rendering and syntax highlighting
- Dynamic tool description reflecting effective limits
- Reload support through Pi's `/reload`

## Installation

### From GitHub

```bash
pi install git:github.com/arcanemachine/pi-read
```

Update with:

```bash
pi update git:github.com/arcanemachine/pi-read
```

### From npm

```bash
pi install npm:@arcanemachine/pi-read
```

Update with:

```bash
pi update npm:@arcanemachine/pi-read
```

### From a Local Clone

```bash
git clone https://github.com/arcanemachine/pi-read.git
pi install /path/to/pi-read
```

No local dependency installation is required for normal use.

## Configuration

Add `readTool` to Pi's global or project `settings.json`:

```json
{
  "readTool": {
    "maxLines": 100,
    "maxBytes": 5120,
    "maxLimitLines": 2000,
    "maxLimitBytes": 51200
  }
}
```

| Option          | Type             | Default | Description                                   |
| --------------- | ---------------- | ------- | --------------------------------------------- |
| `maxLines`      | positive integer | `100`   | Default maximum complete lines per read       |
| `maxBytes`      | positive integer | `5120`  | Default maximum UTF-8 bytes per read          |
| `maxLimitLines` | positive integer | `2000`  | Hard cap for an explicit `limit` request      |
| `maxLimitBytes` | positive integer | `51200` | Hard cap for an explicit `limitBytes` request |

The first line or byte limit reached wins. Explicit `limit` and `limitBytes` values may request larger reads than the defaults but are clamped to the corresponding hard caps. Defaults must not exceed their hard caps.

### Settings Locations

- Global: `$PI_CODING_AGENT_DIR/settings.json`, or `~/.pi/agent/settings.json` by default
- Project: `.pi/settings.json`

Project settings override individual global `readTool` values. Project settings are read only when Pi trusts the project.

After editing settings, run `/reload`.

## Tool Parameters

`pi-read` uses the same parameters as Pi:

- `path`: relative or absolute file path
- `offset`: first line to read, 1-indexed
- `limit`: maximum requested line count; may increase the default up to `maxLimitLines`
- `offsetBytes`: first byte to read, 0-indexed; takes precedence over `offset`
- `limitBytes`: maximum requested byte count; may increase the default up to `maxLimitBytes`

Example continuation notice:

```text
[Showing lines 1-100 of 500. Use offset=101 to continue or offsetBytes=4970 for byte paging.]
```

Use the exact byte offset from the footer. Arbitrary byte offsets inside a UTF-8 character are rejected rather than returning corrupted text.

## Image Handling

All reads first pass through Pi's native reader. When Pi recognizes an image from its content, `pi-read` returns the native result unchanged. This retains:

- content-based MIME detection rather than extension-based detection
- PNG, JPEG, GIF, WebP, and BMP handling
- conversion to provider-supported formats
- isolated resize processing and size limits
- non-vision-model notices
- Pi's global `images.autoResize` and `images.blockImages` behavior

For text, the native probe result is discarded and the file is read with the configured limits. The extra text read is the main remaining implementation cost of not having a native limit option.

## TUI Rendering

The override returns Pi's standard `ReadToolDetails` with the actual `TruncationResult`. Pi's inherited read renderer therefore shows the configured line or byte limit when expanded.

Line-based calls keep Pi's native compact call rendering. Byte-based calls add a compact byte-range line so their non-native arguments remain visible in the tool box.

## Development

```bash
npm install --ignore-scripts --workspaces=false
npm run typecheck
npm run test
npm run build
npm run format
```
