AI Newsletter Digest improvements: fixed QP soft line break decoding, URL extraction, and content cleaning
This commit is contained in:
142
skills/context-anchor/SKILL.md
Normal file
142
skills/context-anchor/SKILL.md
Normal file
@@ -0,0 +1,142 @@
|
||||
---
|
||||
name: context-anchor
|
||||
version: 1.0.0
|
||||
description: Recover from context compaction by scanning memory files and surfacing where you left off. Use when waking up fresh, after compaction, or when you feel lost about what you were doing.
|
||||
---
|
||||
|
||||
# Context Anchor Skill
|
||||
|
||||
Helps agents recover context after compaction by scanning memory files and generating a "here's where you are" briefing.
|
||||
|
||||
## Why This Exists
|
||||
|
||||
Context compaction loses memory. Files survive. But after waking up fresh, you need to:
|
||||
1. Know what you were working on
|
||||
2. See decisions that were made
|
||||
3. Find open loops that need closing
|
||||
4. Get oriented fast
|
||||
|
||||
This skill automates that recovery.
|
||||
|
||||
---
|
||||
|
||||
## Quick Start
|
||||
|
||||
```bash
|
||||
# Full briefing (default)
|
||||
./scripts/anchor.sh
|
||||
|
||||
# Just show current task
|
||||
./scripts/anchor.sh --task
|
||||
|
||||
# Just show active context files
|
||||
./scripts/anchor.sh --active
|
||||
|
||||
# Just show recent decisions
|
||||
./scripts/anchor.sh --decisions
|
||||
|
||||
# Show open loops / questions
|
||||
./scripts/anchor.sh --loops
|
||||
|
||||
# Scan specific number of days back
|
||||
./scripts/anchor.sh --days 3
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## What It Scans
|
||||
|
||||
| Source | What It Extracts |
|
||||
|--------|------------------|
|
||||
| `memory/current-task.md` | Current task status, blockers, next steps |
|
||||
| `memory/YYYY-MM-DD.md` | Recent daily logs (last 2 days by default) |
|
||||
| `context/active/*.md` | In-progress task files |
|
||||
| Daily logs | Decisions (lines with "Decision:", "Decided:", "✅") |
|
||||
| Daily logs | Open loops (lines with "?", "TODO:", "Blocker:", "Need to") |
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
The script outputs a structured briefing:
|
||||
|
||||
```
|
||||
═══════════════════════════════════════════════════════════
|
||||
CONTEXT ANCHOR
|
||||
Where You Left Off
|
||||
═══════════════════════════════════════════════════════════
|
||||
|
||||
📋 CURRENT TASK
|
||||
───────────────────────────────────────────────────────────
|
||||
[Contents of memory/current-task.md or "No current task set"]
|
||||
|
||||
📂 ACTIVE CONTEXT FILES
|
||||
───────────────────────────────────────────────────────────
|
||||
• context/active/project-name.md (updated 2h ago)
|
||||
└─ First line preview...
|
||||
|
||||
🎯 RECENT DECISIONS (last 2 days)
|
||||
───────────────────────────────────────────────────────────
|
||||
[2026-01-30] Decision: Use Cloudflare Pages for hosting
|
||||
[2026-01-30] ✅ Completed email capture setup
|
||||
|
||||
❓ OPEN LOOPS
|
||||
───────────────────────────────────────────────────────────
|
||||
[2026-01-30] Need to enable SFTP on NAS
|
||||
[2026-01-30] TODO: Create Product Hunt account
|
||||
|
||||
═══════════════════════════════════════════════════════════
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Integration with AGENTS.md
|
||||
|
||||
Add to your "Every Session" routine:
|
||||
|
||||
```markdown
|
||||
## Every Session
|
||||
|
||||
Before doing anything else:
|
||||
1. Run `./skills/context-anchor/scripts/anchor.sh` for orientation
|
||||
2. Read `SOUL.md` — this is who you are
|
||||
3. Read `USER.md` — this is who you're helping
|
||||
...
|
||||
```
|
||||
|
||||
Or use it manually when you feel lost about context.
|
||||
|
||||
---
|
||||
|
||||
## Customization
|
||||
|
||||
### Change workspace root
|
||||
|
||||
```bash
|
||||
WORKSPACE=/path/to/workspace ./scripts/anchor.sh
|
||||
```
|
||||
|
||||
### Change days to scan
|
||||
|
||||
```bash
|
||||
./scripts/anchor.sh --days 5 # Scan 5 days back
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## No Dependencies
|
||||
|
||||
Pure bash. Uses only:
|
||||
- `find`, `grep`, `head`, `tail`, `date`, `stat`
|
||||
- Works on macOS and Linux
|
||||
- No external tools required
|
||||
|
||||
---
|
||||
|
||||
## When to Use
|
||||
|
||||
- **Session start**: Quick orientation on what's happening
|
||||
- **After compaction**: Recover lost context
|
||||
- **Feeling lost**: "Wait, what was I doing?"
|
||||
- **Handoff**: Show another agent where things stand
|
||||
- **Daily review**: See what decisions were made
|
||||
276
skills/context-anchor/scripts/anchor.sh
Executable file
276
skills/context-anchor/scripts/anchor.sh
Executable file
@@ -0,0 +1,276 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# context-anchor: Recover context after compaction
|
||||
# Scans memory files and generates a "here's where you are" briefing
|
||||
#
|
||||
|
||||
set -e
|
||||
|
||||
# Configuration
|
||||
WORKSPACE="${WORKSPACE:-$(cd "$(dirname "$0")/../../.." && pwd)}"
|
||||
MEMORY_DIR="$WORKSPACE/memory"
|
||||
CONTEXT_DIR="$WORKSPACE/context/active"
|
||||
DAYS_BACK="${DAYS_BACK:-2}"
|
||||
|
||||
# Colors (disabled if not a terminal)
|
||||
if [ -t 1 ]; then
|
||||
BOLD='\033[1m'
|
||||
DIM='\033[2m'
|
||||
RESET='\033[0m'
|
||||
BLUE='\033[34m'
|
||||
GREEN='\033[32m'
|
||||
YELLOW='\033[33m'
|
||||
CYAN='\033[36m'
|
||||
else
|
||||
BOLD=''
|
||||
DIM=''
|
||||
RESET=''
|
||||
BLUE=''
|
||||
GREEN=''
|
||||
YELLOW=''
|
||||
CYAN=''
|
||||
fi
|
||||
|
||||
# Parse arguments
|
||||
SHOW_ALL=true
|
||||
SHOW_TASK=false
|
||||
SHOW_ACTIVE=false
|
||||
SHOW_DECISIONS=false
|
||||
SHOW_LOOPS=false
|
||||
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
--task)
|
||||
SHOW_ALL=false
|
||||
SHOW_TASK=true
|
||||
shift
|
||||
;;
|
||||
--active)
|
||||
SHOW_ALL=false
|
||||
SHOW_ACTIVE=true
|
||||
shift
|
||||
;;
|
||||
--decisions)
|
||||
SHOW_ALL=false
|
||||
SHOW_DECISIONS=true
|
||||
shift
|
||||
;;
|
||||
--loops)
|
||||
SHOW_ALL=false
|
||||
SHOW_LOOPS=true
|
||||
shift
|
||||
;;
|
||||
--days)
|
||||
DAYS_BACK="$2"
|
||||
shift 2
|
||||
;;
|
||||
--help|-h)
|
||||
echo "Usage: anchor.sh [OPTIONS]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --task Show only current task"
|
||||
echo " --active Show only active context files"
|
||||
echo " --decisions Show only recent decisions"
|
||||
echo " --loops Show only open loops"
|
||||
echo " --days N Scan N days back (default: 2)"
|
||||
echo " --help Show this help"
|
||||
exit 0
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Helper: print header
|
||||
header() {
|
||||
echo -e "${BOLD}${BLUE}$1${RESET}"
|
||||
echo -e "${DIM}───────────────────────────────────────────────────────────${RESET}"
|
||||
}
|
||||
|
||||
# Helper: relative time
|
||||
relative_time() {
|
||||
local file="$1"
|
||||
local now=$(date +%s)
|
||||
local mod
|
||||
|
||||
# macOS vs Linux stat
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
mod=$(stat -f %m "$file" 2>/dev/null || echo 0)
|
||||
else
|
||||
mod=$(stat -c %Y "$file" 2>/dev/null || echo 0)
|
||||
fi
|
||||
|
||||
local diff=$((now - mod))
|
||||
|
||||
if [ $diff -lt 60 ]; then
|
||||
echo "just now"
|
||||
elif [ $diff -lt 3600 ]; then
|
||||
echo "$((diff / 60))m ago"
|
||||
elif [ $diff -lt 86400 ]; then
|
||||
echo "$((diff / 3600))h ago"
|
||||
else
|
||||
echo "$((diff / 86400))d ago"
|
||||
fi
|
||||
}
|
||||
|
||||
# Helper: get daily files for last N days
|
||||
get_daily_files() {
|
||||
local files=()
|
||||
for i in $(seq 0 $((DAYS_BACK - 1))); do
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
local date_str=$(date -v-${i}d +%Y-%m-%d)
|
||||
else
|
||||
local date_str=$(date -d "-$i days" +%Y-%m-%d)
|
||||
fi
|
||||
local file="$MEMORY_DIR/${date_str}.md"
|
||||
if [ -f "$file" ]; then
|
||||
files+=("$file")
|
||||
fi
|
||||
done
|
||||
echo "${files[@]}"
|
||||
}
|
||||
|
||||
# Section: Current Task
|
||||
show_current_task() {
|
||||
header "📋 CURRENT TASK"
|
||||
|
||||
local task_file="$MEMORY_DIR/current-task.md"
|
||||
if [ -f "$task_file" ]; then
|
||||
echo -e "${DIM}($(relative_time "$task_file"))${RESET}"
|
||||
echo ""
|
||||
cat "$task_file"
|
||||
else
|
||||
echo -e "${DIM}No current task set (memory/current-task.md not found)${RESET}"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Section: Active Context Files
|
||||
show_active_context() {
|
||||
header "📂 ACTIVE CONTEXT FILES"
|
||||
|
||||
if [ ! -d "$CONTEXT_DIR" ]; then
|
||||
echo -e "${DIM}No context/active/ directory${RESET}"
|
||||
echo ""
|
||||
return
|
||||
fi
|
||||
|
||||
local found=false
|
||||
for file in "$CONTEXT_DIR"/*.md; do
|
||||
[ -e "$file" ] || continue
|
||||
found=true
|
||||
local name=$(basename "$file")
|
||||
local age=$(relative_time "$file")
|
||||
local preview=$(head -n 5 "$file" | grep -v '^#' | grep -v '^$' | head -n 1)
|
||||
|
||||
echo -e "${GREEN}• ${name}${RESET} ${DIM}(${age})${RESET}"
|
||||
if [ -n "$preview" ]; then
|
||||
echo -e " ${DIM}└─ ${preview:0:70}...${RESET}"
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "$found" = false ]; then
|
||||
echo -e "${DIM}No active context files${RESET}"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Section: Recent Decisions
|
||||
show_decisions() {
|
||||
header "🎯 RECENT DECISIONS (last $DAYS_BACK days)"
|
||||
|
||||
local files=($(get_daily_files))
|
||||
local found=false
|
||||
|
||||
for file in "${files[@]}"; do
|
||||
local date=$(basename "$file" .md)
|
||||
|
||||
# Look for decision patterns
|
||||
grep -n -i -E "(^|\s)(decision:|decided:|chose:|picked:|went with|✅.*completed|✅.*done|✅.*finished)" "$file" 2>/dev/null | while read -r line; do
|
||||
found=true
|
||||
# Extract just the content, clean it up
|
||||
local content=$(echo "$line" | sed 's/^[0-9]*://' | sed 's/^[ -]*//')
|
||||
echo -e "${CYAN}[$date]${RESET} $content"
|
||||
done
|
||||
done
|
||||
|
||||
if [ "$found" = false ]; then
|
||||
# Check if we actually found nothing
|
||||
local any_decisions=false
|
||||
for file in "${files[@]}"; do
|
||||
if grep -q -i -E "(decision:|decided:|✅)" "$file" 2>/dev/null; then
|
||||
any_decisions=true
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ "$any_decisions" = false ]; then
|
||||
echo -e "${DIM}No explicit decisions found in recent logs${RESET}"
|
||||
fi
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Section: Open Loops
|
||||
show_loops() {
|
||||
header "❓ OPEN LOOPS & TODO"
|
||||
|
||||
local files=($(get_daily_files))
|
||||
local task_file="$MEMORY_DIR/current-task.md"
|
||||
local found=false
|
||||
|
||||
# Check daily files for open items
|
||||
for file in "${files[@]}"; do
|
||||
local date=$(basename "$file" .md)
|
||||
|
||||
# Look for open loop patterns (questions, TODOs, blockers, unchecked items)
|
||||
grep -n -E "(^|\s)(\?$|TODO:|FIXME:|Blocker:|Need to|needs to|should|waiting for|- \[ \])" "$file" 2>/dev/null | \
|
||||
grep -v -E "(✅|\[x\]|\[X\])" | while read -r line; do
|
||||
found=true
|
||||
local content=$(echo "$line" | sed 's/^[0-9]*://' | sed 's/^[ -]*//')
|
||||
echo -e "${YELLOW}[$date]${RESET} $content"
|
||||
done
|
||||
done
|
||||
|
||||
# Check current-task.md for unchecked items
|
||||
if [ -f "$task_file" ]; then
|
||||
grep -n -E "^- \[ \]" "$task_file" 2>/dev/null | while read -r line; do
|
||||
found=true
|
||||
local content=$(echo "$line" | sed 's/^[0-9]*://' | sed 's/^- \[ \] //')
|
||||
echo -e "${YELLOW}[current-task]${RESET} $content"
|
||||
done
|
||||
fi
|
||||
|
||||
if [ "$found" = false ]; then
|
||||
echo -e "${DIM}No obvious open loops found${RESET}"
|
||||
fi
|
||||
echo ""
|
||||
}
|
||||
|
||||
# Main output
|
||||
main() {
|
||||
if [ "$SHOW_ALL" = true ]; then
|
||||
echo ""
|
||||
echo -e "${BOLD}═══════════════════════════════════════════════════════════${RESET}"
|
||||
echo -e "${BOLD} CONTEXT ANCHOR${RESET}"
|
||||
echo -e "${BOLD} Where You Left Off${RESET}"
|
||||
echo -e "${BOLD}═══════════════════════════════════════════════════════════${RESET}"
|
||||
echo ""
|
||||
|
||||
show_current_task
|
||||
show_active_context
|
||||
show_decisions
|
||||
show_loops
|
||||
|
||||
echo -e "${BOLD}═══════════════════════════════════════════════════════════${RESET}"
|
||||
echo ""
|
||||
else
|
||||
[ "$SHOW_TASK" = true ] && show_current_task
|
||||
[ "$SHOW_ACTIVE" = true ] && show_active_context
|
||||
[ "$SHOW_DECISIONS" = true ] && show_decisions
|
||||
[ "$SHOW_LOOPS" = true ] && show_loops
|
||||
fi
|
||||
}
|
||||
|
||||
main
|
||||
Reference in New Issue
Block a user