Perl CodeMap

A self-contained, interactive architecture map for Perl projects.

Perl CodeMap scans a source tree without executing it, extracts namespace and subroutine metadata, resolves statically identifiable local module dependencies, and generates a standalone HTML report with an interactive dependency graph, searchable symbol index, and syntax-highlighted source browser.

Inspired by peterretief/codemap, reimagined for Perl applications that may have multiple packages per file, interconnected libraries, and circular dependencies.

Perl CodeMap synthetic example

Features

Requirements

Install from the repository

# In a cloned checkout
cpanm PPI                        # recommended, optional
perl Makefile.PL
make
make test
sudo make install               # optional: installs perl-codemap on PATH

For a source-checkout-only run, no installation is necessary:

perl bin/perl-codemap --root examples/sample --parser lite \
  --output example.html --json example.json

Open example.html locally. It contains sample application code only.

Public live demo on GitHub Pages

The GitHub Actions workflow publishes a regenerated interactive report from examples/sample/ to GitHub Pages on successful pushes to main. The Perl and JavaScript CI test jobs must pass before the deployment starts. The published root page (index.html) is the interactive demo; no web server or build tool is required on the client.

To enable deployment, open Settings → Pages → Build and deployment → Source → GitHub Actions in your GitHub repository, then push to main. The live sample is available at https://interrupt21h.github.io/perl-codemap/.

The workflow deliberately scans only the synthetic example and uploads only _site, never the repository root, JSON exports, or internal source trees. See GitHub Pages deployment for setup, troubleshooting and safety considerations.

Scan an actual project

perl-codemap \
  --root /path/to/my-project/lib \
  --parser ppi \
  --name 'My Perl Project' \
  --output code-map.html \
  --json code-map.json

To include test files, add --include-tests. A report embeds source code by default so functions can be opened without network access. To avoid embedding:

perl-codemap --root /path/to/my-project/lib --no-embed-source \
  --output architecture-only.html

See CLI and usage for complete options, GitLab/GitHub source links, navigation examples, and common troubleshooting steps.

Re-render an existing JSON export

perl-codemap --from-json old-map.json --output new-map.html

To add highlighted source to an export created without source content, pass its original scan directory:

perl-codemap --from-json old-map.json \
  --root /path/to/original/scan-directory \
  --output map-with-source.html

The exporter only reads paths under the selected source directory, and rejects absolute or traversal paths when hydrating source from JSON.

How the graph works

It uses local package-level dependencies, not function call inference:

flowchart BT
    Config[Demo::Config]
    Storage[Demo::Storage]
    Queue[Demo::Queue]
    Web[Demo::Web]
    Worker[Demo::Worker]
    App[Demo::App]
    Storage --> Config
    Queue --> Config
    Web --> Storage
    Worker --> Queue
    Worker --> Storage
    App --> Web
    App --> Worker

A directed connection means the source module depends on the target module. The layout places foundations below dependents. Strongly connected components are handled without recursion loops; cycle edges are distinguished visually. See architecture for graph limitations and data flow.

Quality and tests

prove -Ilib -v t
node --check lib/Perl/CodeMap/assets/app.js
node t/browser-smoke.js

CI runs Perl tests across multiple supported interpreter versions, both lite and PPI parsing paths, and JavaScript smoke checks. An optional Chromium end-to-end script is provided for development (see contributing).

Known limitations

Static use, named require, use parent, use base, extends, and with relations are recognized when resolvable to a package inside the scanned root. Dynamic require, AUTOLOAD, monkey-patching, runtime method dispatch, Catalyst action routing, DBIx::Class relationships, and Moose/Moo method modifiers are not fully modeled. Multiple package statements per file are supported; temporary block-scoped package declarations are best effort. PPI does not provide full runtime execution semantics.

The lite parser is intentionally heuristic. For projects with complex Perl syntax, use --parser ppi.

Security and privacy

HTML and JSON reports can contain complete source files, secrets, or private paths. Do not publish generated reports from private repositories. The public Git repository should contain only this application and synthetic examples. Read SECURITY.md before publishing artifacts or enabling CI.

Project documentation

Maintainer

Scott Muller — scott@21h.io.

Issues, fixes, and contributions are welcome; see CONTRIBUTING.md.

License

MIT — see LICENSE. Perl CodeMap is a separate project inspired by Peter Retief's MIT-licensed Go CodeMap; see NOTICE.md. Vendored PrismJS components retain their own MIT license.