From vault
Summarize the current coding session. Shows learnings and accomplishments in terminal, appends to today's Obsidian daily note under "## Progress >
How this skill is triggered — by the user, by Claude, or both
Slash command
/vault:devlogThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Log your coding session progress to Obsidian daily notes, organized by project.
Log your coding session progress to Obsidian daily notes, organized by project.
Read ~/.claude/settings.json and extract:
env.OBSIDIAN_VAULT - Path to Obsidian vaultenv.SESSION_EXPORTS_BASE - External storage for session exports (default: ~/.claude/session-exports)If OBSIDIAN_VAULT is not set, display: "Vault not configured. Run /vault first."
Read vault structure from <vault_path>/vault-config.yaml.
Paths used from vault-config.yaml:
daily_notes → Daily Notes folderprojects → Projects folderprocessed_coding → Vault location for lightweight summaries (full exports go to SESSION_EXPORTS_BASE)Section format: ## Progress → ### [[Project Name]]
botThe rating is an optional assessment of how well Claude performed during the session.
Rating scale:
| Rating | Meaning |
|---|---|
| 7 | Exceptional - exceeded expectations |
| 6 | Great - very helpful |
| 5 | Good - solid assistance |
| 4 | Okay - got the job done |
| 3 | Poor - struggled significantly |
| 2 | Bad - mostly unhelpful |
| 1 | Terrible - counterproductive |
Input methods:
/devlog 5 or /devlog 5 --slackAn optional free-text comment providing qualitative feedback about the session. Can be provided inline after the rating (e.g., /devlog 5 great session). If omitted, the user is prompted. Stored as string or null. See Step 4 for full parsing rules.
First, read <vault_path>/vault-config.yaml to get the daily_notes folder name.
Then check if today's daily note exists:
<vault_path>/<daily_notes>/YYYY-MM-DD.md
Use today's date in YYYY-MM-DD format.
If the file does NOT exist:
If the file exists: Continue to Step 1.5.
Determine if the current working directory is a git worktree (e.g., .claude/worktrees/worktree-*):
GIT_DIR=$(git rev-parse --path-format=absolute --git-dir)
GIT_COMMON_DIR=$(git rev-parse --path-format=absolute --git-common-dir)
if [ "$GIT_DIR" != "$GIT_COMMON_DIR" ]; then
IS_WORKTREE=true
MAIN_REPO_PATH=$(dirname "$GIT_COMMON_DIR")
else
IS_WORKTREE=false
MAIN_REPO_PATH=$(pwd)
fi
# Guard: real worktrees always have /worktrees/ in GIT_DIR
[ "$IS_WORKTREE" = true ] && [[ "$GIT_DIR" != */worktrees/* ]] && IS_WORKTREE=false && MAIN_REPO_PATH=$(pwd)
MAIN_REPO_BASENAME=$(basename "$MAIN_REPO_PATH")
# Encoded path for session-exports directory (matches Claude's project-path encoding)
MAIN_PROJECT_PATH=$(echo "$MAIN_REPO_PATH" | sed 's|/|-|g')
IS_WORKTREE=true, MAIN_REPO_PATH points to the main repository rootIS_WORKTREE=false, MAIN_REPO_PATH = CWD (no behavior change)Use MAIN_REPO_BASENAME and MAIN_PROJECT_PATH in subsequent steps instead of CWD-derived values.
Identify which project this session belongs to:
.md files in the Projects folder (<vault_path>/<projects> from vault-config.yaml)MAIN_REPO_BASENAME from Step 1.5 (e.g., personal-toolkit — uses main repo name even when running from a worktree)# Title heading### [[Thought Organizer Agent]])If no matching project found: Use "General" as the project name.
Export session to external storage (outside the vault) for future reference, with a lightweight summary in the vault.
Note: If session identification fails (session ID not resolved AND transcript not found), raise an error and DO NOT CONTINUE
Get current session info:
${CLAUDE_SESSION_ID}
(Claude Code replaces this literal with the actual UUID at skill load time -- no hooks needed)SESSION_ID="<the substituted UUID visible above>"
TRANSCRIPT_PATH=$(find ~/.claude/projects/ -name "${SESSION_ID}.jsonl" -type f 2>/dev/null | head -1)
PROJECT_PATH=$(echo "$TRANSCRIPT_PATH" | sed "s|^$HOME/.claude/projects/||" | sed "s|/${SESSION_ID}.jsonl$||")
TMPBASE="${CLAUDE_CODE_TMPDIR:-/tmp/claude-$(id -u)}"$TMPBASE/ matching the CWD project~/.claude/projects/{project-path}/{session-id}.jsonlVerify with content fingerprinting:
Before proceeding, confirm the transcript actually contains THIS conversation. Multiple sessions can exist for the same project path, and the session ID may point to the wrong one.
Build a session fingerprint (reused in Part B2 -- build it once, store for later):
/stylize, /scribe)Score the candidate transcript by grepping for all fingerprint terms at once:
grep -cE "term1|term2|term3|term4|term5" "$TRANSCRIPT_PATH"
Count how many distinct terms matched (each term that appears at least once = 1 match).
Decide:
Fallback: Content-based session discovery
If the primary transcript fails fingerprinting:
.jsonl files in ~/.claude/projects/{project-path}/ modified in the last 24 hours:
find ~/.claude/projects/{project-path}/ -maxdepth 1 -name "*.jsonl" -mtime -1
grep -cE approach. Track match counts per file.Session ID transcript mismatch detected.
Using transcript {session-id} based on content matching.
Could not identify the correct session transcript.
Please provide the session ID manually.
Detect previous transcripts (recursive with LLM verification):
CRITICAL: Only count REAL continuation references, not casual mentions.
Compaction vs Continuation:
Compaction stays in the same JSONL file (same session ID). It writes a
compact_boundary system message followed by a summary user message. The
summary's "read the full transcript at:" path points to itself (self-reference).
Continuation creates a new JSONL file pointing to the previous file.
When discovery finds a self-referencing path (extracted path == file being searched),
skip it — it's a compaction, not a separate transcript.
A transcript reference is ONLY valid if it appears in a continuation message - either:
Both end with "read the full transcript at:" followed by the path.
DO NOT count:
JSONL Structure Reference: Each line is a JSON object with fields:
type: "user", "assistant", "system", "progress", "queue-operation"message.content: either a string (direct message) or array (tool results)queue-operation type: content is at top level (not nested in message)Step A: Find candidate lines
grep -n "read the full transcript at:" <transcript.jsonl>
Step B: Verify each candidate using JSON structure
For each candidate line, examine the JSON:
type == "user" OR type == "queue-operation"message.content is a string (NOT an array)
For "queue-operation" type: Check content at top level (not nested)"Implement the following plan:" (plan-mode)"This session is being continued" (compaction)grep -o "read the full transcript at: [^\"\\]*\.jsonl"Example verification:
Line 2: {"type":"user","message":{"content":"Implement the following plan:...read the full transcript at: /path/to/abc.jsonl"}}
✓ type == "user"
✓ message.content is a string
✓ Contains "Implement the following plan:"
→ VALID plan-mode continuation → abc.jsonl
Line 4: {"type":"queue-operation","content":"Implement the following plan:...read the full transcript at: /path/to/abc.jsonl"}
✓ type == "queue-operation"
✓ content is a string at top level
✓ Contains "Implement the following plan:"
→ VALID plan-mode continuation → abc.jsonl
Line 356: {"type":"user","message":{"content":[{"type":"tool_result",...}]}}
✓ type == "user"
✗ message.content is an ARRAY (tool_result)
→ SKIP (false positive from grep output)
Grep-based validation (using for-loop to avoid subshell issues):
Note: Do NOT use jq for validation - JSONL lines often contain unescaped control characters (tabs, newlines) that cause jq parse errors. Use grep pattern matching instead.
# IMPORTANT: Do NOT use "grep | while read" - the while loop runs in a subshell
# and output is lost. Use a for-loop over line numbers instead.
for linenum in $(grep -n "read the full transcript at:" "$TRANSCRIPT_PATH" | cut -d: -f1); do
line=$(sed -n "${linenum}p" "$TRANSCRIPT_PATH")
# Validate using grep pattern matching (not jq - avoids control char errors)
# Check for either "user" type OR "queue-operation" type
is_user=$(echo "$line" | grep -c '"type":"user"')
is_queue=$(echo "$line" | grep -c '"type":"queue-operation"')
if [ "$is_user" -eq 1 ]; then
# For user type, content must be a string (not array)
echo "$line" | grep -q '"content":"' || continue
elif [ "$is_queue" -eq 1 ]; then
# For queue-operation, content is at top level
echo "$line" | grep -q '"content":"' || continue
else
continue
fi
# Check for valid continuation patterns and extract reference
if echo "$line" | grep -q '"content":"Implement the following plan'; then
ref=$(echo "$line" | grep -o 'read the full transcript at: [^"\\]*\.jsonl' | sed 's/read the full transcript at: //')
# Skip self-references (compaction within same file)
[ "$ref" = "$TRANSCRIPT_PATH" ] && continue
[ -f "$ref" ] && echo "$ref"
elif echo "$line" | grep -q '"content":"This session is being continued'; then
ref=$(echo "$line" | grep -o 'read the full transcript at: [^"\\]*\.jsonl' | sed 's/read the full transcript at: //')
# Skip self-references (compaction within same file)
[ "$ref" = "$TRANSCRIPT_PATH" ] && continue
[ -f "$ref" ] && echo "$ref"
fi
done
Step C: Recursive discovery
For each valid transcript found, repeat Steps A-B until no new transcripts are discovered.
Step D: Determine chronological order using reference topology
DO NOT use file modification times - they are unreliable. Use the reference chain: transcripts that are referenced but don't reference others come FIRST.
Example from a real session:
Discovery:
- 830e4d0f (current) has plan implementation referencing de2864e0
- de2864e0 has plan implementations referencing 2bb50f3b AND c9c826aa
- c9c826aa has plan implementation referencing 2bb50f3b
- 2bb50f3b has no plan implementation references (ROOT)
Reference topology:
- 2bb50f3b: referenced by c9c826aa and de2864e0, references nothing → ROOT
- c9c826aa: referenced by de2864e0, references 2bb50f3b → SECOND
- de2864e0: referenced by current, references both above → THIRD
- 830e4d0f: references de2864e0 → CURRENT (last)
Final order: 2bb50f3b → c9c826aa → de2864e0 → 830e4d0f
Verification output: After discovery, list all found transcripts showing:
Handling compaction: If the conversation context has been compacted (summarized), the continuation reference may not be visible in the current context. In this case:
Detect compact_boundary entries for metadata:
grep -n '"subtype":"compact_boundary"' "$TRANSCRIPT_PATH"
Each match is a JSON line with type: "system", subtype: "compact_boundary",
compactMetadata.trigger ("auto" or "manual"), and compactMetadata.preTokens.
Collect these per-transcript for the compactions field in metadata.json.
Generate task title:
Create external session folder:
{SESSION_EXPORTS_BASE}/{project-path}/ (expand ~ to $HOME)IS_WORKTREE=true, use MAIN_PROJECT_PATH from Step 1.5 as the {project-path} instead of the transcript-derived path. This ensures exports land at the main repo's directory (e.g., -Users-henrybae-Files-Startup-Projects-personal-toolkit/).PROJECT_PATH derived from the transcript path in Part A (e.g., "-Users-henrybae-Files-Startup-Projects-thought-organizer"){YYYY-MM-DD} {Project Name} {Task Title}/~/.claude/session-exports/-Users-henrybae-Files-Startup-Projects-thought-organizer/2026-01-22 Thought Organizer Agent Clippings Fix/mkdir -p "$EXPORT_PATH"~/.claude/projects/). Only the export DESTINATION changes.Copy transcripts:
session.jsonlsession-1.jsonl, session-2.jsonl, etc. (simplest, always works)session-1.jsonl, session-2.jsonl, session-3.jsonl, session-4.jsonlDetect and copy plan files:
"slug":"[^"]*" to extract ALL unique plan slugs~/.claude/plans/<slug>.mdplan.mdplan-1.md, plan-2.md (in chronological order)# heading from each plan fileCopy session folder contents (subagents, tool-results, etc.):
~/.claude/projects/{project-path}/{session-id}/
(project-path is derived from transcript path, e.g., "-Users-henrybae-Files-Startup-Projects-thought-organizer")ls -d "$session_folder" 2>/dev/nullcp -r "$session_folder"/* "$EXPORT_PATH/"subagents/ - Subagent JSONL transcripts (Explore, Plan, etc.)tool-results/ - Large tool outputsCapture CLAUDE.md configuration files:
Discover and copy CLAUDE.md files that were active during the session.
{project_path} below refers to MAIN_REPO_PATH from Step 1.5.
~/.claude/CLAUDE.md{project_path}/CLAUDE.md{project_path}/.claude/CLAUDE.mdIS_WORKTREE=true): Also check the worktree CWD for CLAUDE.md files that may differ from the main repo (e.g., worktree-specific .claude/CLAUDE.md)For each that exists:
mkdir -p "$EXPORT_PATH/claude-md"claude-md/global.mdclaude-md/project.mdclaude-md/project-dot-claude.md{"scope": "global|project|project-dot-claude", "source": "/abs/path", "file": "claude-md/global.md"}claude_md from metadata)Detect subagent information for metadata:
$EXPORT_PATH/subagents/ existsagent-*.jsonl filesagent-{id}.jsonl)"slug":"...")"sessionId":"...")Extract git commits made during session:
Step A: Detect session-relevant git repos
Only track repos where files were actually created, edited, or committed during this session (including continuations from previous transcripts in the chain). Do NOT blindly scan all subdirectories.
CRITICAL: CWD being a git repo does NOT automatically make it session-relevant. Pre-existing uncommitted changes (those already present in the gitStatus snapshot at session start) do NOT count. Editing files outside any git repo (e.g., ~/.claude/settings.json) does NOT make CWD session-relevant.
gitStatus: If CWD repo's uncommitted changes ALL appear in the session-start gitStatus, they are pre-existing — do NOT count CWD as session-relevantgit -C <path> rev-parse --git-dirIS_WORKTREE=true, use MAIN_REPO_PATH from Step 1.5 as the CWD repo path (not the worktree directory)untracked_repos (informational only)git: null, skip rest of Step 10Step B: Check repo cleanliness (session-relevant repos only)
Only check repos identified in Step A — ignore unrelated repos entirely.
B1: Uncommitted changes
git -C "$repo_path" status --porcelain for each session-relevant repoUncommitted changes detected in:
- claude-config
Commit your changes first, then run /devlog again.
B2: Unpushed commits
git -C "$repo_path" log @{u}..HEAD --oneline 2>/dev/nullUnpushed commits detected in:
- claude-config (3 commits ahead)
Push your changes first, then run /devlog again.
Priority: Check uncommitted first (must commit before push). Only check unpushed if all session-relevant repos are clean.
Step C: Get session start timestamp
Extract the first timestamp from the oldest transcript in the session chain:
# Skip line 1 (file-history-snapshot has no timestamp), get timestamp from line 2
head -2 "$OLDEST_TRANSCRIPT" | tail -1 | python3 -c "import sys,json; print(json.loads(sys.stdin.read())['timestamp'])"
The timestamp format is ISO 8601: 2026-01-27T23:51:46.497Z
Step D: Query commits per-repo
For each tracked repo:
git -C "$repo_path" log --all --since="$SESSION_START_TIMESTAMP" --format="%H" --reverse
--all searches across all branches (catches commits made in worktrees)--reverse ensures commits are in chronological order (oldest first)%H gives full commit hashesStep E: Build per-repo tracking data
For each tracked repo with commits:
commits = [hash1, hash2, ...] # chronological order
start_commit = $(git -C "$repo_path" rev-parse commits[0]^) # parent of first commit
end_commit = commits[-1] # last commit
commit_range = "start_commit..end_commit"
remote = $(git -C "$repo_path" remote get-url origin 2>/dev/null) # null if no remote
name = basename of repo_path
Edge case - if first commit has no parent (initial commit):
git -C "$repo_path" rev-parse $FIRST_COMMIT^ 2>/dev/null || echo "ROOT"
If ROOT, set start_commit: null and commit_range: "..end_commit"
If no commits found for a repo, exclude it from repos[].
Step F: Filter commits by conversation context (per-repo)
Apply the LLM-based conversation-context filter independently per repo.
Get commit messages for all commits found in each repo:
git -C "$repo_path" log --format="%H %s" <commit1> <commit2> ...
Compare each commit against the current conversation context:
For each commit, determine if it matches:
Only include matching commits in the repo's tracking data
Discard repo entries with zero matching commits after filtering
Example (multi-repo):
claude-config: fa31b22 "Bump devlog schema" → MATCH, e7c9d01 "Update slackbot" → NO MATCH
personal-toolkit: 3a8f1cc "Rewrite Step 9 for multi-repo" → MATCH
Step G: Assemble git object
repos[] = all repos with matching commits after filteringuntracked_repos = sub-repos found in single-repo mode (if any); omit field if none foundgit: nullSCHEMA.md v0.11 for field structure and examples{
"schema_version": "0.11",
"date": "2026-01-22",
"project": "Thought Organizer Agent",
"project_slug": "thought-organizer",
"project_path": "/Users/henrybae/Files/Startup/Projects/thought-organizer",
"worktree": {
"path": "/Users/henrybae/Files/Startup/Projects/thought-organizer/.claude/worktrees/worktree-feature",
"name": "worktree-feature"
},
"task": "Fix clippings heading duplication",
"task_title": "Clippings Fix",
"rating": 5,
"comment": "Solid session but got stuck on type inference",
"phases": [
{"name": "planning", "file": "planning.jsonl", "session_id": "aaa"},
{"name": "implementation-1", "file": "implementation-1.jsonl", "session_id": "bbb"}
],
"plan_files": [
{
"slug": "virtual-strolling-bee",
"file": "plan-1.md",
"title": "Plan: Add Plan File Export to Devlog",
"phase": "planning"
}
],
"subagents": [
{"agent_id": "a946520", "slug": "joyful-splashing-lake", "session_id": "aaa", "session_num": 1},
{"agent_id": "b123456", "slug": "gentle-flowing-river", "session_id": "bbb", "session_num": 2}
],
"git": {
"repos": [
{
"name": "thought-organizer",
"path": "/Users/henrybae/Files/Startup/Projects/thought-organizer",
"remote": "https://github.com/BaeHenryS/thought-organizer.git",
"start_commit": "9b75d4a",
"end_commit": "def5678",
"commits": ["abc1234", "def5678"],
"commit_range": "9b75d4a..def5678"
}
]
},
"compactions": [
{"file": "session-2.jsonl", "line": 430, "timestamp": "2026-03-11T09:24:10.107Z", "trigger": "auto", "pre_tokens": 169072}
],
"claude_md": [
{"scope": "global", "source": "/Users/henrybae/.claude/CLAUDE.md", "file": "claude-md/global.md"},
{"scope": "project", "source": "/Users/henrybae/Files/Startup/Projects/thought-organizer/CLAUDE.md", "file": "claude-md/project.md"}
],
"files_modified": {
".": ["src/clipper.py"]
},
"outcome": "completed"
}
Schema reference: See SCHEMA.md in this skill folder for version history and field documentation.
[{"name": "session", "file": "session.jsonl", "session_id": "xxx"}]plan_files array: include only if plan files were exportedsubagents array: include only if subagent files were foundcompactions array: include only if compact_boundary entries were found in any transcriptclaude_md array: include only if CLAUDE.md files were foundworktree object: include only when IS_WORKTREE=true from Step 1.5 (contains path and name); omit entirely when not in a worktreeproject_path: always uses MAIN_REPO_PATH from Step 1.5 (main repo path, not worktree path)git object: uses repos[] array (even single-repo = one element); set to null if no commits or no git reposfiles_modified: Object (dict) keyed by directory path. Use "." for files within CWD (with repo-prefixed paths in multi-repo mode, e.g., "claude-config/skills/devlog/SKILL.md"). For files outside CWD, use ~-relative directory paths as keys (e.g., "~/Library/CloudStorage/.../Segment-B-Bookface": ["spotify.md", "netflix.md"]). See SCHEMA.md v0.11 for full specification and examples.After all files are exported and metadata.json is written, verify the copied transcripts actually contain this conversation's content.
Step 1: Reuse the session fingerprint built in Part A (Step 3, item 1). Add the approximate conversation flow (e.g., "started with planning, then implemented X, then fixed bug Y").
Step 2: Launch verification agent
Agent tool:
subagent_type: "Explore"
description: "Verify exported transcripts"
prompt: |
Verify that the exported session transcripts in {EXPORT_PATH}
contain the conversation from my current session.
Session fingerprint:
- Topics: {list of 3-5 topics from fingerprint}
- Files touched: {list of key files from fingerprint}
- Key actions: {list of notable things done from fingerprint}
- Flow: {brief conversation arc from fingerprint}
Verification approach:
1. Use grep to count mentions of key topics across session-*.jsonl files
(e.g., grep -c "topic_keyword" session-*.jsonl)
2. Use grep to confirm each key file path appears in the transcripts
3. Use targeted reads (head/tail) on each JSONL to verify the
conversation flow matches (start of earliest, end of latest)
4. Check line counts (wc -l) to confirm transcripts are non-trivial
Return:
PASS - with a brief summary of evidence (topic counts, files found,
line counts, flow confirmation)
WARN - if something seems off, with a brief explanation
Step 3: Handle result
Transcript verification warning:
[warning details from agent]
Continuing with devlog. Review exported files if needed.
Determine vault summary path:
<vault_path>/<processed_coding>/{YYYY-MM-DD} {Project Name} {Task Title}.md.md file, NOT a folder. NEVER create a summary.md inside a directory. The path ends in .md.Write vault summary file:
---
date: 2026-01-22
project: Thought Organizer Agent
task: Fix clippings heading duplication
rating: 5
comment: "Solid session but got stuck on type inference"
session_path: /Users/henrybae/.claude/session-exports/-Users-henrybae-Files-Startup-Projects-thought-organizer/2026-01-22 Thought Organizer Agent Clippings Fix/
categories:
- "[[Coding]]"
---
## Summary
[2-3 sentence summary of what was accomplished]
## Key Changes
- [Major change 1]
- [Major change 2]
## Files Modified
- `path/to/file1.py`
- `path/to/file2.md`
If files span multiple directories (cross-directory work), group under directory headers:
## Files Modified
### ./
- `src/main.py`
### ~/Library/CloudStorage/.../Segment-B-Bookface/
- 66 files (spotify.md, netflix.md, stripe.md, ...)
---
**Full session:** [Open in Finder](file:///Users/henrybae/.claude/session-exports/-Users-henrybae-Files-Startup-Projects-thought-organizer/2026-01-22%20Thought%20Organizer%20Agent%20Clippings%20Fix/)
Multi-repo vault summary: When multiple repos have commits, group Key Changes by repo:
## Key Changes
### claude-config
- [Change in claude-config]
### personal-toolkit
- [Change in personal-toolkit]
If only one repo has commits (even in multi-repo mode), keep the flat format without sub-headers.
For ## Files Modified, group files by directory when they span multiple locations. For files within CWD, use relative paths (with repo prefix in multi-repo mode). For files outside CWD, show the ~-relative directory path as a sub-header. When a directory has many files (>10), summarize with count and a few examples instead of listing all.
Comment in frontmatter: Only include comment: if non-null. Wrap in quotes for YAML safety.
Important: Use the full absolute path (expand ~ to $HOME) for the file:// URL to work in Obsidian.
Vault summary notes:
session_path in frontmatter for programmatic accessExternal folder structure:
~/.claude/session-exports/
└── {project-path}/ # e.g., "-Users-henrybae-Files-Startup-Projects-thought-organizer"
└── {YYYY-MM-DD} {Project Name} {Task Title}/ # e.g., "2026-01-27 Personal Toolkit Devlog Fix"
├── metadata.json
├── session.jsonl # Main transcript (or session-1.jsonl, etc.)
├── plan.md # (if exists)
├── claude-md/ # (if exists - CLAUDE.md files)
│ ├── global.md
│ └── project.md
└── subagents/ # (if exists - copied from session folder)
└── agent-*.jsonl
└── tool-results/ # (if exists - copied from session folder)
└── toolu_*.txt
Vault folder structure (lightweight):
<vault>/Processed/Coding/{YYYY-MM-DD} {Project Name} {Task Title}.md # Links to external session
Store the session path (e.g., ~/.claude/session-exports/-Users-henrybae-Files-Startup-Projects-thought-organizer/2026-01-22 Thought Organizer Agent Clippings Fix/) for use in Step 6.
--slack flag first, then:
/devlog 5 great pair programming session → rating=5, comment="great pair programming session"/devlog 5 worked well but got stuck on types --slack → rating=5, comment="worked well but got stuck on types", slack=true/devlog 5 → rating=5, comment: prompt user/devlog → prompt for rating, then prompt for commentRate this session (1-7):
7 - Exceptional (exceeded expectations)
6 - Great (very helpful)
5 - Good (solid assistance)
4 - Okay (got the job done)
3 - Poor (struggled significantly)
2 - Bad (mostly unhelpful)
1 - Terrible (counterproductive)
Do NOT use AskUserQuestion for this — it caps at 4 options and produces inconsistent groupings.
Wait for the user to reply with a number, then validate it is 1-7.nullReview the current conversation to identify:
Output the rating AND both sections to the terminal:
## Session Rating: X/7 (Meaning)
> "comment text here"
## What I Learned
- [Learning 1]
- [Learning 2]
## What I Shipped
- [Accomplishment 1]
- [Accomplishment 2]
Replace X with the rating number and (Meaning) with the corresponding description from the rating scale (e.g., "5/7 (Good - solid assistance)").
Only show the comment blockquote if the comment is non-null.
Keep bullet points concise (one line each).
Read the current daily note and append to the project's section under ## Progress.
Constraints:
-) highlighting key items — use your discretion; skip sub-bullets for simple single-task sessions(X/7) after the top-level summary([Session Log](Processed/Coding/{filename}.md))
session_path linking to the full external session.md extension (e.g., 2026-01-11 Thought Organizer Feature Name.md)- [x] for completed items- [ ] for in-progress/incomplete itemsLocating/Creating Sections:
## Progress section (top-level, NOT under ## Notes)
## Weekly Tracking if present, otherwise at end of file)### [[Project Name]] under ## Progress (case-insensitive match on project name)
## ProgressFormat to write:
## Progress
### [[Thought Organizer Agent]]
- [x] Rewrote clippings pipeline and fixed heading bugs (5/7) ([Session Log](Processed/Coding/2026-01-11 Thought Organizer Agent Clippings Fix.md))
- Replaced regex parser with markdown AST
- Fixed duplicate heading insertion on re-import
- Added unit tests for edge cases
### [[Video Generation Pipeline]]
- [x] Added audio sync feature (6/7) ([Session Log](Processed/Coding/2026-01-11 Video Generation Pipeline Audio Sync.md))
After appending, confirm to the user that their progress has been logged.
Skip this step unless: User invoked /devlog --slack
After logging is complete, send a summary to Slack:
Format the message using "What I Shipped" from Step 5:
📝 *Devlog: {PROJECT_NAME}*
{TASK_SUMMARY}
*Shipped:*
• {ACCOMPLISHMENT_1}
• {ACCOMPLISHMENT_2}
...
Invoke the slackbot skill:
Use the Skill tool to call: /slackbot #{CHANNEL} "{formatted_message}"
Use the channel from "Slack Configuration" above.
Confirm to user: "Slack notification sent to #{CHANNEL}"
After all steps complete, provide a brief final confirmation to the user that includes the session rating.
[x] for done, [ ] for incomplete--slack to send notificationCreates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.
npx claudepluginhub baehenrys/personal-toolkit --plugin vault