viocode/content-extractor

Extract Laravel project source files (controllers, models, migrations, or the whole tree) into a single text file, respecting .gitignore rules and configurable skip/add filters.

Maintainers

Package info

github.com/Eng-Mohannad-Mahmoud/content-extractor

pkg:composer/viocode/content-extractor

Transparency log

Statistics

Installs: 2

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

v1.0.0 2026-08-31 20:33 UTC

This package is auto-updated.

Last update: 2026-08-31 20:35:42 UTC


README

A Laravel package that dumps your project's source files — controllers, models, migrations, or the whole tree — into a single text file, respecting .gitignore, with configurable --skip / --add overrides.

Requirements

  • PHP 8.2+
  • Laravel 11 or 12

Installation

composer require viocode/content-extractor

The package uses Laravel's package auto-discovery, so the extract:content Artisan command is available immediately — no manual ServiceProvider registration needed.

If you ever need to register it manually (auto-discovery disabled), add to bootstrap/providers.php (Laravel 11+):

VioCode\ContentExtractor\ContentExtractorServiceProvider::class,

How it works

  1. The project's .gitignore (at the project root) is parsed and used as the baseline filter — anything it ignores is excluded, and ignored directories are not even recursed into.
  2. Six common lock files (composer.lock, package-lock.json, yarn.lock, pnpm-lock.yaml, poetry.lock, Gemfile.lock) are excluded by default, regardless of .gitignore.
  3. --skip="pattern" forcibly excludes anything matching pattern, even if .gitignore would have allowed it.
  4. --add="pattern" forcibly includes anything matching pattern, even if .gitignore, a --skip pattern, or the default lock-file list would otherwise have excluded it. --add has the final say.
  5. Binary files are always skipped (by extension, and by sniffing for a NUL byte in the first 8KB of content).

Precedence, highest to lowest: --add > --skip > lock-file defaults > .gitignore.

Usage

Extract everything (respecting .gitignore)

php artisan extract:content

Writes to content.txt in the project root.

Choose an output file

php artisan extract:content project-dump.txt

Extract only controllers

php artisan extract:content --controllers

Scans app/Http/Controllers only.

Extract only models

php artisan extract:content --models

Scans app/Models only.

Extract only migrations

php artisan extract:content --migrations

Scans database/migrations only.

Combine a mode with --skip

php artisan extract:content --controllers --skip="app/Http/Controllers/Admin/*"

Extracts all controllers except anything under Admin/.

Combine a mode with --add

php artisan extract:content --models --add="app/Traits/HasUuid.php"

Extracts all models, plus the specified trait file even though it lives outside app/Models.

Repeatable flags

Both --skip and --add can be passed multiple times:

php artisan extract:content \
    --skip="tests/*" \
    --skip="database/seeders" \
    --add="composer.lock" \
    --add=".env.example"

Re-include a lock file

Lock files are excluded by default. To include one anyway:

php artisan extract:content --add="composer.lock"

Full extraction with a custom output file, skips, and adds

php artisan extract:content full-dump.txt \
    --skip="storage/*" \
    --skip="*.lock" \
    --add="storage/app/important-config.json"

Pattern syntax for --skip / --add

Patterns are glob-style and matched against the file's path relative to the project root:

  • An exact path (database/seeders) matches that path itself and everything underneath it.
  • A path containing *, ?, or [...] is matched with fnmatch() against both the full relative path and the file's basename, so *.log matches any .log file at any depth, while app/Http/Controllers/*.php only matches direct children of that directory.

Output format

For every included file, in alphabetical path order:

app/Http/Controllers/AuthController.php
<?php

namespace App\Http\Controllers;
...

app/Models/User.php
<?php

namespace App\Models;
...

Each block is the file's relative path, a newline, then its exact contents, followed by a single blank line before the next block.

Running the package's own tests

From the package directory:

composer install
vendor/bin/phpunit

Tests cover:

  • GitignoreMatcherTest — glob-to-regex translation, negation, anchoring, ** handling, directory-only patterns, and the no-.gitignore fallback.
  • SkipAddResolverTest — the full --add > --skip > lock-file > .gitignore precedence chain, including directory-recursion pruning.
  • LockFileExclusionTest — default lock-file exclusion and its override via --add.

Install & Usage (quick reference)

composer require viocode/content-extractor

# Dump everything except vendor/node_modules/etc. (from .gitignore) into content.txt
php artisan extract:content

# Dump only your models, skipping factories, into models.txt,
# but force-include the base model trait
php artisan extract:content models.txt --models \
    --skip="app/Models/Concerns/*" \
    --add="app/Models/Concerns/HasUuid.php"