PHPackages                             papi-ai/ingest - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. papi-ai/ingest

ActiveLibrary

papi-ai/ingest
==============

Deterministic repository ingestion for PapiAI: render a codebase within a token budget

v0.15.0(today)012↑2650%2MITPHPPHP ^8.2CI passing

Since Jul 27Pushed todayCompare

[ Source](https://github.com/papi-ai/ingest)[ Packagist](https://packagist.org/packages/papi-ai/ingest)[ RSS](/packages/papi-ai-ingest/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (4)Versions (2)Used By (2)

papi-ai/ingest
==============

[](#papi-aiingest)

Deterministic repository ingestion for [PapiAI](https://papi-ai.org): turn a codebase into the largest useful picture that fits a token budget.

Agent apps keep hand-rolling tree scans and file reads, which gives the model shallow context and gives you an unbounded token bill. This is that job done once: discover, filter, rank, and render, with nothing hidden from the reader.

**Deterministic by definition.** No model is called during ingestion. The same repository state and the same request always produce the same digest, which is what makes the fingerprint worth caching against.

Install
-------

[](#install)

```
composer require papi-ai/ingest
```

Usage
-----

[](#usage)

```
use PapiAI\Ingest\Depth;
use PapiAI\Ingest\IngestRequest;
use PapiAI\Ingest\NativeIngestor;

$digest = (new NativeIngestor())->ingest(new IngestRequest(
    source: '/path/to/repo',
    depth: Depth::Full,
    tokenBudget: 4000,
));

echo $digest->toPrompt();     // tree, then as many files as fit, then what was left out
echo $digest->fingerprint;    // cache key: moves when included content moves, and not otherwise
```

### Depth

[](#depth)

DepthWhat each file contributes`Depth::Tree`Nothing. Paths only, the cheapest orientation`Depth::Api`A symbol block: what it declares, extends, and reaches for`Depth::Full`The whole file`Api` is the level agent consumers usually want: the entire system stays legible for a fraction of `Full`'s tokens. It needs a symbol extractor for the language, so install [`papi-ai/ingest-php-symbols`](https://github.com/papi-ai/ingest-php-symbols) and pass it in:

```
$ingestor = new NativeIngestor(new PhpSymbolExtractor());
$digest = $ingestor->ingest(new IngestRequest($repo, Depth::Api));
```

Asking for `Api` without an extractor throws. It will not quietly hand you a `Tree` and let you wonder where the symbols went.

### Prioritising what survives the budget

[](#prioritising-what-survives-the-budget)

The budget renders the tree first, then files in priority order, skipping any that do not fit so one huge file cannot starve everything below it. A prioritiser is how you say what matters right now:

```
$recent = time() - 86400;

new IngestRequest(
    source: $repo,
    depth: Depth::Api,
    tokenBudget: 4000,
    prioritiser: fn (IngestedFile $file): float => $file->mtime > $recent ? 10.0 : 0.0,
);
```

Map plus heat: the whole shape of the system, with the parts you are working on rendered first.

### Rendering

[](#rendering)

CallBudget used`toPrompt()`The one the request carried, or everything if it carried none`toPromptWithin(int $budget)`This one, overriding the request`toFullPrompt()`None. Everything, whatever the request saidWhatever gets dropped is named in a trailer line, always. A prompt that quietly omits half a repository is worse than one that admits it, because the reader cannot tell the difference.

Discovery
---------

[](#discovery)

Inside a git repository, discovery defers to git itself (`git ls-files --cached --others --exclude-standard`): tracked files plus untracked ones that are not ignored. That is faster than walking and exactly right about `.gitignore`, including nested ignore files and global excludes, which a hand-rolled matcher never quite is. Outside a repository, or with `respectGitignore: false`, it walks the directory and never follows symlinks.

`vendor/`, `node_modules/`, `.git/`, lock files, `.env*` and binaries are excluded by default. Binaries and oversized files still appear in the tree, with a note saying why they were not read.

Interchange
-----------

[](#interchange)

File blocks use gitingest's framing (a 48-character rule, then `FILE: `), and the tree opens with `Directory structure:`, so digests are interchangeable with what people already paste into models.

Related packages
----------------

[](#related-packages)

PackageAdds`papi-ai/ingest-php-symbols``Depth::Api` for PHP, via nikic/php-parser`papi-ai/ingest-gitingest`Remote repositories, via the gitingest CLILicense
-------

[](#license)

MIT, Marcello Duarte

###  Health Score

39

—

LowBetter than 84% of packages

Maintenance100

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity35

Early-stage or recently created project

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

0d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/70713?v=4)[md](/maintainers/md)[@md](https://github.com/md)

---

Top Contributors

[![MarcelloDuarte](https://avatars.githubusercontent.com/u/144535?v=4)](https://github.com/MarcelloDuarte "MarcelloDuarte (1 commits)")

###  Code Quality

TestsPest

Static AnalysisPsalm

Code StylePHP CS Fixer

Type Coverage Yes

### Embed Badge

![Health badge](/badges/papi-ai-ingest/health.svg)

```
[![Health](https://phpackages.com/badges/papi-ai-ingest/health.svg)](https://phpackages.com/packages/papi-ai-ingest)
```

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
