Dist-Zilla-Plugin-GatherAgentContext

 view release on metacpan or  search on metacpan

.claude/skills/gatheragentcontext-core/SKILL.md  view on Meta::CPAN

a configured tree. Other directories (`.agents/skills`, own `dir` entries) are taken in
full.

## The built-in excludes

Always skipped, wherever they are found, before any `exclude_match` addition:

| Excluded | Why |
|---|---|
| `<name>.local.<ext>` (any depth) | machine-local overrides and their backups. A **leading-dot** `.local.<name>.md` is skilletor content and stays. |
| `.credentials.json`, `auth.json` | harness login tokens |
| `settings.json` | editor and permission config, not agent content |
| any `worktrees/` directory | agent worktrees hold full checkouts (thousands of files) |
| `.DS_Store` | — |
| `.gitignore` | unless `prune_gitignore` is 0 |

An excluded **directory** is pruned before the plugin descends into it, so its contents
are never stat-walked. A rewrite into walk-then-filter re-introduces a full walk of
`.claude/worktrees/` on every build — the thing the prune exists for.

## Encoding and symlinks

.gitignore  view on Meta::CPAN

Build
Build.bat
pm_to_blib
# XS build artifacts
*.o
*.bs
# Testing
cover_db/
pod2htmd.tmp
# Claude Code — commit: skills/, agents/, hooks/, settings.json
# Ignore: local overrides, credentials, session data
.claude/*.local.*
.claude/local/
.claude/.credentials.json
.claude/statsig/
.claude/todos/
.claude/projects/

# karr materialized task view -- never commit
tasks/
config.yml

# Claude Code worktrees (claude --worktree / isolated agents) -- never commit
/.claude/worktrees/

Changes  view on Meta::CPAN

Release history for Dist-Zilla-Plugin-GatherAgentContext

0.002     2026-10-25 18:38:49Z
    - Local state and secrets below a harness directory can no longer end up
      in the tarball. Below .claude/ and .codex/ only agent content is
      gathered now (agents/, skills/, rules/, hooks/, commands/, CLAUDE.md,
      skilletor.json, skilletor.lock.json, skilletor-rules.md); everything
      else there (.credentials.json, auth.json, config.toml, projects/,
      todos/, statsig/, local/, session logs, backups, ...) is never read,
      whatever it is called. To snapshot a further subdirectory, configure it
      by name ("dir = .claude/output-styles").
    - Built-in excludes cover any <name>.local.<ext> file (settings.local.json,
      settings.local.json.bak, CLAUDE.local.md) as well as .credentials.json
      and auth.json, at any depth.

0.001     2026-09-29 20:02:51Z
    - Initial release: snapshot agent context (.claude/.codex/CLAUDE.md/...)
      into the build under misc/agent-context/ for build provenance.

lib/Dist/Zilla/Plugin/GatherAgentContext.pm  view on Meta::CPAN

  return @files;
}

sub _exclude_res {
  my ($self) = @_;
  my @res = (
    # <name>.local.<ext>: machine-local overrides (settings.local.json,
    # skilletor.local.json, CLAUDE.local.md) and their backups (.local.json.bak).
    # A leading-dot `.local.<name>.md` is skilletor-installed content and stays.
    qr{(?:^|/)[^/]+\.local\.[^/]+$},
    qr{(?:^|/)(?:\.credentials|auth)\.json$},   # harness login tokens
    qr{(?:^|/)settings\.json$},       # editor/permission config, not agent content
    qr{(?:^|/)worktrees/},
    qr{(?:^|/)\.DS_Store$},
  );
  push @res, qr{(?:^|/)\.gitignore$} if $self->prune_gitignore;
  push @res, map { qr/$_/ } @{ $self->exclude_match };
  return @res;
}

sub _excluded {

lib/Dist/Zilla/Plugin/GatherAgentContext.pm  view on Meta::CPAN

the directories C<agents/>, C<skills/>, C<rules/>, C<hooks/> and C<commands/>,
recursively;

=item *

the files C<CLAUDE.md>, C<skilletor.json>, C<skilletor.lock.json> and
C<skilletor-rules.md>.

=back

So C<.claude/.credentials.json>, C<.claude/projects/>, C<.claude/todos/>,
C<.claude/statsig/>, C<.claude/local/>, C<.codex/auth.json>,
C<.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 L</dir> and for one met deeper inside a configured tree.

Other directories (C<.agents/skills>, or your own L</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]

lib/Dist/Zilla/Plugin/GatherAgentContext.pm  view on Meta::CPAN

=item *

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

=item *

C<.credentials.json> and C<auth.json> — harness login tokens.

=item *

C<settings.json> — editor and permission configuration, not agent content.

=item *

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

misc/agent-context/.claude/skills/gatheragentcontext-core/SKILL.md  view on Meta::CPAN

a configured tree. Other directories (`.agents/skills`, own `dir` entries) are taken in
full.

## The built-in excludes

Always skipped, wherever they are found, before any `exclude_match` addition:

| Excluded | Why |
|---|---|
| `<name>.local.<ext>` (any depth) | machine-local overrides and their backups. A **leading-dot** `.local.<name>.md` is skilletor content and stays. |
| `.credentials.json`, `auth.json` | harness login tokens |
| `settings.json` | editor and permission config, not agent content |
| any `worktrees/` directory | agent worktrees hold full checkouts (thousands of files) |
| `.DS_Store` | — |
| `.gitignore` | unless `prune_gitignore` is 0 |

An excluded **directory** is pruned before the plugin descends into it, so its contents
are never stat-walked. A rewrite into walk-then-filter re-introduces a full walk of
`.claude/worktrees/` on every build — the thing the prune exists for.

## Encoding and symlinks

t/20-excludes.t  view on Meta::CPAN

}

# --- Local state and secrets below a harness directory never reach the build.
# The harness and the user park session logs, todos, caches and login tokens in
# .claude/ and .codex/. Nothing of that may be gathered -- including names no
# list anticipated (history.jsonl, a stray backup, a new cache dir): below a
# harness directory only known agent content is taken.
{
  my %state = (
    # what the fleet .gitignore calls "never track"
    'source/.claude/.credentials.json'          => "{\"token\":\"s3cret\"}\n",
    'source/.claude/projects/-home-x/abc.jsonl' => "session log\n",
    'source/.claude/todos/a.json'               => "[]\n",
    'source/.claude/statsig/cache.json'         => "{}\n",
    'source/.claude/local/notes.md'             => "private\n",
    'source/.claude/settings.local.json'        => "{}\n",
    'source/.claude/settings.local.json.bak'    => "{}\n",
    'source/.claude/CLAUDE.local.md'            => "private memory\n",
    'source/.codex/auth.json'                   => "{\"token\":\"s3cret\"}\n",
    # names nobody put on a list
    'source/.claude/history.jsonl'              => "prompt history\n",
    'source/.claude/shell-snapshots/s.sh'       => "export TOKEN=s3cret\n",
    'source/.claude/notes.txt'                  => "scratch\n",
    'source/.codex/config.toml'                 => "[mcp_servers.x]\n",
    'source/.codex/sessions/2026/s.jsonl'       => "session log\n",
    # a content name of the wrong kind is not content
    'source/.codex/rules'                       => "a file, not the rules dir\n",
    # tokens and local overrides tucked into otherwise gathered directories
    'source/.claude/skills/foo/auth.json'         => "{}\n",
    'source/.claude/skills/foo/.credentials.json' => "{}\n",
    'source/.claude/agents/reviewer.local.md'     => "local override\n",
    'source/.agents/skills/bar/auth.json'         => "{}\n",
  );
  my %content = (
    'source/CLAUDE.md'                                 => "c\n",
    'source/AGENTS.md'                                 => "a\n",
    'source/.claude/CLAUDE.md'                         => "c\n",
    'source/.claude/agents/worker.md'                  => "agent\n",
    'source/.claude/agents/.local.karr-coordinator.md' => "agent\n",
    'source/.claude/skills/foo/SKILL.md'               => "body\n",

t/20-excludes.t  view on Meta::CPAN

    'exactly the agent content is gathered, nothing else';
}

# --- An explicitly configured harness directory is filtered the same way:
# `dir = .claude` means "the agent content of .claude", not "all of .claude".
{
  my $tzil = build_tzil(
    ini   => [ 'dir = .claude' ],
    files => {
      'source/.claude/skills/foo/SKILL.md'  => "body\n",
      'source/.claude/.credentials.json'    => "{}\n",
      'source/.claude/projects/p/abc.jsonl' => "session log\n",
    },
  );
  plugin($tzil)->gather_files;
  is_deeply [ gathered($tzil) ],
    [ 'misc/agent-context/.claude/skills/foo/SKILL.md' ],
    'explicit dir = .claude still takes agent content only';
}

# --- A harness directory met deeper in a configured tree is filtered too.



( run in 1.309 second using v1.01-cache-2.11-cpan-3f962061493 )