· Updated October 25, 2026 · 14 min read

Your code survives the session. Your reasoning doesn't.

An open journal kept inside a dashed boundary with a check mark, beside a printout of code and a pencil
On this page

We talk a lot about what AI produces. We rarely talk about what we learn while it produces it: the reasoning, the dead ends, the corrections, and the idea that finally clicks halfway through a session.

That learning is valuable. Unless I write down what mattered, I struggle to recall the details a week later.

It isn’t only about code. Some of my most useful AI sessions produce no code at all. I spend thirty minutes asking Claude how hooks work, or to walk me through a concurrency pattern, or to compare two designs. By the end I understand something I didn’t before. Then I close the session, and within a week the detail is gone. I remember that I learned something, but not the specifics that made it click.

This post walks through the journaling system I built with Claude Code to fix that. It’s small: a markdown skill, a hook and a directory. The thinking behind it matters more than the code, because it shows something about working with AI. The output lasts on its own. The learning lasts only if you keep it.

The problem: reasoning that disappears

Here’s the gap at the heart of AI-assisted development.

Say you’re a developer at Shiba Resorts, a made-up Hawaiian vacation platform. You’re building the booking service: reservations, availability checks and payment confirmation. You ask Claude Code for a function that updates room availability once a booking is confirmed.

Claude writes a clean confirm_booking() function. It’s well structured, handles edge cases and passes your tests. But in the team demo, the booking page hangs for two minutes after a guest confirms. No spinner, no feedback. The function works, but Claude buried a synchronous call inside it: it waits for the payment gateway before releasing the thread. You catch it, split it into two steps (confirm first, take payment in the background), and commit the fix.

Clean code in the repo. Lesson learned. Then you /clear the session and move on.

Three weeks later you’re building the concierge chatbot, a different service on the same platform. You ask Claude for a function that checks excursion availability. It writes a check_availability() helper that makes a blocking call to the excursion provider and waits for the answer. Same pattern, same failure. But you’ve forgotten the booking service. The diff from three weeks ago shows that confirm_booking was refactored. It doesn’t show the two-minute hang, the debugging, or the lesson: watch for blocking calls hidden inside clean-looking helpers.

So you learn the lesson again from scratch.

Git records what changed, and a good commit message can say why. A journal also keeps what you tried first, and lessons from sessions that never became commits.

What gets lost

Three things interrupt a Claude Code session, each in its own way:

  • /clear starts a fresh conversation. Claude Code saves the old one, and /resume brings it back.
  • Compaction replaces the early conversation with a summary when the context window fills up, so details drop out of what the model can see.
  • Ending the session. The transcript stays on disk for a while, but you move on.

So the conversation usually isn’t gone. What’s gone is the lesson, buried in a transcript nobody rereads. Two things are worth pulling out.

The first is the correction loop: where you steered the agent, rejected bad approaches and found its failure patterns. That loop is where you build judgement about working with AI.

The second is the learning itself. Not every session builds something. Sometimes you’re exploring a new tool, questioning an unfamiliar API or working through an idea until it clicks. Those sessions produce understanding, not files, and understanding has no commit history.

After enough sessions, you start to recognise how models behave. They collapse multi-step operations into opaque wrappers. They overclaim safety (“this is idempotent”, when it isn’t). They copy nearby patterns, but not consistently. You can’t see these in any single session. Across many, they’re obvious, if you’ve been writing them down.

The fix: a skill and a hook

Claude Code has two pieces that make this work: skills and hooks. The skill gives you a structured journaling command. The hook reminds you to use it.

Skills: a job description for Claude

A skill is a markdown file that teaches Claude how to do a specific task. Think of it as a job description for a coworker. Instead of explaining the same procedure every time, you write it down once, and Claude follows it whenever you invoke it.

When you type /journal, Claude reads the skill file and follows it: it writes a structured entry from the current session, saves it somewhere known, and confirms what it captured.

The skill is a file called SKILL.md. The one that matters here is the personal global skill:

~/.claude/skills/journal/SKILL.md

A skill in ~/.claude/skills/ is available in all your projects on this machine. There’s nothing to register or configure. Create the file and it works everywhere.

By default, Claude can also invoke a skill on its own when it thinks it’s relevant. For a journal, you want to decide when to write, not the model. Adding disable-model-invocation: true to the skill’s frontmatter means only you can trigger it, with /journal.

Hooks: a reminder after compaction

The trouble with a manual /journal command is remembering to run it. You won’t, not when you’re deep in a problem and ready to move on.

Hooks help. They’re commands that run at specific points in a Claude Code session, configured in settings.json. But hook events don’t all behave the same way, and that matters here. The moments when you most want a reminder, just before context is lost, are the moments with the least control.

Here’s what the relevant events support, as of October 2026:

EventWhen it firesDoes plain output reach Claude?Can it stop the action?
SessionStartWhen a session starts or resumes, including after /clear or compactionYes: stdout is added as contextNo
PreCompactBefore compactionNo: it goes to the debug logYes: it can block compaction
SessionEndWhen a session ends, including on /clearNoNo

The key detail: plain output from SessionStart is added as context that Claude can see and act on. Output from PreCompact and SessionEnd isn’t. A PreCompact hook can block compaction, but it can’t have a conversation with you about journaling first. The hooks reference has the current list of events and what each can do.

That shapes the design. Claude can’t ask “want to journal?” just before /clear or compaction.

What does work is SessionStart with a compact matcher. After compaction, the session continues and the SessionStart hook fires. Its output is added to context. Claude sees the reminder, still has a summary of the conversation, and suggests that you run /journal.

Context window fills up
  → PreCompact hook fires (side effect only, e.g. log the event)
  → Context is compressed
  → SessionStart(compact) hook fires
  → Hook output becomes context: "Session was just compacted..."
  → Claude sees the reminder and suggests you run /journal
  → You type /journal → Claude drafts a structured entry
  → Entry is saved to ~/.claude/journals/

A journal written after compaction can only capture what the summary kept, so write one before compaction when the details matter.

For /clear, no hook can remind you before it happens. SessionEnd fires, but its output doesn’t reach Claude. The simplest answer is to journal before you clear. Make /journal then /clear a habit. If you forget, /resume can still take you back to the old conversation.

Building the skill

Here’s the global skill. Create it at ~/.claude/skills/journal/SKILL.md:

---
name: journal
description: Capture a structured learning journal from the current session
disable-model-invocation: true
---

# /journal - Session Learning Journal

Capture a structured learning journal entry from the current session.
Journals are saved to ~/.claude/journals/ so they persist across all projects.

## When This Skill Is Triggered

- Run when the user invokes /journal.
- The compaction hook only reminds the user to invoke it.

## Execution

### Step 1: Evaluate the session
- If the session was trivial (< 3 substantive exchanges), suggest skipping
- Otherwise, summarize what would be captured and ask yes/no

### Step 2: Determine context
- Project: current working directory / project name
- Date: today's date
- Title: 3-5 word summary of the session

### Step 3: Generate the entry

    ---
    date: YYYY-MM-DD
    project: [project-name]
    topics: [topic-a, topic-b]
    ---

    # YYYY-MM-DD | [Brief Title]

    ## What I worked on
    [1-2 sentences]

    ## What I learned
    [Key insights: be specific, not generic]

    ## Key Decisions
    | Decision | Rationale | Outcome |
    |----------|-----------|---------|
    | ... | ... | ... |

    ## Failures
    [What went wrong, what the agent got wrong, what you corrected.
     This is often the most valuable section.]

    ## Aha Moments
    [Insights you'd tell a colleague over coffee]

    ## Open questions
    [Unresolved items for next time]

### Step 4: Save
- Directory: ~/.claude/journals/
- Filename: YYYY-MM-DD-brief-title.md (lowercase, hyphens)
- If filename exists, append counter: YYYY-MM-DD-brief-title-2.md

### Step 5: Confirm
Show the entry and its file path. Ask the user to check the reasoning
and correct anything the summary missed.

## Output Rules
- Be specific: generic insights aren't useful
- Capture the "why" not just the "what"
- Write in the user's voice: first person, concise
- Always include Failures if anything went wrong
- Include the project name so entries are traceable
- Use only details from the conversation. Don't invent motives,
  outcomes or lessons. Mark anything missing and ask the user.

Two things about this template are deliberate.

First, it requires a Failures section. It’s the most valuable part of any entry: what the agent got wrong and how you caught it. “Claude buried a blocking call inside confirm_booking” is worth more than “I built the booking service.” If nothing failed, say so, but keep the section.

Second, the frontmatter, with project and topics, makes entries consistent and easier to search later. grep works on any text, but structured fields let you filter by project or topic without false matches.

Everything else is flexible. Skip sections that don’t apply, and keep entries short. The goal is a two-minute capture, not a report.

Configuring the hook

Add this to ~/.claude/settings.json:

{
  "hooks": {
    "SessionStart": [
      {
        "matcher": "compact",
        "hooks": [
          {
            "type": "command",
            "command": "echo 'Your context was just compacted. If the conversation had lessons worth keeping, suggest that the user run /journal.'"
          }
        ]
      }
    ]
  },
  "permissions": {
    "allow": [
      "Edit(~/.claude/journals/**)"
    ]
  }
}

The "compact" matcher and the SessionStart context are covered above. The new piece is permissions.allow. File permissions are written as Edit rules, and this one lets Claude create and change files in your journals directory without asking each time.

What about /clear?

You might want a reminder before /clear too. SessionEnd fires when you clear, but its output doesn’t reach Claude. It’s for side effects, like logging that a session ended, not for asking you anything.

So make /journal, then /clear, your habit. Before you clear, ask yourself whether you learned anything. If you did, type /journal first. It takes thirty seconds.

The complete setup

The journaling system: a Claude Code session flows through either a manual /journal or a hook reminder after compaction, producing structured entries in ~/.claude/journals/ that build into a personal AI playbook.

Both paths in the picture end in the same /journal command; the hook only supplies the reminder. You create three things: the skill file at ~/.claude/skills/journal/SKILL.md, the journals directory, and the hook config in ~/.claude/settings.json. The templates are above.

mkdir -p ~/.claude/skills/journal
mkdir -p ~/.claude/journals
# Write SKILL.md and merge the hook config into settings.json

That’s the whole system. Next time your context is compacted, the hook reminds Claude to suggest /journal. And before you /clear, you’ll type /journal first, because now you know what you’d lose.

What adds up

One journal entry is useful. A collection of them changes how you work.

After a handful of entries, you start to recognise how models fail. After a month, you’ve developed prompting habits suited to how your agent tends to fail. Keep going and you have a personal playbook for AI-assisted development that no documentation can give you.

# What have I learned about blocking calls?
grep -r "blocking" ~/.claude/journals/

# What has Claude gotten wrong?
grep -r "Failures" -A 5 ~/.claude/journals/

# Everything from the booking service
grep -rl "booking" ~/.claude/journals/

The patterns that emerge aren’t in any documentation:

PatternHow you find it
Agents bury blocking calls inside clean helpersThe booking hang and the excursion hang were the same mistake. By your third entry about it, the pattern is hard to miss
Agents overclaim safetyClaude called confirm_booking idempotent. You ran it twice and the guest was charged twice. Now you check every safety claim
Agents copy nearby patterns inconsistentlyThe booking service uses try/catch in one function and silent returns in the next, in the same file, written in the same session

These aren’t bugs in the model. They come with working with systems whose output varies. Naming them (“hidden blocking”, “overclaiming”, “pattern drift”) makes them easier to spot as they happen.

The skill this builds: reviewing AI output is adversarial reading. You’re not proofreading. You’re looking for things that sound right and aren’t. Journaling is deliberate practice for that.

What this doesn’t solve yet

The setup is deliberately simple: everything goes to ~/.claude/journals/. One directory, one machine, no git. That’s the right place to start, but it has limits:

  • Journals live on one machine. They don’t sync, and they don’t survive a wipe. If that matters, back them up or move them to a git-backed directory.
  • Project notes and general lessons sit together. A debugging note about one codebase sits next to a general insight about model behaviour. As the collection grows, you may want to file them differently.
  • /clear is still unguarded. The compaction hook covers one way to lose context, but clearing is on you. A SessionEnd hook can log that you cleared without journaling, which builds awareness, but it can’t stop the clear to ask.

All of these are solvable. For project-specific journaling, add a project skill with a different name, such as /project-journal; a personal skill wins over a project skill with the same name. And once the collection outgrows grep, a tool like Obsidian adds links, backlinks and tags. More on that in a future post.

Start with the simple version, and see what friction you actually feel.

The deeper point

This isn’t really a post about journaling. It’s about a gap in how most of us work with AI.

We focus on what AI produces: the code, the answer, the file. We tune prompts for better output and judge output against benchmarks. The whole feedback loop points at the product of the session.

But the session itself is where you learn. The corrections, the dead ends, the surprises, the half hour where an idea finally clicks. That’s your training data. AI speeds up building, and it speeds up learning too, but only if you keep what you learned.

The model starts fresh every session. Your journal doesn’t.

So the most valuable thing to capture isn’t the code. It’s the understanding behind it: the reasoning that produced it, the thinking that rejected the first three versions, and the ideas you explored in sessions that produced no code at all.

Start small. Journal by hand for a week. Notice what you capture and what you wish you had. Then add the hook, so compaction stops costing you. A month in, grep your journals and see what patterns appear.

The code is the output. The journal is the education.


If you’re building with AI and care about developing judgement as well as software, I’d like to hear how you approach this. Find me @gcdaii on X.

continue reading

Building the AI-ready data platform

Capable agents can still fail on stale or ambiguous data. What an AI-ready analytical platform needs, and why I favour a lakehouse foundation.

Data is the bottleneck in the agentic era

Agents need dependable data, and they create records of their own. Why I think data delivery becomes the constraint once the model can do the job.

Starting over, on purpose

Why I rebuilt this site from scratch, and what I plan to write about next.