Skip to content

Commit 72e6d6c

Browse files
jumskiclaude
andcommitted
refactor: simplify notes skill scripts with standardized output format (#316)
Refactored note management scripts to use a consistent header-first output format and added AI summarization capability for quick note overviews. Key changes: 1. Standardized script output format: - All scripts (search-notes.sh, list-titles.sh) now output header first - Data rows follow (empty if no results) - Removed verbose "Found N notes" messages for cleaner piping - Header-only output clearly indicates no results 2. Added summarize-notes.sh: - Pipes into search/list commands to add AI summaries - Uses GNU parallel + aichat for fast parallel processing - Adds SUMMARY column to help identify notes without reading full content - Detects header line (line 1) and appends "| SUMMARY" column - Processes data rows (line 2+) with AI model to generate summaries 3. Reorganized skill structure: - Moved shared scripts to .claude/skills/_shared/notes/ - Split monolithic idea-refine into focused skills: * note-capture: Save conversation context to topic notes * note-find: Search for notes with optional AI summaries * note-list: List topics or notes with optional AI summaries * note-organize: Archive/refine notes with confirmation prompts * note-overview: Summarize all notes in a topic * note-refine: Iteratively edit and improve notes - Added shared documentation (notes-layout.md, topics.md) 4. Updated skill documentation: - All note-* skills now mention summarize-notes.sh capability - Added tips on when to use summarization (multiple unclear results) - Consistent patterns using AskUserQuestion for confirmations - Clear examples of piping: `list-titles.sh topic/ | summarize-notes.sh` Benefits: - Cleaner script output for reliable piping - Fast AI summaries help disambiguate similar notes - Modular skills with clear responsibilities - Better UX with confirmation prompts before bulk operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 920c70e commit 72e6d6c

File tree

26 files changed

+593
-872
lines changed

26 files changed

+593
-872
lines changed

.claude/skills/notes/scripts/list-titles renamed to .claude/skills/_shared/notes/list-titles.sh

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,11 +104,6 @@ extract_title() {
104104
fi
105105
}
106106

107-
# Print header if with_dates
108-
if [ "$with_dates" = true ]; then
109-
echo "# PATH | TITLE | MODIFIED | CREATED"
110-
fi
111-
112107
# Collect all output
113108
output=$(
114109
for arg in "${args[@]}"; do
@@ -129,10 +124,17 @@ output=$(
129124
done
130125
)
131126

127+
# Always output header first
132128
if [ "$with_dates" = true ]; then
133-
# Sort by modification time (oldest first), then format output
134-
echo "$output" | sort -t'|' -k1 -n | cut -d'|' -f2- | awk -F'|' '{printf "%s | %s | %s | %s\n", $1, $2, $3, $4}'
129+
echo "PATH | TITLE | MODIFIED | CREATED"
130+
# Output sorted results (if any)
131+
if [ -n "$output" ]; then
132+
echo "$output" | sort -t'|' -k1 -n | cut -d'|' -f2- | awk -F'|' '{printf "%s | %s | %s | %s\n", $1, $2, $3, $4}'
133+
fi
135134
else
136-
# Just output as-is
137-
echo "$output"
135+
echo "PATH | TITLE"
136+
# Output results (if any)
137+
if [ -n "$output" ]; then
138+
echo "$output"
139+
fi
138140
fi
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# list-topics - List all topic directories (non-underscore top-level folders)
5+
# Usage: list-topics
6+
# Output: One topic name per line
7+
8+
# Get the directory where this script is located
9+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
10+
11+
# Validate and get notes directory
12+
NOTES_DIR=$("$SCRIPT_DIR/echo-notes-dir.sh")
13+
14+
# Find all top-level directories that don't start with underscore
15+
# -maxdepth 1: only top level
16+
# -type d: directories only
17+
# -not -name '_*': exclude underscore-prefixed
18+
# -not -name '.': exclude current dir
19+
# -not -name '.*': exclude hidden dirs
20+
# Note: Trailing slash needed for symlink support
21+
topics=$(find "$NOTES_DIR/" -maxdepth 1 -type d \
22+
-not -name '_*' \
23+
-not -name '.' \
24+
-not -name '.*' \
25+
-printf '%f\n' | sort)
26+
27+
# Count and output with summary
28+
count=$(echo "$topics" | grep -c '^' || echo "0")
29+
30+
if [ "$count" -eq 0 ]; then
31+
echo "No topics found."
32+
else
33+
echo "Found $count topic(s):"
34+
echo ""
35+
echo "$topics"
36+
fi
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
# Notes Directory Layout
2+
3+
**Notes directory:** !`./.claude/skills/_shared/notes/echo-notes-dir.sh`
4+
5+
## Folder Structure
6+
7+
```
8+
./.notes/
9+
├── [topic]/ # Topic-based folders (e.g., pgflow-demo, ci-optimization)
10+
│ ├── WIP-*.md # Work in progress (quick captures, drafts)
11+
│ └── *.md # Refined notes (ready to use)
12+
13+
├── _archive/ # Archived/completed work
14+
│ └── [topic]/ # Organized by original topic
15+
16+
├── _reference/ # Knowledge base (optional)
17+
│ └── *.md # Reference docs, guides, non-actionable info
18+
19+
└── roadmap.md # (optional) Project roadmap
20+
```
21+
22+
## File Naming
23+
24+
- **WIP prefix**: `WIP-descriptive-name.md` for work in progress
25+
- **No prefix**: `descriptive-name.md` for refined notes
26+
- **Kebab-case**: Use hyphens, lowercase, no spaces
27+
- **Extension**: Always `.md`
28+
29+
## Workflow
30+
31+
1. **Capture**: Create `[topic]/WIP-note.md` (note-capture skill)
32+
2. **Refine**: Edit and improve over time (note-refine skill)
33+
3. **Finalize**: Remove WIP prefix when ready (note-organize skill)
34+
4. **Archive**: Move to `_archive/[topic]/` when done (note-organize skill)
35+
36+
## Important Notes
37+
38+
- Always use `./.notes/` (relative to repo root)
39+
- Working directory (`$PWD`) must be repository root
40+
- Use relative paths for scripts: `./.claude/skills/_shared/notes/`
41+
- Topics are inferred from folder names (use `list-topics.sh` script)

.claude/skills/notes/scripts/search renamed to .claude/skills/_shared/notes/search-notes.sh

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ else
3535
fi
3636

3737
# Use ripgrep to find files matching pattern (case-insensitive, list files only)
38-
"${rg_cmd[@]}" 2>/dev/null | while IFS= read -r file; do
38+
results=$("${rg_cmd[@]}" 2>/dev/null | while IFS= read -r file; do
3939
# Extract H1 title from first line
4040
title=$(head -1 "$file" 2>/dev/null | sed 's/^# //' || echo "")
4141
@@ -46,4 +46,12 @@ fi
4646
4747
# Output: path | title
4848
echo "$file | $title"
49-
done
49+
done || true)
50+
51+
# Always output header first
52+
echo "PATH | TITLE"
53+
54+
# Output results (if any)
55+
if [ -n "$results" ]; then
56+
echo "$results"
57+
fi
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
#!/usr/bin/env bash
2+
set -euo pipefail
3+
4+
# summarize-notes - Add AI summaries to note listings
5+
# Usage: list-titles.sh scratch/ | summarize-notes.sh
6+
# or: search-notes.sh "pattern" | summarize-notes.sh
7+
#
8+
# Expected input format:
9+
# Line 1: Header (e.g., "PATH | TITLE")
10+
# Line 2+: Data rows (e.g., ".notes/foo.md | My Note")
11+
# If only header exists (no data rows), means no notes found
12+
#
13+
# Adds SUMMARY column with fast AI-generated summaries (parallel processing)
14+
15+
# Model and prompt
16+
MODEL="groq:meta-llama/llama-4-scout-17b-16e-instruct"
17+
PROMPT="summarize this file in two sentences, only output summary"
18+
19+
# Check if 'parallel' is available
20+
if ! command -v parallel &> /dev/null; then
21+
echo "Error: GNU parallel not installed. Install with: sudo pacman -S parallel" >&2
22+
exit 1
23+
fi
24+
25+
# Check if 'aichat' command is available
26+
if ! command -v aichat &> /dev/null; then
27+
echo "Error: 'aichat' command not found. Make sure it's installed and in PATH." >&2
28+
exit 1
29+
fi
30+
31+
# Process a single line
32+
process_line() {
33+
local line="$1"
34+
local line_number="$2"
35+
# Use exported MODEL and PROMPT environment variables
36+
37+
# First line is always the header - append SUMMARY column
38+
if [ "$line_number" -eq 1 ]; then
39+
echo "$line | SUMMARY"
40+
return
41+
fi
42+
43+
# Extract path (everything before first |)
44+
local path="${line%%|*}"
45+
# Trim whitespace (bash parameter expansion)
46+
path="${path#"${path%%[![:space:]]*}"}"
47+
path="${path%"${path##*[![:space:]]}"}"
48+
49+
# Skip if file doesn't exist
50+
if [ ! -f "$path" ]; then
51+
return # Skip failed files silently
52+
fi
53+
54+
# Get summary (pass prompt as separate words, not quoted)
55+
local summary
56+
summary=$(aichat --model "$MODEL" -f "$path" $PROMPT 2>/dev/null || echo "")
57+
58+
# Skip if summary failed
59+
if [ -z "$summary" ]; then
60+
return
61+
fi
62+
63+
# Collapse multiline to single line (replace newlines with spaces, collapse multiple spaces)
64+
summary=$(echo "$summary" | tr '\n' ' ' | sed 's/ */ /g')
65+
# Trim whitespace (bash parameter expansion)
66+
summary="${summary#"${summary%%[![:space:]]*}"}"
67+
summary="${summary%"${summary##*[![:space:]]}"}"
68+
69+
# Append summary
70+
echo "$line | $summary"
71+
}
72+
73+
export -f process_line
74+
export MODEL PROMPT
75+
76+
# Read stdin, number lines, and process in parallel (16 jobs)
77+
cat -n | parallel -j 16 --keep-order --colsep '\t' process_line {2} {1}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
## Available Topics
2+
3+
!`./.claude/skills/_shared/notes/list-topics.sh`

.claude/skills/idea-refine/SKILL.md

Lines changed: 0 additions & 83 deletions
This file was deleted.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
---
2+
name: note-capture
3+
description: Save conversation context to topic notes. Use when user says "capture note [about X]", "save to notes", "create note [in topic]", "note this [for topic]", "add note to [topic]". IMPORTANT - User must say "note" or "notes" explicitly.
4+
allowed-tools: Write, Bash, AskUserQuestion
5+
---
6+
7+
# Note Capture
8+
9+
Save conversation context to `.notes/[topic]/WIP-[name].md`
10+
11+
@../_shared/notes/topics.md
12+
13+
<critical>
14+
- ALWAYS use AskUserQuestion for topic selection
15+
- User MUST say "note" or "notes" (not just "save this")
16+
</critical>
17+
18+
## Workflow
19+
20+
**1. Determine topic:**
21+
22+
If user specified topic explicitly → use it
23+
24+
Otherwise use AskUserQuestion to select from available topics above.
25+
26+
**2. Create file:**
27+
- Filename: `WIP-[descriptive-name].md` (kebab-case)
28+
- Location: `.notes/[topic]/WIP-[name].md`
29+
- Format: H1 title on first line
30+
31+
**3. Confirm:**
32+
- Tell user where saved
33+
- Suggest `notes-sync` skill to commit
34+
35+
## File Format
36+
37+
```markdown
38+
# [Descriptive title]
39+
40+
[Content from conversation]
41+
```
42+
43+
H1 can be informal: questions, TODOs, context notes.
44+
45+
## Examples
46+
47+
**With explicit topic:**
48+
- "capture note about deployment in pgflow-demo"
49+
- "add note to ci-optimization about parallel jobs"
50+
51+
**Inferred topic:**
52+
- "capture note about this CI discussion" → Ask: which topic?
53+
- "note this for later" → Ask: which topic + what to capture?
54+
55+
@../_shared/notes/notes-layout.md

0 commit comments

Comments
 (0)