CLAUDE LABJP
ENTERPRISE — Claude Enterprise adds richer admin analytics, model-level entitlements, and spend alertsDEVICES — Trusted Devices arrives for Team and Enterprise, verifying devices before remote Claude Code sessionsCODE — Claude Code adds org default models, readable session names, and clickable file attachmentsMODEL — Claude Sonnet 5 is the default across all plans at $2/$10 per million tokens through August 31FABLE 5 — Claude Fable 5 returns worldwide from July 1 after export controls lift, with a new cybersecurity classifierLIMITS — Claude Code weekly usage limits are up 50% through July 13; Claude Science applications close July 15ENTERPRISE — Claude Enterprise adds richer admin analytics, model-level entitlements, and spend alertsDEVICES — Trusted Devices arrives for Team and Enterprise, verifying devices before remote Claude Code sessionsCODE — Claude Code adds org default models, readable session names, and clickable file attachmentsMODEL — Claude Sonnet 5 is the default across all plans at $2/$10 per million tokens through August 31FABLE 5 — Claude Fable 5 returns worldwide from July 1 after export controls lift, with a new cybersecurity classifierLIMITS — Claude Code weekly usage limits are up 50% through July 13; Claude Science applications close July 15
Articles/Claude Code
Claude Code/2026-07-06Advanced

Which Nightly Job Wrote This Commit? Threading a Correlation Key Through Claude Code's Readable Session Names

When you run unattended nightly jobs across several repositories, you lose track of which session produced which commit. Here is how I redesigned Claude Code's readable session names into a correlation key that ties commits, logs, and sessions into a single thread — with real numbers.

Claude Code182session management4unattended automation4indie developer18traceability

Premium Article

Last week I was scrolling through a git log over coffee when I stopped. One of my wallpaper app repositories had a changelog entry written by the previous night's job, and it referenced an old version number.

The mistake itself was small. What made it painful was that I had no idea which run had written it. I run a handful of my indie app repositories through Claude Code every night in headless mode — dependency bumps, changelog drafts, Crashlytics crash summaries, AdMob mediation config checks. On a busy night that is twelve sessions. The only handle on any given session was an opaque UUID, and nothing about the session's identity survived into the commit message.

In the end, cross-referencing log timestamps against commit times to find the culprit took about fifteen minutes. Finding the run that caused the problem took longer than fixing the problem itself.

Now that Claude Code assigns readable session names, this whole situation can be redesigned. The key was to treat the name as a single meaningful thread rather than decoration.

Treating the name as a correlation key

If you leave the session name as a cosmetic label, it does nothing for you the next morning. What I changed was to design the name as a correlation key — a shared heading that lets you line up separate records against each other after the fact.

Here is the shape of the key I settled on.

PartExamplePurpose
App namewallpaper-zenWhich repository the work is in
Task typechangelog-draftWhat the run does
JST date20260706Which nightly batch
Short random valuea1b2c3d4Collision guard for same-minute runs

Joined together, that becomes wallpaper-zen-changelog-draft-20260706-a1b2c3d4. You stamp this one string, in the same form, into all three places: the session name, the commit, and the log file name. From any one of those points, you can reach the other two. Tracing becomes a grep instead of archaeology.

Building the key in a run wrapper

First, a wrapper that generates the correlation key every time it launches a single nightly job and passes it in as the session name.

#!/usr/bin/env bash
# run-nightly.sh — run one nightly job with a readable correlation key
set -euo pipefail
 
APP="$1"        # e.g. wallpaper-zen
TASK="$2"       # e.g. changelog-draft
 
# correlation key = app-task-JSTdate-shortrandom
# Always make the timezone explicit. A bare date is UTC-based and
# drifts to the previous day for late-night runs.
DATE_JST="$(TZ=Asia/Tokyo date +%Y%m%d)"
SHORT="$(head -c4 /dev/urandom | od -An -tx1 | tr -d ' \n')"
export CC_SESSION_NAME="${APP}-${TASK}-${DATE_JST}-${SHORT}"
 
LOG_DIR="$HOME/nightly-logs/${DATE_JST}"
mkdir -p "$LOG_DIR"
LOG="${LOG_DIR}/${CC_SESSION_NAME}.log"
 
echo "[$(TZ=Asia/Tokyo date +%H:%M:%S)] start ${CC_SESSION_NAME}" | tee -a "$LOG"
 
# Run Claude Code headless and pass this key as the readable session name.
# The point is to hand CC_SESSION_NAME to whatever option sets the session name.
# If your version cannot set the session name directly, the commit trailer and
# the log side below still complete the correlation on their own.
claude -p "$(cat "prompts/${TASK}.md")" \
  --session-name "$CC_SESSION_NAME" \
  2>&1 | tee -a "$LOG"
 
echo "[$(TZ=Asia/Tokyo date +%H:%M:%S)] done ${CC_SESSION_NAME}" | tee -a "$LOG"

Two things matter here. First, the log file name itself is the correlation key. Second, CC_SESSION_NAME is exported as an environment variable. That variable is the bridge to the commit hook next.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A correlation key built from app name, task, JST date, and a short random value, plus how to avoid the date drift a bare date command causes
A prepare-commit-msg hook that stamps the session name into commits, and a trace script that walks from a commit to its log with a single grep
Cutting incident tracing from about 15 minutes to roughly 20 seconds, and the concrete fixes for key collisions and timezone drift
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Claude Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Claude Code2026-07-04
A 1M Context Window Is the New Default — So I Built an Admission Policy Instead of Filling It
Sonnet 5 is now the Claude Code default and native 1M context is standard. The hard errors disappeared, but a quieter kind of degradation took their place. Here is how I made it visible with a probe, plus an admission policy and an effective-token-cost view — with working code and my own measurements.
Claude Code2026-07-02
Which Model Ran Last Night's Unattended Session? Building Model Attribution and Default-Drift Detection After the Sonnet 5 Switch
Claude Code's default model switched to Sonnet 5, and unpinned headless runs changed models silently. Here is a working design for extracting the actual model from run output, appending an atomic run record, and deciding per task lineage whether to pin or follow the default.
Claude Code2026-07-01
Don't Accept an Agent's Numbers and Citations As-Is — A Verification Gate Built on a Dedicated Auditor Subagent
A design that verifies every number and citation in an agent-generated summary using a separate subagent before accepting it — with working TypeScript for deterministic recomputation and fail-closed source matching.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →