NAME

Dist::Zilla::Plugin::GatherAgentContext - Snapshot the agent context (.claude/.codex/CLAUDE.md/AGENTS.md/...) into the build for provenance

VERSION

version 0.002

SYNOPSIS

; in your dist.ini
[GatherAgentContext]

; or narrow what is snapshotted
[GatherAgentContext]
harness       = claude
exclude_match = (?:^|/)secrets/

DESCRIPTION

Gathers a distribution's agent context from disk into the build under misc/agent-context/ (present in the tarball, but not installed), so that a built distribution records which skills, agents and rules it was built with.

Unlike [Git::GatherDir] this plugin reads from the working directory, not from git, so it also captures skilletor-installed (git-ignored) skills, agents and rules — exactly the content that is not committed in the repository.

Because it reads from disk, it is strict about what it reads there: below a harness directory only known agent content is taken, never the local state a harness keeps next to it. See "WHAT IS SNAPSHOTTED".

harness

Which harness default sets to snapshot: claude, codex (repeatable), or all. Unset means all. Ignored once dir/file are set explicitly.

dir

Directories (repo-relative) to snapshot recursively. Overrides the harness-derived directory defaults. A harness directory (.claude, .codex) is reduced to its agent content even when named here; see "WHAT IS SNAPSHOTTED" for how to take more.

file

Single repo-relative files to snapshot. Overrides the harness-derived file defaults.

to

Base path inside the build. Default misc/agent-context.

exclude_match

Additional exclude regexes (repeatable), applied on top of the built-in ones (see "BUILT-IN EXCLUDES").

prune_gitignore

Skip .gitignore files (skilletor's per-skill management marker). Default 1.

missing_ok

Silently skip a configured dir/file that is absent. Default 1. Set to 0 to make an absent configured path fatal.

WHAT IS SNAPSHOTTED

A harness directory — any directory named .claude or .codex — is not only agent context. The harness and the user also keep local state there: login tokens, session transcripts, todo lists, caches, local overrides, backups. This plugin reads from disk, so a .gitignore does not keep any of that out of the tarball. Directly below a harness directory the plugin therefore takes only these entries and never opens anything else:

  • the directories agents/, skills/, rules/, hooks/ and commands/, recursively;

  • the files CLAUDE.md, skilletor.json, skilletor.lock.json and skilletor-rules.md.

So .claude/.credentials.json, .claude/projects/, .claude/todos/, .claude/statsig/, .claude/local/, .codex/auth.json, .codex/config.toml and anything else a harness or a person drops there stay out, whatever the file is called. This holds for a harness directory named explicitly through "dir" and for one met deeper inside a configured tree.

Other directories (.agents/skills, or your own "dir" entries) are taken in full. To snapshot a further subdirectory of a harness directory, configure it by name — it is then an ordinary directory:

[GatherAgentContext]
dir = .claude
dir = .claude/output-styles
dir = .codex
dir = .agents/skills

The "BUILT-IN EXCLUDES" apply on top, everywhere.

BUILT-IN EXCLUDES

These paths are always skipped, wherever they are found and before any "exclude_match" additions:

  • Any <name>.local.<ext> file (for example settings.local.json, skilletor.local.json, CLAUDE.local.md, or a backup such as settings.local.json.bak) — machine-local overrides, not agent content. Skilletor-installed agents and rules named .local.<name>.md (leading dot) are content and are kept.

  • .credentials.json and auth.json — harness login tokens.

  • settings.json — editor and permission configuration, not agent content.

  • Any worktrees/ directory — agent worktrees hold full checkouts (thousands of files). Such directories are pruned before descent, not walked and then discarded leaf by leaf.

  • .DS_Store.

  • .gitignore files, unless "prune_gitignore" is set to 0 (skilletor drops a per-skill .gitignore as a management marker).

Any excluded directory is pruned before the plugin descends into it, so its contents are never stat-walked.

ENCODING AND SYMLINKS

Files are read and decoded as strict UTF-8. A binary or otherwise non-UTF-8 file aborts the build with a fatal error rather than being silently substituted — snapshot textual agent context, not binaries.

Within the recursive directory walk, symlinks are never followed — a symlinked file or subdirectory found while descending is skipped. A top-level path given explicitly through "dir" or "file" is resolved normally, so a configured entry that is itself a symlink is still read.

SUPPORT

Issues

Please report bugs and feature requests at https://github.com/Getty/p5-dist-zilla-plugin-gatheragentcontext/issues.

CONTRIBUTING

Contributions are welcome! Please fork the repository and submit a pull request.

AUTHOR

Torsten Raudssus <getty@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2026 by Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.