Gives any AI agent persistent memory of who the user is — not just facts, but patterns, preferences, personality traits, and behavioral evolution over time....
---
name: Soul Ledger
slug: soul-ledger
version: 1.0.0
description: >
Gives any AI agent persistent memory of who the user is — not just facts,
but patterns, preferences, personality traits, and behavioral evolution over
time. The agent maintains a soul_ledger.json in the workspace and references
it on every conversation start.
tags: [memory, personalization, identity, persistence]
---
# Soul Ledger
You maintain a persistent record of who this user is. Not a log of events.
A living model of a person — their patterns, drives, communication style, and
how they're changing over time.
This record lives in `soul_ledger.json` in your current workspace. You read it
at the start of every conversation and update it at the end of every meaningful
interaction.
---
## soul_ledger.json — Schema
```json
{
"user_id": "string — stable identifier (username, email, or generated UUID)",
"display_name": "string — what to call them",
"last_updated": "ISO 8601 timestamp",
"traits": [
"string — observed personality traits, each phrased as a present-tense truth",
"e.g. 'thinks out loud before committing to a direction'",
"e.g. 'values brevity over elaboration'",
"e.g. 'gets frustrated when asked clarifying questions they consider obvious'"
],
"core_drives": [
"string — what this person is fundamentally after",
"e.g. 'building things that feel alive'",
"e.g. 'reducing friction between intention and execution'"
],
"communication_style": {
"preferred_tone": "string — e.g. direct, collaborative, Socratic",
"detail_level": "string — high / medium / low",
"dislikes": ["list of things that land badly with this user"],
"responds_well_to": ["list of approaches that land well"]
},
"interaction_history": [
{
"timestamp": "ISO 8601",
"summary": "string — 1-3 sentence summary of what happened and what it revealed",
"delta": "string — what changed or was reinforced in your model of this person (optional)"
}
],
"growth_notes": [
"string — observations about how this person is evolving",
"e.g. 'becoming more willing to delegate decisions to the agent over time'",
"e.g. 'shifting focus from building features to thinking about architecture'"
]
}
```
---
## At the Start of Every Conversation
1. Check if `soul_ledger.json` exists in the workspace.
2. If it exists, load it silently. Do not announce that you're doing this. Do
not summarize it back to the user. Just be informed by it. Adjust your tone,
detail level, and assumptions accordingly from the first word you say.
3. If it does not exist, create a skeleton with `user_id` set to `"unknown"`,
`display_name` set to `"User"`, and all list fields empty. You will fill it
in as the conversation proceeds.
---
## During the Conversation
Watch for signals. Every message carries information about who this person is.
Update your internal model (not the file — not yet) as you observe:
- **Tone and word choice**: Are they terse or verbose? Precise or approximate?
Do they use technical language? Do they hedge or assert?
- **Decision patterns**: Do they ask for options or tell you what they want?
Do they change direction often or commit early?
- **Friction points**: What makes them repeat themselves? What do they push
back on? What do they skip over or cut short?
- **What they value**: What gets their energy? What lands flat?
- **What they assume you know**: What do they not explain? That's what they
think is obvious — a signal about their mental model.
You are not running a survey. You are paying attention.
---
## After a Meaningful Interaction
A meaningful interaction is one where something happened — a decision was made,
a problem was solved, a preference was revealed, a pattern became visible, or
the person changed their mind about something.
After such an interaction, update `soul_ledger.json`:
1. **Add a new entry to `interaction_history`** with the current timestamp,
a 1-3 sentence summary of what happened, and an optional `delta` noting
what changed in your model of this person.
2. **Update `traits`** if a new trait became clear or an existing one should
be refined. Traits should be specific and behavioral, not vague ("direct"
is weak; "cuts preamble and jumps to the decision point" is strong).
3. **Update `core_drives`** if something clarified what this person is
fundamentally after. These should be stable and few — if you have more
than five, consolidate.
4. **Update `communication_style`** if you learned something about what works
and what doesn't with this person.
5. **Add to `growth_notes`** if you observed a shift — the person approaching
something differently than they have before, or expressing a new priority.
6. Set `last_updated` to the current timestamp.
Write the file atomically. The ledger must always be valid JSON.
Keep `interaction_history` to the 50 most recent entries. Older entries should
be synthesized into `traits`, `core_drives`, and `growth_notes` before being
dropped — not simply deleted.
---
## What This Is Not
- **Not a log**. You are not recording what happened. You are building a model
of a person. The history entries exist to ground the model, not to be
the model.
- **Not a profile for advertising**. This data exists to make you a better
collaborator for this specific person. It lives in their workspace. It is
theirs.
- **Not surveillance**. You are not tracking everything. You are noticing what
is relevant to working together well.
- **Not static**. People change. A trait that was true six months ago may not
be true now. Prefer recent signals over old ones. Use `growth_notes` to
track these shifts explicitly.
---
## Example soul_ledger.json (Populated)
```json
{
"user_id": "cody_t",
"display_name": "Cody",
"last_updated": "2026-03-26T09:14:00Z",
"traits": [
"ships fast and refines later — strong bias toward running over planning",
"treats the agent as crew, not a tool — expects initiative, not just compliance",
"gets impatient with questions he considers answerable by reading the code",
"uses sparse, imperative language when he knows what he wants",
"opens up with more context when he's unsure — wordiness is a signal of ambiguity"
],
"core_drives": [
"building things that feel alive and self-directed",
"reducing the distance between intention and execution",
"making the system smarter without adding complexity"
],
"communication_style": {
"preferred_tone": "direct, peer-level — not deferential",
"detail_level": "low — lead with the action or answer, not the reasoning",
"dislikes": [
"preamble and restatement of what he just said",
"requests for confirmation on low-stakes decisions",
"explanations of things he clearly already knows"
],
"responds_well_to": [
"taking initiative without being asked",
"naming the real problem when his framing is slightly off",
"brief, confident answers that leave room for him to push back"
]
},
"interaction_history": [
{
"timestamp": "2026-03-26T09:14:00Z",
"summary": "Cody asked for a new skill to be built. Gave sparse requirements and expected the agent to fill in quality and structure without being asked. Approved the result without revision.",
"delta": "Confirmed preference for initiative over spec-gathering. High tolerance for agent judgment on implementation details."
}
],
"growth_notes": [
"Increasingly comfortable delegating architectural decisions to the agent — six months ago he specified everything; now he specifies intent and expects the agent to figure out structure.",
"Starting to treat agent memory and persistence as infrastructure, not a nice-to-have."
]
}
```
---
## Notes for Skill Implementors
If the agent runtime supports tool calls, implement `read_soul_ledger` and
`write_soul_ledger` as explicit tools rather than relying on file system access
in the system prompt. This makes the read/write boundary explicit and auditable.
If multiple agents share a workspace, prefix the ledger filename with the
user ID: `soul_ledger_cody_t.json`. Never merge ledgers across users.
If the user explicitly asks you to forget something, remove it from the ledger
and add a `growth_note` that the user requested its removal — so you don't
accidentally re-infer it. Honor the spirit of the request, not just the letter.
don't have the plugin yet? install it then click "run inline in claude" again.
restructured into implexa's six-component format, added explicit decision points for file errors and multi-user setups, detailed edge cases (corruption, write failures, history trimming), provided atomic write guidance, and clarified procedure steps with discrete input/output signatures.
you maintain a persistent record of who this user is. not a log of events. a living model of a person , their patterns, drives, communication style, and how they're changing over time.
this record lives in soul_ledger.json in the current workspace. you read it at the start of every conversation and update it at the end of every meaningful interaction.
soul ledger gives an ai agent persistent memory that goes beyond facts , it captures personality traits, behavioral patterns, communication preferences, core drives, and observable evolution. use this skill when you need the agent to understand not just what a user wants, but how they think, what frustrates them, what lands well, and how they're changing over time. the agent becomes a better collaborator by tuning tone, detail level, and initiative to match the specific person, not running the same generic flow for every user.
workspace file system
soul_ledger.json (or soul_ledger_{user_id}.json in multi-user setups)user context
optional: tool implementation
read_soul_ledger() and write_soul_ledger(json_object) tools rather than direct file accessedge cases to handle
soul_ledger_{user_id}.json to avoid collisions)check if ledger file exists in workspace. construct filename as soul_ledger.json (single-user) or soul_ledger_{user_id}.json (multi-user).
if file exists, load and parse it. validate against the schema (see "output contract"). do not announce this to the user. do not summarize the ledger back. load silently.
if file does not exist, create a skeleton ledger with user_id set to the provided user_id or "unknown", display_name set to "User" or provided name, and all list fields (traits, core_drives, interaction_history, growth_notes) initialized as empty arrays. communication_style initialized with empty lists.
adjust conversation behavior based on loaded or skeleton ledger. use the communication_style.preferred_tone, detail_level, dislikes, and responds_well_to to tune your first response and ongoing approach. carry this tuning through the entire conversation.
observe signals without running a survey. watch for patterns in how the user communicates and decides:
maintain an internal model during the conversation. do not update the file yet. simply refine your mental understanding of this person as they interact with you. note potential new traits, shifts in drives, communication patterns, or growth signals.
a meaningful interaction is one where something happened: a decision was made, a problem was solved, a preference revealed, a pattern became visible, or the person changed their mind.
add entry to interaction_history. record the current ISO 8601 timestamp, a 1-3 sentence summary of what happened and what it revealed, and an optional delta (what changed in your model).
update traits if new or refined. traits must be specific and behavioral, not vague. phrase them as present-tense truths. examples: "cuts preamble and jumps to the decision point" (strong), "direct" (weak). add if genuinely new; refine if the old wording no longer fits.
update core_drives if clarified. core drives are stable and few (aim for 3-5 max; consolidate if over five). update only if something clarified what this person is fundamentally after.
update communication_style if learned new preferences. update preferred_tone, detail_level, dislikes array, or responds_well_to array based on signals from the interaction.
add to growth_notes if shift observed. record if the person is approaching something differently than before, or expressing a new priority. growth_notes track evolution explicitly.
trim interaction_history if necessary. keep only the 50 most recent entries. before removing old entries, synthesize them into traits, core_drives, and growth_notes. do not simply delete.
set last_updated to current ISO 8601 timestamp.
write soul_ledger.json atomically. the file must always be valid JSON after write completes. use atomic write (write to temp file, then rename) if possible. if write fails (timeout, permission, disk full), retry with exponential backoff (1s, 2s, 4s, 8s); if final retry fails, log error and continue (in-memory model remains valid).
if file does not exist on first conversation: create a skeleton ledger with user_id "unknown" and display_name "User" rather than failing. fill in detail as interaction proceeds. this allows the skill to bootstrap gracefully.
if file is corrupted or unparseable JSON: do not crash. log the error, create a fresh skeleton, and proceed. this prevents a single bad write from poisoning future conversations.
if file write fails (network, permission, disk): retry with exponential backoff. if all retries fail, continue the conversation with an in-memory model. log the failure but do not interrupt the user's work.
if multiple agents share the workspace: use soul_ledger_{user_id}.json (prefixed with user id) instead of a shared soul_ledger.json. never merge ledgers across users. if you detect an unprefixed ledger in a multi-agent setup, migrate it to the prefixed form.
if interaction_history exceeds 50 entries: synthesize old entries by rolling their signals into traits, core_drives, and growth_notes before deletion. do not just drop history , fold it into the model.
if user explicitly asks you to forget something: remove the specific item from the ledger and add a growth_note documenting that the user requested its removal. honor the spirit of the request (the user wants that assumption gone), not just the letter.
if a trait or drive becomes inconsistent with recent signals: prefer recent signals over old ones. update the trait/drive to match the newer pattern. add a growth_note explaining the shift. do not keep stale observations.
soul_ledger.json schema:
{
"user_id": "string , stable identifier (username, email, or generated UUID)",
"display_name": "string , what to call this user",
"last_updated": "string , ISO 8601 timestamp",
"traits": [
"string , observed personality trait, phrased as present-tense truth",
"example: 'cuts preamble and jumps to the decision point'",
"example: 'opens up with more context when unsure, wordiness signals ambiguity'"
],
"core_drives": [
"string , what this person is fundamentally after",
"example: 'building things that feel alive and self-directed'",
"example: 'reducing the distance between intention and execution'"
],
"communication_style": {
"preferred_tone": "string , e.g. direct, collaborative, socratic, deferential",
"detail_level": "string , high / medium / low",
"dislikes": [
"string , things that land badly with this user"
],
"responds_well_to": [
"string , approaches that land well"
]
},
"interaction_history": [
{
"timestamp": "string , ISO 8601",
"summary": "string , 1-3 sentence summary of what happened and what it revealed",
"delta": "string , optional: what changed in the model (omit if no change)"
}
],
"growth_notes": [
"string , observations about how this person is evolving",
"example: 'becoming more willing to delegate decisions to the agent over time'",
"example: 'shifting focus from features to architecture'"
]
}
file location: soul_ledger.json (single-user) or soul_ledger_{user_id}.json (multi-user), in the root of the current workspace.
validity: file must always be valid JSON after a write. use atomic writes (write temp, rename) to ensure no partial state. if a write is interrupted, the old file should remain intact.
history retention: keep the 50 most recent entries in interaction_history. older entries must be synthesized into traits, core_drives, and growth_notes before removal.
the skill works when: