nadeemkhan / atlas-scope
Scan a Laravel, C++, C# or Python project and explore it as a 3D map of routes, classes, models, namespaces and database tables. Runs on Laravel 10, 11, 12 and 13.
Requires
- php: ^8.3
- ext-mbstring: *
- ext-zip: *
- laravel/framework: ^10.0|^11.0|^12.0|^13.0
- nikic/php-parser: ^5.0
Requires (Dev)
- orchestra/testbench: ^11.0
- phpunit/phpunit: ^12.5
Suggests
- ext-sqlite3: The default database for a fresh install, and what the bundled dev server expects.
Provides
None
Conflicts
None
Replaces
None
README
Scan a Laravel, C++, C# or Python project and explore it as a 3D map: routes, controllers, models, classes, namespaces, build targets and database tables — with the relationships between them drawn as actual links, and every request's journey traced end to end.
composer require atlas/scope
php artisan migrate
Then open /atlas. That is the whole installation.
What it does
| Scanner | Four language profiles — Laravel/PHP, C++, C#, Python — behind one pipeline. A scan walks the source, builds a graph of nodes and edges, computes layers, layouts and insights, and stores all of it. |
| 3D atlas | The graph rendered with three.js: one instanced mesh for nodes, one buffer for relationships, layered decks for architecture, and three layout engines (architecture layers, modules, spiral). Quality tiers from High (bloom) down to Performance, with an automatic step-down if the frame rate drops. |
| Report page | The same scan as a readable document: composition, metrics, per-language vocabulary, database tables with their columns. |
| Request journeys | Pick a route and the atlas lights the exact chain it walks — entry point → middleware → controller → services → models → tables. Compiled projects get their entry points (main(), an executable target) instead. |
| Source viewer | Every node opens the file it came from, in place, with the line it was declared on. |
| Local assistant | An optional chat panel that answers questions about the loaded project — running on your machine, free, with no API key. See The local assistant. |
Uploads up to 150 MB, on a stock PHP install
PHP's upload_max_filesize is 2 MB out of the box, and that is where most
"upload failed" reports come from. Large archives are streamed here in ~1 MB
pieces as raw request bodies — which PHP does not treat as form uploads, so
neither upload_max_filesize nor post_max_size ever applies. The UI reads the
server's real capacity live and tells you which limit is binding, in numbers.
Requirements
| PHP | 8.1 – 8.4, with ext-zip and ext-mbstring |
| Laravel | 10, 11, 12 or 13 — one codebase, no version branches |
| Database | SQLite by default — the package ships migrations and nothing else |
| Node | none. The renderer ships compiled in assets/; Node is only needed to rebuild it. |
| Queue | optional — see Running a scan |
| php-parser | ^4.19 or ^5.0, whichever your application already has |
Compatibility
Every supported combination is exercised by the package's own suite, on real runtimes — not asserted from a constraint file:
composer test:matrix # Laravel 10, 11, 12 and 13, one cell each
| Laravel | Testbench | PHP | Result |
|---|---|---|---|
| 10.x | 8.x | 8.1 – 8.4 | ✅ 32 tests, 302 assertions |
| 11.x | 9.x | 8.2 – 8.4 | ✅ 32 tests, 302 assertions |
| 12.x | 10.x | 8.2 – 8.4 | ✅ 32 tests, 302 assertions |
| 13.x | 11.x | 8.3 – 8.4 | ✅ 32 tests, 302 assertions |
PHP 8.1 is the floor because Laravel 10's floor is 8.1, and because the codebase is written in the 8.1 language: enums, readonly properties, first-class typed signatures. Laravel 4–9 and PHP 5–8.0 are not supported, and supporting them would not be a constraint change — it would mean rewriting the scanner, the enums, the models and the assistant in an older dialect, with a different framework API for each major you add. If you need that, it is a fork, not a version range.
Three things had to change for this range, and each is worth knowing if you touch the code:
$castsis a property, not a method. Laravel 11 introducedcasts(); Laravel 10 ignores the method and the model quietly loses every cast.- No standalone
nullreturn types, and no->valueinside constants — both are legal in newer PHP and fatal on 8.1. Enum label keys are written as literal backed values, with a test that asserts they still match their cases. - php-parser is wrapped (
Atlas\Scope\Support\Ast): 5.x renamed the parser entry point and 4.x does not have it.
Installation
composer require atlas/scope php artisan migrate
The service provider is discovered automatically. Migrations create five
atlas_* tables; nothing else in your application is touched.
By default AtlasScope is served under /atlas, so it can never shadow your
own routes. To serve it from the root of a dedicated installation:
ATLAS_ROUTE_PREFIX=
Publish what you want to own
Nothing below is required to run the package — publishing is for hosts that want a copy they can edit.
php artisan vendor:publish --tag=atlas-config # config/atlas.php php artisan vendor:publish --tag=atlas-assets # assets/ → public/vendor/atlas php artisan vendor:publish --tag=atlas-errors # error pages → resources/views/errors php artisan vendor:publish --tag=atlas-bin # bin/limits.env, the dev-server upload limits php artisan vendor:publish --tag=atlas-sources # the unbuilt CSS/JS, to rebuild yourself
Assets are streamed by a route until you publish them, so the tool works on a
read-only public/ directory, behind a proxy, or on a first run with no setup
step. Publishing moves 675 kB of static files to the web server where they
belong.
Running a scan
Uploads and re-scans run on a queue so the request returns immediately, unless
your queue connection is sync — with the default driver a scan runs inline and
there is nothing to supervise.
php artisan queue:work --queue=atlas # if QUEUE_CONNECTION is not 'sync'
From the command line:
php artisan atlas:scan /path/to/project --name="My project" # scan a directory php artisan atlas:scan --all # re-scan everything php artisan atlas:prune # drop workspaces with no project row php artisan atlas:serve --port=8080 # artisan serve, with real upload limits
atlas:serve is worth knowing about: plain php artisan serve hands requests to
a child php -S process that knows nothing about your -d flags, which is why
uploads fail at 2 MB on a dev machine. atlas:serve puts the limits on the child
invocation itself, taken from bin/limits.env (publish it with --tag=atlas-bin).
The local assistant
Optional, and entirely local: Ollama on your own machine, no account, no key, no metering. With nothing listening the panel says so and explains how to start one — it never falls back to a cloud service.
ollama pull qwen3:8b # about 5 GB, the balance of speed and quality on a laptop
ollama serve
The panel knows the graph and reads file excerpts through a retriever, so it can
answer what does this application do and what is this particular file doing
with citations that open the node they came from. The model list and everything
else lives in config/atlas.php (atlas.ai), overridable from .env:
ATLAS_AI_BASE_URL=http://127.0.0.1:11434 # any OpenAI-compatible local runtime ATLAS_AI_MODEL=qwen3:8b
Configuration
Everything has a working default; see config/atlas.php.
| key | default | what it does |
|---|---|---|
atlas.routes.prefix |
atlas |
URL prefix for every route. '' serves it from the root. |
atlas.routes.middleware |
['web'] |
Put the tool behind auth here. |
atlas.storage_path |
storage/app/atlas |
Where project workspaces are unpacked. Absolute path. |
atlas.max_archive_bytes |
150 MB | Ceiling per uploaded archive. |
atlas.max_extracted_bytes |
2 GB | Zip-bomb guard while unpacking. |
atlas.sync_scans |
= queue is sync |
Run scans inline instead of dispatching them. |
atlas.scan_memory_limit |
1024M |
Raised for console processes only — scans read whole trees. |
atlas.demo_enabled |
true |
Offers the bundled sample project on the landing page. |
atlas.ai.* |
see above | The assistant: runtime, model, timeout, retrieval budget. |
Rebuilding the renderer
Only needed if you change the JavaScript. The package's build is self-contained:
it emits assets/atlas.js, assets/atlas.css and a three.js chunk, plus an
assets/version file the layout uses to cache-bust.
npm install npm run build
--tag=atlas-sources publishes the unbuilt sources into
resources/vendor/atlas/ if you would rather fold them into your own build.
Tests
composer install
composer test
The suite runs against a real Laravel application booted by Orchestra Testbench: it uploads and scans fixtures in all four languages, walks the API, reads source back out of a scanned project and drives the assistant against a fake runtime.
How it is put together
src/ holds the package; see docs/ARCHITECTURE.md for
the pipeline, the language profiles, the graph payload, the renderer and the
focus engine.
src/Services/Scan/ |
the pipeline, the four language profiles, the parsers and classifiers |
src/Services/Ai/ |
the local model client, the project brief and the retriever |
src/Http/Controllers/ |
the pages, the JSON API and the chunked upload endpoints |
src/Support/ |
graph builder, path sandbox, workspace paths, asset URLs, PHP ini readings |
resources/js/atlas/ |
the renderer: scene, layouts, store, inspector, tracer, assistant panel |
resources/demo/taskflow/ |
the sample project offered on the landing page |
Notes
- Table names are prefixed (
atlas_projects,atlas_scans, …) so the package can be installed into an application that already has aprojectstable. - Error pages are published, not registered: Laravel resolves
resources/views/errorsby convention, which a package cannot namespace. - Memory: a scan of a very large project wants the CLI's
memory_limit; the package raises it toatlas.scan_memory_limitin console processes only. - Licence: MIT is declared in
composer.json. Add your ownLICENSEfile before publishing if that is not the licence you intend.