v0.1.3 · MIT · Rust CLI

Search the source. Leave the data behind.

source-map-php scans a Laravel or Hyperf repository, writes source-code metadata to Meilisearch, and answers search from the command line. Symbols, routes, tests, package ownership, schema hints, and comments stay. Strings that look like secrets or personal data are dropped before they are stored.

The project README documents the two-line install. The single line is the same formula by its full Homebrew name.

brew tap dickwu/tap
brew install source-map-php
brew install dickwu/tap/source-map-php

Output modelREADME example

source-map-php search --project ****-api --query "patient consent store"

what matched
the symbol or route that hit
where it lives
file and line in the repository
why it matched
the query terms that lined up
related routes
framework routes tied to the symbol
related tests
tests linked to the symbol
validation command
source-map-php validate --symbolApp\Services\ConsentService::sign
missing-test warning
present when confidence is weak

Before it is stored

kept App\Services\ConsentService::sign

dropped notify owner at name@example.com

The query, the symbol, and the validate command are the examples in the project README. The email is only a shape the sanitizer drops. This slip is not a live search result.

Run it in this order.

Nothing stays running between commands. There is no app server. search and validate both accept --json.

  1. init

    init writes config/indexer.toml, .env.example, docker-compose.meilisearch.yml, and ~/.config/meilisearch/connect.json with placeholder values when that file is missing. It will not overwrite a connect file you already have. Commands that use --config load <project-root>/.env before resolving Meilisearch settings. The default config path is config/indexer.toml.

    source-map-php init --dir .
    cp .env.example .env

    Fill .env for credentials that belong to this repo. change-me below is the placeholder from the README. Skip .env when ~/.config/meilisearch/connect.json already has the shared credentials.

    MEILI_HOST=http://127.0.0.1:7700
    MEILI_MASTER_KEY=change-me
  2. doctor

    Check the environment for a repository. doctor expects Phpactor to be installed, even though symbol extraction can fall back without it.

    source-map-php doctor --repo /path/to/php-repo
  3. index

    Build an index. --framework is auto, laravel, or hyperf. --mode clean replaces the index. The project name in this example is the one the README uses.

    source-map-php index --repo /path/to/php-repo --project-name ****-api --framework auto --mode clean
  4. search

    --project is the saved project name or the full repository path, for example /Users/you/work/****-api. Omit --index and the CLI searches every saved index type and prints grouped results. You can also pass symbols, routes, tests, packages, or schema.

    source-map-php search --project ****-api --query "patient consent store"
  5. validate

    Ask for validation commands for a symbol. The CLI links symbols to related tests and ranks those commands.

    source-map-php validate --symbol "App\Services\ConsentService::sign"

Staged index

Use --mode staged when you want a run you can check before it replaces the live index. verify checks the staged indexes. promote takes the run id.

source-map-php index --repo /path/to/php-repo --framework auto --mode staged
source-map-php verify
source-map-php promote --run-id <run-id>

Remove a saved project

remove deletes the project entry from ~/.config/meilisearch/project.json and the matching Meilisearch indexes for that project prefix. --keep-indexes forgets the saved name and leaves the indexes in place.

source-map-php remove --project ****-api
source-map-php remove --project ****-api --keep-indexes

Five indexes, two frameworks.

The tool detects Laravel and Hyperf repositories. It extracts symbols, comments, package ownership, tests, and schema metadata, plus framework routes. Search targets these index names.

  • symbols
  • routes
  • tests
  • packages
  • schema

Laravel

Route extraction is in place. Fixtures cover symbol, route, schema, and test extraction for one Laravel repository.

Hyperf

Route extraction is in place. Fixtures cover route and test extraction for one Hyperf repository. Real-world route edge cases are still being hardened.

How an index is built

  1. Scan allowlisted project paths.
  2. Export Composer package ownership metadata.
  3. Extract symbols and docs from PHP files.
  4. Enrich with framework-specific route and schema metadata.
  5. Link tests and generate validation commands.
  6. Apply Meilisearch settings and write documents.
  7. Save project metadata to ~/.config/meilisearch/project.json.
  8. Emit a run manifest to build/index-runs/<run_id>.json.

Metadata in. Secrets out.

If it smells like secrets or PHI, it should not reach Meilisearch.

Project README, safety model

The index is source-code metadata: symbols, routes, tests, package ownership, schema hints, comments, and PHPDoc. It is explicitly not a production data search engine. Before strings are indexed, the sanitizer drops values that look like:

  • API keys
  • JWTs
  • private keys
  • passwords and DSNs
  • email addresses
  • phone numbers
  • long numeric IDs
  • date-of-birth-like strings
  • medical-record-style identifiers

What the scan touches.

These are the default allow and deny rules from the project README. Vendor indexing is on by default, and only for allowlisted vendor paths.

Allow

app/ · src/ · routes/ · config/ · database/migrations/ · database/factories/ · database/seeders/ · tests/ · test/ · composer.json · composer.lock · phpunit.xml · pest.php

Deny

.env* · storage/ · bootstrap/cache/ · logs/ · tmp/ · database dumps · spreadsheets · archives · node_modules/

Install the binaries.

Version 0.1.3. The formula homepage is the GitHub repository. Crate documentation is on docs.rs.

Homebrew

The formula is source-map-php in dickwu/tap. It depends on Rust at build time and installs every binary the crate builds.

brew tap dickwu/tap
brew install source-map-php
brew install dickwu/tap/source-map-php

crates.io

cargo install source-map-php

From source

git clone git@github.com:dickwu/source-map-php.git
cd source-map-php
cargo build --release

The binary is at ./target/release/source-map-php.

What Homebrew installs

Two binaries: source-map-php and phpantom_lsp. phpantom_lsp speaks Language Server Protocol on stdio. It answers document symbols, definitions, and references with the fallback PHP parser. Reference search walks PHP files under the workspace root and skips .git, vendor, and node_modules. It does not replace Phpactor. doctor still expects Phpactor.

What you still need

The README lists these build requirements. Indexing also needs a Meilisearch instance. Phpactor on PATH is the recommended extractor.

  • Rust toolchain
  • PHP 8.3+
  • Composer
  • Meilisearch
  • Phpactor on PATH, for the best extraction quality

Host order: MEILI_HOST, then meilisearch.host in config/indexer.toml when you override the default, then ~/.config/meilisearch/connect.json, then http://127.0.0.1:7700. Key order: MEILI_MASTER_KEY by default, or the env var named by meilisearch.master_key_env, then ~/.config/meilisearch/connect.json.

A working baseline.

The project says so itself. CI runs cargo fmt --check, cargo clippy --all-targets --all-features -- -D warnings, and cargo test on Linux and macOS. Tagged pushes matching v* build x86_64-unknown-linux-gnu and aarch64-apple-darwin.

  • Hyperf routes Extraction still needs hardening for large repositories, mixed file encodings, and route organization. The README calls out config/routers/*.php and grouped route trees as next work.
  • Phpactor and fallback parsing doctor expects Phpactor even though the extractor can fall back. Multiline method signatures in that fallback are listed as next work.
  • Live Meilisearch in CI End-to-end indexing against a live Meilisearch instance is not covered in CI. Non-UTF-8 junk files inside scanned trees are still being hardened.
  • Release policy Release artifacts are wired in CI. The README says no versioning policy is documented yet, and it still lists a first tagged binary release as next work. Install from Homebrew or crates.io.

Questions.

What does source-map-php index?

It indexes PHP source-code metadata from Laravel and Hyperf repositories into Meilisearch: symbols, comments, routes, tests, package ownership, and schema hints. It does not index production application data.

How do I install it with Homebrew?

Run brew tap dickwu/tap, then brew install source-map-php. The fully qualified command brew install dickwu/tap/source-map-php installs the same formula.

Which frameworks does it detect?

It detects Laravel and Hyperf repositories. The index command accepts --framework auto, --framework laravel, or --framework hyperf.

Where does the CLI read Meilisearch settings?

The host is resolved from MEILI_HOST, then meilisearch.host in config/indexer.toml when you override the default, then ~/.config/meilisearch/connect.json, then the built-in default http://127.0.0.1:7700. The API key is resolved from MEILI_MASTER_KEY by default, or the env var named by meilisearch.master_key_env, then ~/.config/meilisearch/connect.json.

What does the sanitizer drop before indexing?

API keys, JWTs, private keys, passwords and DSNs, email addresses, phone numbers, long numeric IDs, date-of-birth-like strings, and medical-record-style identifiers.

Does it run an application server?

No. source-map-php is a command-line tool, and no always-on app server is required.

How do I choose a project when I search?

Pass --project the saved project name or the full repository path. Omit --index to search symbols, routes, tests, packages, and schema and print grouped results.

What else does the Homebrew formula install?

It installs the source-map-php and phpantom_lsp binaries. phpantom_lsp is a stdio language server for document symbols, definitions, and references, using the fallback PHP parser.

What is still unfinished?

The project describes itself as a working baseline. Hyperf route extraction still needs hardening on large repositories with mixed file encodings and route organization. The doctor command expects Phpactor even though extraction can fall back. End-to-end indexing against a live Meilisearch instance is not covered in CI.