NAME
Langertha::Raider::Context::Memory - Internal reader of the Claude Code memory files (CLAUDE.md hierarchy)
VERSION
version 0.504
SYNOPSIS
# Internal to Langertha-Raider -- no API promise.
my $memory = Langertha::Raider::Context::Memory->new(
root => $root,
walk_dirs => [ $layout->walk_dirs ],
);
for my $item (@{ $memory->items }) {
say $item->{label}.' ('.$item->{scope}.')';
}
my $prompt = $memory->prompt_text; # undef without any file
# later, when a file tool touches lib/Foo/Bar.pm:
my @nested = $memory->nested_for('lib/Foo/Bar.pm');
my $append = $memory->nested_text(@nested); # undef when nothing new
DESCRIPTION
Internal module. Its interface may change without notice.
Reads the Claude Code memory files as ADR 0019 §2 describes, each as its own context item with source and scope (ADR 0004):
- 1. <claude_home>/CLAUDE.md -- scope
user. - 2. For every directory of "walk_dirs", top down: CLAUDE.md (or, when that level has none, its AGENTS.md) -- scope
projectin "root",ancestorabove it; then CLAUDE.local.md -- scopelocal.
@path imports in these files are expanded in place, as Claude Code does: a token @some/path at the start of a line or after whitespace (the path runs to the next whitespace) is replaced by the content of that file, resolved relative to the importing file, from "home" for @~/..., as given when absolute. Imports are never expanded inside inline code spans or fenced code blocks, at most "max_import_depth" levels deep, never twice for one file (so cycles end), and a missing or unreadable target is left as written. Because the @ must follow whitespace or start the line, an address like a@b.c is never an import.
CLAUDE.md files below "root" are not read up front; "nested_for" hands them out once each when a path in their subtree is touched (Claude Code's nested memory).
Empty and unreadable files are skipped. Paths are compared by their real path where the filesystem has one; every file is such an absolute path.
root
The project directory. Required.
home
The user's home directory, for @~/ imports and ~/ labels. Defaults to "home_dir" in Langertha::Raider::Home.
claude_home
The Claude Code configuration directory holding the user memory: like "claude_home" in Langertha::Raider::Context::Layout, $ENV{CLAUDE_CONFIG_DIR} when set and not empty, else <home>/.claude.
walk_dirs
walk_dirs => [ $layout->walk_dirs ],
Required. The directories of the memory walk, top down and ending at "root" (strings or Path::Tiny), as "walk_dirs" in Langertha::Raider::Context::Layout returns them.
max_import_depth
How many levels of @path imports are expanded. Defaults to 5; an import deeper than that is left as written.
items
for my $item (@{ $memory->items }) { ... }
The memory files in load order (see "DESCRIPTION"), computed once, as an ArrayRef of HashRefs:
file-- absolute path.label-- the path relative to "root" when inside it,~/...when under "home", else absolute.scope--user,ancestor,projectorlocal.kind--CLAUDE.md,CLAUDE.local.mdorAGENTS.md.text-- the content with its imports expanded.imports-- ArrayRef of the absolute paths actually imported, nested imports included.
prompt_text
my $text = $memory->prompt_text;
"items" formatted as Claude Code puts them into the prompt, one block per item, separated by blank lines:
Contents of /abs/CLAUDE.md (project instructions, checked into the codebase):
<text>
The description is user's private global instructions for all projects (scope user), project instructions, checked into the codebase (project, ancestor, nested), user's private project instructions, not checked in (local) or project instructions (AGENTS.md) (kind AGENTS.md). Returns undef when there are no items.
nested_for
my @items = $memory->nested_for($path);
The CLAUDE.md files of the directories strictly below "root" down to the directory of $path ($path itself when it is a directory), top down, that this object has not handed out before. $path is absolute or relative to "root"; a path outside "root" yields nothing. Every file is returned at most once per object. Items have the shape of "items", scope nested, kind CLAUDE.md.
nested_text
my $text = $memory->nested_text(@items);
The given items formatted like "prompt_text"; undef for none.
SEE ALSO
SUPPORT
Issues
Please report bugs and feature requests at https://github.com/Getty/langertha-raider/issues.
IRC
Join #langertha on irc.perl.org or message Getty directly.
CONTRIBUTING
Contributions are welcome! Please fork the repository and submit a pull request.
AUTHOR
Torsten Raudssus <torsten@raudssus.de> https://raudssus.de/
COPYRIGHT AND LICENSE
This software is copyright (c) 2026 by Torsten Raudssus.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.