# ReadSeek

`readseek` turns source files, images, and PDFs into compact structured context for
scripts, editors, and coding agents. Source output includes stable `LINE:HASH`
anchors, symbol maps, parse diagnostics, AST matches, definitions, references,
and verified rename plans.

## Install

Choose one installation method:

```sh
npm install -g @jarkkojs/readseek  # Node 18+
cargo install readseek             # Rust 1.89+
make install                       # build this checkout and install the CLI + man page
```

`make install` supports `PREFIX` and `DESTDIR`. Prebuilt npm binaries are
available for macOS ARM64, Linux ARM64/x64, and Windows x64; Linux builds are
statically linked with musl.

## Integrations

| Host | Package | Install |
| --- | --- | --- |
| Pi | [pi-readseek](packages/pi-readseek/README.md) | `pi install npm:pi-readseek` |
| OpenCode | [opencode-readseek](packages/opencode-readseek/README.md) | Add `opencode-readseek` to `opencode.json` |
| Claude Code | [claude-readseek](packages/claude-readseek/README.md) | Add this repository as a `/plugin` marketplace source |
| Vim | [readseek.vim](doc/readseek.txt) | Install this repository with a plugin manager, then run `:ReadSeekInstall` |

## CLI tour

### Read and inspect

```sh
readseek detect src/main.rs
readseek read src/main.rs:10 --end 20
readseek map src/main.rs
readseek symbol src/main.rs:run --name
readseek identify src/main.rs:42 --column 8
readseek check src/main.rs
```

Source reads emit records such as `42:a1b|let value = parse(input);`. The line
number locates the text; the short hash rejects most stale edits while tolerating
whitespace-only changes.

### Search and navigate

```sh
readseek def src run --language rust --format plain
readseek refs src run --language rust --format plain
readseek refs src/main.rs run --scope --line 42 --column 8
readseek search src 'fn $NAME() { $$$BODY }' --language rust
```

`def`, `refs`, and `search` accept a file or directory. In a Git work tree,
directory searches include tracked/indexed and untracked non-ignored files by
default. Use `--git cached`, `--git others`, or both to restrict the set;
`ignored` requires `others`.

### Rename

A rename is a dry run unless `--apply` is present:

```sh
readseek rename src/main.rs --line 42 --column 8 --to renamed
readseek rename src/main.rs --line 42 --column 8 --to renamed --apply
readseek rename src/main.rs --line 42 --to renamed --workspace . --apply
```

Rename plans report conflicts and hash-verified edits. Workspace mode extends the
plan beyond the cursor file.

### Global options and stdin

Global options must precede the command:

```sh
readseek --output result.json detect src/main.rs
readseek --readseek-dir /tmp/project-index view report.pdf
```

Prefix a target with `stdin:` to analyze an unsaved buffer while retaining a
path for language detection and cursor addressing. This works with `detect`,
`read`, `map`, `check`, `symbol`, and `identify`:

```sh
printf '%s\n' 'fn main() {}' | readseek identify stdin:scratch.rs:1 --column 4
```

## Images and PDFs

`detect` reports image metadata and PDF page counts. An image read returns a
bounded base64 payload by default. Select local analysis explicitly:

```sh
readseek read photo.jpg --vision-mode caption
readseek read photo.jpg --vision-mode objects
readseek read scan.png --vision-mode ocr --vision-level high
readseek read photo.jpg --vision-mode all
```

Vision modes are `none`, `caption`, `objects`, `ocr`, and `all`. Analysis starts
at the `low` level; use `medium` or `high` only when more detail is needed.

PDF reads return page-tagged Markdown plus embedded images. `--page` selects a
page, and `--vision-mode` applies to its images:

```sh
readseek read report.pdf --page 3 --vision-mode ocr
readseek init
readseek view report.pdf
readseek view report.pdf --page 3 --outline
```

`view` creates or reuses a structural PDF index and can narrow it by page, node,
kind, or depth. Line/hash suffixes and source range/language options do not apply
to images or PDFs.

Image analysis runs locally on the CPU with
[Qwen3-VL-2B-Instruct](docs/models/qwen3-vl-2b-instruct.md). Its model files are
downloaded and checksum-verified on first use.

## Cache layout

`readseek init [path]` creates `.readseek/` and refreshes its source indexes.
Commands discover that directory by walking up from the target; use
`--readseek-dir` to select one explicitly.

| Path | Contents |
| --- | --- |
| `.readseek/maps/` | Content-addressed source maps |
| `.readseek/def-index/` | Definition index |
| `.readseek/documents/` | PDF indexes and extracted assets |
| `.readseek/vision/` | Level-specific image analysis results |
| User cache `readseek/models/` | Downloaded vision model files |

## Development

```sh
cargo test
cargo clippy --all-targets
cargo fmt --check
```

Integration-specific checks:

```sh
(cd packages/pi-readseek && npm run typecheck && npm test)
(cd packages/opencode-readseek && bun run typecheck && bun test)
(cd packages/claude-readseek && npm run typecheck && npm test)
vim -Nu NONE -n -i NONE -es -S test/readseek.vim
```

## Reference

Run `readseek --help` or `readseek <command> --help`. To read the complete local
manual:

```sh
man ./man/man1/readseek.1
```

## License

- Native `readseek`: LGPL-2.1-or-later
- `@jarkkojs/readseek` npm wrapper: Apache-2.0 AND LGPL-2.1-or-later
- `pi-readseek`, `opencode-readseek`, and `claude-readseek`: Apache-2.0
- `readseek.vim`: MIT

### Third-party attribution

- Qwen3-VL-2B-Instruct: Apache-2.0. Model files are downloaded at runtime and
  are not distributed with ReadSeek.
- [Dwarf Seek 4](https://github.com/antirez/ds4): MIT. ReadSeek's Q4_K and Q6_K
  block decoding and dot-product code includes derived work.
