PHPackages                             valb-mig/teller - 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. valb-mig/teller

ActiveLibrary

valb-mig/teller
===============

Scanner de docblocks @teller que mapeia regra de negocio documentada em PHP num call graph navegavel.

v1.0.0(today)10MITPHPPHP ^8.2CI passing

Since Jul 28Pushed todayCompare

[ Source](https://github.com/valb-mig/php.teller)[ Packagist](https://packagist.org/packages/valb-mig/teller)[ RSS](/packages/valb-mig-teller/feed)WikiDiscussions main Synced today

READMEChangelog (1)Dependencies (3)Versions (2)Used By (0)

Teller
======

[](#teller)

Scanner de docblocks `@teller` que mapeia regra de negócio documentada em PHP num call graph navegável — visual (cards + timeline + setas) e em texto (narrativa "Se X: chama Y — senão chama Z", pronta pra colar numa conversa com IA).

Baseado em call graph **real** (via [nikic/php-parser](https://github.com/nikic/php-parser)), não em estrutura estática tipo UML — segue quem chama quem de verdade, incluindo branches condicionais.

Por que
-------

[](#por-que)

Comentário de negócio junto do código sempre existiu. O que falta é uma forma de **navegar**essa documentação seguindo o fluxo real de execução, em vez de abrir arquivo por arquivo. O Teller lê a tag `@teller` (curadoria deliberada — não documenta tudo, só o que importa), monta o grafo de chamadas de verdade a partir da AST, e apresenta os dois num viewer só.

Instalação
----------

[](#instalação)

```
composer require --dev valb-mig/teller
```

Isso instala `vendor/bin/teller` e deixa `vendor/valb-mig/teller/public/` pronto pro viewer.

A tag `@teller`
---------------

[](#a-tag-teller)

Segue a convenção padrão de PHPDoc: primeira linha = título (summary), resto = descrição longa em **markdown** (parseado via `phpdocumentor/reflection-docblock`, o mesmo parser que o próprio phpDocumentor usa por baixo).

```
/**
 * @teller Calcula multa de atraso
 *
 * Aplica multa fixa de 2% quando o pagamento passa de 5 dias úteis do vencimento —
 * regra definida com o setor financeiro.
 *
 * - Sem atraso: valor original, sem alteração
 * - Com atraso: `valor * 1.02`
 */
public function calcularMulta(float $valor, int $diasAtraso): float
{
    ...
}
```

Funciona em docblock de classe/interface e de método. Também funciona **solto**, colado em qualquer statement de primeiro nível do corpo de um método (não desce em bloco aninhado) — útil pra documentar uma regra no meio do fluxo sem precisar extrair um método só pra isso:

```
public function executar(...): string
{
    /**
     * @teller Regra de atraso
     *
     * Acima de 90 dias, o boleto some pra negativação em vez de seguir o fluxo normal.
     */
    if ($diasAtraso > 90) {
        // ...
    }
}
```

A tag é **obrigatória** — sem ela, o Teller não mostra o método/comentário, de propósito: sem isso todo docblock técnico (`@param`, IDE helper, etc) viraria nó no grafo e a curadoria (o diferencial da ferramenta) se perde.

### Quando usar (e quando não usar)

[](#quando-usar-e-quando-não-usar)

Tagueia quando pelo menos um destes for verdade:

- **Regra de negócio de verdade** — decisão que veio de discussão de produto/jurídico/ comercial, não só "como" o código funciona tecnicamente.
- **Sintaxe complexa demais pra intenção ficar óbvia** — quem ler o código não vai entender o *porquê* só olhando a implementação.
- **Regra extensa** — vários passos/condições que só fazem sentido juntos, difícil de guardar na cabeça lendo linha por linha.
- **Nomenclatura não clara** — nome de variável/método/classe não deixa o significado óbvio (termo específico do domínio, abreviação, nome legado).

**Não tagueia**: getter/setter, CRUD simples, método técnico óbvio (formatação, cast, log), qualquer coisa auto-explicativa pelo nome.

Uso
---

[](#uso)

"Arquivo" é qualquer classe — usecase, service, repository, o que for. Nenhum tratamento especial por tipo, qualquer classe serve de ponto de partida.

```
# a partir de um arquivo (busca por nome, segue classes referenciadas via PSR-4)
vendor/bin/teller scan --file=CalculadoraJuros

# a partir de uma classe (FQCN)
vendor/bin/teller scan --class=App\\Services\\CalculadoraJuros

# codebase inteira sob um path (recomendado pra usar o command palette do viewer)
vendor/bin/teller scan --all --path=app

# limpar o banco local (storage/data.sqlite, nunca precisa ser commitado)
vendor/bin/teller clear

# exportar relatório HTML standalone do subgrafo de um arquivo
vendor/bin/teller export --file=CalculadoraJuros --out=relatorio.html
```

Por padrão a raiz do projeto escaneado é o diretório de onde você roda o comando — use `--project-root=/caminho` se precisar rodar de outro lugar.

Viewer
------

[](#viewer)

O viewer é estático — sem API, o browser lê o `.sqlite` direto via [sql.js](https://sql.js.org/) (WebAssembly). Qualquer servidor HTTP simples serve:

```
vendor/bin/teller scan --all --path=app
php -S localhost:8090 -t vendor/valb-mig/teller/public
```

Ou via Docker, se preferir não instalar PHP local pra isso:

```
docker run --rm -p 8090:8090 \
  -v "$(pwd)/vendor/valb-mig/teller/public:/var/www/html:ro" \
  -v "$(pwd)/vendor/valb-mig/teller/storage/data.sqlite:/var/www/html/data.sqlite:ro" \
  php:8.3-cli-alpine php -S 0.0.0.0:8090 -t /var/www/html
```

Abre em `http://localhost:8090`. Depois de rodar `scan` de novo (ou `clear` + `scan`), recarregue a página — o browser relê o arquivo a cada load.

Tela limpa, sem toolbar fixa: `Ctrl`/`Cmd` + `K` abre o command palette pra buscar arquivo/classe por nome, título `@teller` ou FQCN, ranqueado por quantas referências `@teller`tem na árvore de chamada — escolher um já carrega o trace (BFS client-side, sem bater no banco de novo).

Cada arquivo vira um **card** (nome do arquivo + título/descrição da classe — clicar no header abre no VSCode). Dentro, uma **timeline vertical** lista métodos e comentários soltos na ordem em que aparecem no arquivo: métodos mágicos (`__construct`, `__invoke`) em verde, métodos comuns em cinza, comentário solto em triângulo amarelo. Documentados aparecem destacados (título+descrição, cyan), sem tag aparecem apagados (só o nome). Cada item tem dropdown pra colapsar e abre um **modal** com mais detalhe (namespace, linha, fqcn, botão abrir no VSCode) ao clicar.

Cards ficam em **colunas por profundidade** (BFS a partir do arquivo escolhido — quem ele chama fica na coluna seguinte), com setas conectando o método/comentário exato que chama ao método exato chamado do outro lado, numeradas na ordem real do código-fonte. Canto inferior direito: zoom in/out/fit + exportar PNG (captura tudo via html2canvas).

Chamadas alternativas (`if`/`elseif`/`else` no código) convergem num **losango de decisão**entre origem e destinos — a origem aponta só pro losango (rótulo = número do passo, ex. "4"), o losango se abre pra cada braço (rótulo = letra, "a"/"b"). Hover na origem acende todos os caminhos; hover num destino acende só o caminho dele.

**Sidebar esquerda** (clique no `›` no canto pra abrir/fechar) narra o trace inteiro em texto, na mesma ordem/numeração das setas, traduzindo estrutura de controle pra português ("Se X: chama Y — senão chama Z"). Botão **Copiar pro Claude** copia essa narrativa pra área de transferência — cola numa conversa com IA pra pedir revisão, dúvida sobre a regra, etc.

Limitações da v1
----------------

[](#limitações-da-v1)

- Chamada via dependência injetada resolve pro **tipo declarado** (constructor promoted property ou propriedade tipada), não pelo container real — se a interface tiver várias implementações, o grafo não sabe qual roda em runtime.
- Chamadas a `parent::` não são seguidas.
- Comentário `@teller` solto só é achado em statements de primeiro nível do corpo do método — não desce em bloco aninhado (se dentro de outro if, por exemplo).
- Narrativa da sidebar só entende `if`/`elseif`/`else` — `try`/`catch`, `switch`, loop não viram texto especial (aparecem como chamada linear normal).
- "Abrir no código" usa o esquema `vscode://file/` — preso ao VSCode.
- Só resolve classes dentro dos diretórios PSR-4 do próprio projeto; chamadas pra vendor/framework não viram edge.

Licença
-------

[](#licença)

MIT — veja [LICENSE](LICENSE).

###  Health Score

40

—

FairBetter than 86% of packages

Maintenance100

Actively maintained with recent releases

Popularity2

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity45

Maturing project, gaining track record

 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://www.gravatar.com/avatar/d2687eca112c9e21f3ed671be65f8f074edac9d12419c150de9de812322fc82e?d=identicon)[valb-mig](/maintainers/valb-mig)

---

Top Contributors

[![valb-mig](https://avatars.githubusercontent.com/u/102031404?v=4)](https://github.com/valb-mig "valb-mig (2 commits)")

###  Code Quality

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/valb-mig-teller/health.svg)

```
[![Health](https://phpackages.com/badges/valb-mig-teller/health.svg)](https://phpackages.com/packages/valb-mig-teller)
```

###  Alternatives

[typo3/cms

TYPO3 CMS is a free open source Content Management Framework initially created by Kasper Skaarhoj and licensed under GNU/GPL.

1.2k1.9M122](/packages/typo3-cms)[craftcms/cms

Craft CMS

3.6k3.6M3.2k](/packages/craftcms-cms)[dedoc/scramble

Automatic generation of API documentation for Laravel applications.

2.1k11.2M115](/packages/dedoc-scramble)[psalm/plugin-laravel

Psalm plugin for Laravel

3345.3M348](/packages/psalm-plugin-laravel)[tempest/framework

The PHP framework that gets out of your way.

2.2k34.4k17](/packages/tempest-framework)[phpdocumentor/reflection

Reflection library to do Static Analysis for PHP Projects

12525.9M149](/packages/phpdocumentor-reflection)

PHPackages © 2026

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