# Nightcap

> Nightcap, a nightly agent journal. Reads recent Claude Code and Codex transcripts off disk, skips trivial sessions, and writes one first-person narrative journal entry per real session, like a handwritten end-of-day journal. Use when the user wants an agent session journal, a daily log of AI sessions, transcript summaries, "what did i work on today/this week", to set up or troubleshoot nightcap,…

- **Type:** Skill
- **Install:** `agentstack add skill-tommylower-cortex-nightcap`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [tommylower](https://agentstack.voostack.com/s/tommylower)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [tommylower](https://github.com/tommylower)
- **Source:** https://github.com/tommylower/cortex/tree/main/agent-workflows/nightcap

## Install

```sh
agentstack add skill-tommylower-cortex-nightcap
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# nightcap

A stdlib-only Python script that turns raw agent transcripts into a narrative journal. Every night (or on demand) it:

1. discovers recent sessions: `~/.claude/projects/*/*.jsonl` (skipping `agent-*` subagent files) and `~/.codex/sessions/**/rollout-*.jsonl`, filtered by file mtime within a lookback window (default 3 days)
2. parses each transcript down to user/assistant text, filtering noise (command wrappers, system reminders, environment context). grabs cwd (first-seen wins, since cwd can drift mid-session), timestamps, model, and the session title
3. applies a substance filter: a session needs ≥2 user messages and ≥200 user chars, or 1 message ≥1500 chars. one-shot trivia never gets journaled
4. condenses to ~24k chars (user messages truncated at 700, assistant at 400, middle trimmed)
5. summarizes via `claude -p` into 1-3 first-person paragraphs in the owner's voice, using whichever model is configured (opus by default)
6. writes one markdown entry per session and records it in `/.state.json` so nothing is journaled twice. failed summaries stay pending and retry next run

Filenames are `YYYY/YYYY-MM-DD-HHMM--.md`, keyed on session **start** time. Nice side effect: duplicate transcripts from resumed sessions collapse into one entry.

A `NIGHTCAP-SUMMARIZER` sentinel leads the summarizer prompt and is in the noise filters, so nightcap never journals its own headless runs.

## entry format

```markdown
# 2026-06-10 — Integrate GitHub repository as a skill

- date: 2026-06-10, 15:18 to 15:31
- agent: Claude Code (claude-opus-4-8)
- project: `/Users/you/dev/somerepo`
- chat: `claude --resume   (from /Users/you/dev/somerepo)`
- transcript: `~/.claude/projects/.../.jsonl`

1-3 paragraphs of first-person narrative: tone and energy, the kind of
thinking (debugging, designing, planning), what the session was actually
about, and how the agent helped.
```

The `chat:` line is a working resume command (`claude --resume ` / `codex resume `), so every entry links back to the live conversation.

## setup

If you are an agent setting nightcap up for someone, ask them two things before scheduling: their **voice** (or derive it from how they write) and their **model**. Nightcap runs on any model the `claude` CLI accepts:

- `opus` — best narrative quality and voice adherence. the default
- `sonnet` — balanced quality and cost
- `haiku` — cheapest and fastest, for heavy session volume; expect looser voice adherence
- or any full model ID

Write the choice into the `model` key of the config.

```bash
# 1. try it
scripts/nightcap.py --dry-run          # list what would be journaled
scripts/nightcap.py --limit 1          # write one entry to check the voice

# 2. personalize (optional but recommended)
mkdir -p ~/.config/nightcap
cp assets/config.example.json ~/.config/nightcap/config.json
# then edit: your name, speaker label, voice rules, journal location, model

# 3. schedule nightly (macOS launchd, 23:30 or next wake)
SCRIPT="$(pwd)/scripts/nightcap.py"
sed -e "s|__SCRIPT_PATH__|$SCRIPT|g" -e "s|__HOME__|$HOME|g" \
  assets/local.nightcap.plist > ~/Library/LaunchAgents/local.nightcap.plist
launchctl load ~/Library/LaunchAgents/local.nightcap.plist
```

On Linux, schedule the same command with cron or a systemd timer instead.

## configuration

`~/.config/nightcap/config.json` (or `--config `, or `NIGHTCAP_CONFIG` env var). Every key is optional:

| key | default | meaning |
| --- | --- | --- |
| `journal_dir` | `~/notes/agent-journal` | where entries and `.state.json` live |
| `name` | `the user` | who the journal belongs to; the summarizer writes as this person |
| `speaker_label` | `USER` | label for your lines in the condensed transcript (use your first name) |
| `voice` | plain understated prose | stylistic rules for the narrative (casing, punctuation, tone) |
| `model` | `opus` | model for `claude -p --model`. any model the CLI accepts (opus, sonnet, haiku, or a full model ID) |
| `claude_bin` | found on PATH | explicit path to the claude CLI if it isn't on launchd's PATH |

Structural rules are fixed regardless of voice: first person, past tense, 1-3 short paragraphs, no headers, no lists, no invented specifics.

## usage

```bash
scripts/nightcap.py                 # sweep now
scripts/nightcap.py --dry-run       # preview pending sessions
scripts/nightcap.py --days 7        # widen the lookback window
scripts/nightcap.py --limit 3       # cap entries written this run
```

Journal entries are personal: keep `journal_dir` out of any public repo (gitignore it if it lives inside one).

## troubleshooting

- no entries written: check `--dry-run` output. sessions already in `.state.json` or below the substance thresholds are skipped silently
- summarizer failures: the run logs to stderr (`~/Library/Logs/nightcap.log` under launchd) and retries those sessions next sweep
- wrong or missing claude CLI under launchd: set `claude_bin` in the config, launchd's PATH is minimal
- entries in the wrong voice: edit `voice` in the config; the next sweep uses it (already-written entries are not rewritten)

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [tommylower](https://github.com/tommylower)
- **Source:** [tommylower/cortex](https://github.com/tommylower/cortex)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-tommylower-cortex-nightcap
- Seller: https://agentstack.voostack.com/s/tommylower
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
