Back to list
jrc1883

nightly

by jrc1883

AI-powered development workflow automation for Claude Code. Modular plugin suite with 23 commands, 38 skills, and 22 specialized agents for professional software development.

2🍴 0📅 Jan 24, 2026

SKILL.md


name: nightly description: "End-of-day cleanup and maintenance routine. Calculates Sleep Score (0-100) based on uncommitted work, branch cleanup, issue updates, CI status, and service shutdown. Automatically captures session state to STATUS.json. Use at end of work day before closing Claude Code."

Nightly Routine

Overview

Automated end-of-day maintenance that ensures clean project state before leaving for the day.

Core principle: Leave the codebase in a clean, resumable state with zero manual overhead.

Trigger: End of work day, before closing Claude Code

Duration: ~10-15 seconds (vs. ~60 seconds manual)

Sleep Score (0-100)

Comprehensive health check across 6 dimensions:

CheckPointsCriteria
Uncommitted work saved25No uncommitted changes OR committed
Branches cleaned20No stale merged branches
Issues updated20Today's issues have status updates
CI passing15Latest CI run successful
Services stopped10No dev services running
Logs archived10Session logs saved

Score Interpretation:

  • 90-100: Perfect shutdown - ready for tomorrow
  • 70-89: Good - minor cleanup needed
  • 50-69: Fair - some uncommitted work or failed CI
  • 0-49: Poor - significant cleanup required

Workflow Steps

1. Collect Project State

Using capture_state.py utility:

from popkit_shared.utils.capture_state import capture_project_state

state = capture_project_state()
# Returns: {
#   'git': {...},
#   'github': {...},
#   'services': {...}
# }

Git Analysis:

  • Current branch
  • Uncommitted files (count and list)
  • Stashed changes count
  • Last commit info
  • Merged branches count

GitHub Analysis:

  • Open issues (last 5)
  • Recent issue updates
  • Latest CI run status

Service Analysis:

  • Running dev services (node, npm, pnpm, redis, postgres, supabase)
  • Session log files to archive

2. Calculate Sleep Score

Using sleep_score.py module:

from pop_nightly.scripts.sleep_score import calculate_sleep_score

score, breakdown = calculate_sleep_score(state)
# score: 0-100
# breakdown: {
#   'uncommitted_work_saved': {'points': 0, 'max': 25, 'reason': '...'},
#   'branches_cleaned': {'points': 20, 'max': 20, 'reason': '...'},
#   ...
# }

3. Generate Nightly Report

Using report_generator.py module:

from pop_nightly.scripts.report_generator import generate_nightly_report

report = generate_nightly_report(score, breakdown, state)
# Returns formatted markdown report with:
# - Sleep Score headline
# - Score breakdown table
# - Uncommitted changes (if any)
# - Recommendations before leaving
# - Next session actions

4. Capture Session State

Invoke pop-session-capture skill to update STATUS.json:

# This happens automatically via Skill tool invocation
# Updates STATUS.json with:
# - Nightly routine execution timestamp
# - Sleep score
# - Git status
# - In-progress work
# - Recommendations

5. Present Report to User

Display nightly report with:

  • Sleep Score (0-100) with visual indicator
  • Score Breakdown - What contributed to the score
  • Uncommitted Changes - Files that need attention
  • Recommendations - Actions before leaving
  • Next Steps - What to do tomorrow morning

Data Collection Commands

Git Commands (Consolidated)

Single command to gather all git data:

{
  echo "=== BRANCH ==="
  git rev-parse --abbrev-ref HEAD
  echo "=== COMMIT ==="
  git log -1 --format="%h - %s"
  echo "=== STATUS ==="
  git status --porcelain
  echo "=== STASHES ==="
  git stash list | wc -l
  echo "=== MERGED ==="
  git branch --merged main | grep -v "^\*" | grep -v "main" | wc -l
} | python -c "
import sys
sections = sys.stdin.read().split('===')
data = {}
for section in sections:
    if 'BRANCH' in section:
        data['branch'] = section.split('===')[1].strip()
    # ... parse other sections
print(json.dumps(data))
"

Branch Protection Detection (Issue #142):

After collecting branch name, check if it's a protected branch:

from popkit_shared.utils.session_recorder import is_recording_enabled, record_reasoning

# Get current branch
current_branch = git_output['branch']

# Protected branches
PROTECTED_BRANCHES = ["main", "master", "develop", "production"]
is_protected = current_branch in PROTECTED_BRANCHES

# Record if on protected branch
if is_recording_enabled():
    record_reasoning(
        step="Check branch protection",
        reasoning=f"Branch '{current_branch}' is {'PROTECTED' if is_protected else 'not protected'}",
        data={
            "current_branch": current_branch,
            "is_protected": is_protected
        }
    )

Sleep Score Impact:

If on protected branch with uncommitted work:

  • Warning: Include ⚠️ PROTECTED indicator in output
  • Recommendation: "Create feature branch and move uncommitted work before committing"
  • Option Priority: Prioritize "Create feature branch" over "Commit and push"

GitHub Commands (Consolidated)

{
  gh issue list --state open --limit 5 --json number,title,updatedAt
  echo "---SEPARATOR---"
  gh run list --limit 1 --json conclusion,status,createdAt
} > /tmp/gh_data.json

Service Check (Consolidated)

{
  ps aux | grep -E "(node|npm|pnpm|redis|postgres|supabase)" | grep -v grep
  echo "---SEPARATOR---"
  ls ~/.claude/logs/*.log 2>/dev/null | wc -l
} > /tmp/service_data.txt

Integration with Existing Utilities

capture_state.py

Located: packages/shared-py/popkit_shared/utils/capture_state.py

def capture_project_state() -> dict:
    """Capture complete project state for nightly routine."""
    return {
        'git': capture_git_state(),
        'github': capture_github_state(),
        'services': capture_service_state(),
        'timestamp': datetime.now().isoformat()
    }

routine_measurement.py

Located: packages/shared-py/popkit_shared/utils/routine_measurement.py

When invoked with --measure flag:

  • Tracks tool call count
  • Measures duration
  • Calculates token usage
  • Saves to .claude/popkit/measurements/nightly-<timestamp>.json

routine_cache.py

Located: packages/shared-py/popkit_shared/utils/routine_cache.py

Caching strategy:

  • Never cache: Git status (changes frequently)
  • Cache 15 min: CI status
  • Cache 1 hour: GitHub issue list

Output Format

# 🌙 Nightly Routine Report

**Date**: 2025-12-28
**Sleep Score**: 60/100 ⚠️

## Score Breakdown

| Check                  | Points | Status                  |
| ---------------------- | ------ | ----------------------- |
| Uncommitted work saved | 0/25   | ❌ 3 uncommitted files  |
| Branches cleaned       | 20/20  | ✅ No stale branches    |
| Issues updated         | 20/20  | ✅ All issues current   |
| CI passing             | 0/15   | ❌ Latest run skipped   |
| Services stopped       | 10/10  | ✅ All services stopped |
| Logs archived          | 10/10  | ✅ No logs to archive   |

## Uncommitted Changes (3 files)

- `apps/popkit/packages/websitebuild-popkit-test-beta.txt` (deleted)
- `pnpm-lock.yaml` (modified)
- `.npmrc` (untracked)

## 📋 Recommendations

**Before Leaving:**

- Commit or stash uncommitted changes
- Review 8 stashes: `git stash list`
- Check why CI was skipped

**Next Morning:**

- Run `/popkit:routine morning` to check overnight changes
- Review and test pending PRs
- Clear stash backlog

---

STATUS.json updated ✅
Session state captured for tomorrow's resume.

## 🎯 Next Actions (The PopKit Way)

**CRITICAL**: Always end with AskUserQuestion to keep PopKit in control.

Use AskUserQuestion tool with context-aware options based on nightly report:

**Option 1: If uncommitted work exists (Score < 70)**

What would you like to do before ending the day? ├─ Commit and push all changes (Recommended) │ └─ Save all uncommitted work ├─ Stash changes for tomorrow ├─ Review uncommitted files └─ Other


**Option 2: If clean working directory (Score >= 70)**

Ready to wrap up! What's your last action? ├─ Review tomorrow's priorities ├─ Check overnight CI status ├─ End session (all clean) └─ Other


**Option 3: If services still running**

Dev services are still running. What would you like to do? ├─ Stop all dev services (Recommended) ├─ Leave services running ├─ Check which services are running └─ Other


**Option 4: If CI failing**

Latest CI run failed. What would you like to do? ├─ Investigate CI failure now ├─ Note for morning review ├─ Check CI logs └─ Other


### Implementation

After generating the nightly report, invoke AskUserQuestion based on score and context:

```python
# After generating report
questions = generate_next_action_questions(score, breakdown, state)
# Returns AskUserQuestion tool invocation

# Example output to Claude:
{
    "type": "ask_user_question",
    "questions": [{
        "question": "What would you like to do before ending the day?",
        "header": "Next Action",
        "multiSelect": false,
        "options": [
            {
                "label": "Commit and push all changes (Recommended)",
                "description": "Save 5 uncommitted files"
            },
            {
                "label": "Stash changes for tomorrow",
                "description": "Keep work-in-progress safe"
            },
            {
                "label": "Stop dev services",
                "description": "3 services still running: redis, postgres, node"
            }
        ]
    }]
}

Why This Matters (The PopKit Way):

  • ✅ Keeps PopKit in control of the workflow
  • ✅ Prevents "forgot to commit" situations
  • ✅ Enables graceful session shutdown
  • ✅ Prevents "report dump and done" anti-pattern
  • ✅ Maintains workflow continuity for tomorrow

Never just show a report and end the session!


## Error Handling

### Git Not Available

```python
try:
    git_state = capture_git_state()
except GitNotFoundError:
    print("[WARN] Git not available - skipping git checks")
    # Continue with partial score

GitHub CLI Not Available

try:
    github_state = capture_github_state()
except GhNotFoundError:
    print("[WARN] GitHub CLI not available - skipping GitHub checks")
    # Continue with partial score

Service Check Failures

# Service checks are best-effort
# If they fail, assume services are stopped (safe default)

Optimization Features

Tool Call Reduction

  • Baseline: 11 tool calls (manual)
  • Optimized: 4 tool calls (automated)
  • Reduction: 64%

Execution Time

  • Baseline: ~60 seconds (manual, with thinking)
  • Optimized: ~10-15 seconds (automated)
  • Improvement: 75-83%

Caching

With --optimized flag:

  • Uses routine_cache.py for GitHub data
  • Reduces redundant API calls
  • 40-96% token reduction (per routine.md)

Usage Examples

Basic Usage

/popkit:routine nightly
# → Runs default nightly routine
# → Calculates Sleep Score
# → Updates STATUS.json
# → Shows report

With Measurement

/popkit:routine nightly --measure
# → Runs nightly routine
# → Tracks performance metrics
# → Saves to .claude/popkit/measurements/

Quick Summary

/popkit:routine nightly quick
# → Shows one-line summary
# → Sleep Score: 60/100 - 3 uncommitted files, CI skipped

With Optimization

/popkit:routine nightly --optimized
# → Uses caching for GitHub data
# → Reduces token usage by 40-96%

Files Modified

  1. STATUS.json - Session state updated with:

    • Sleep score
    • Git context
    • Nightly routine timestamp
    • Recommendations
  2. .claude/popkit/measurements/ (if --measure used)

    • Performance metrics
    • Tool call breakdown
    • Duration and token usage
  • pop-session-capture: Updates STATUS.json (invoked automatically)
  • pop-morning: Morning counterpart with Ready to Code score
  • pop-routine-optimized: Optimized execution with caching
  • /popkit:routine nightly: Main entry point
  • /popkit:routine morning: Morning routine
  • /popkit:next: Context-aware next action recommendations

Success Criteria

✅ Sleep Score accurately reflects project state ✅ STATUS.json always updated correctly ✅ Completes in <20 seconds ✅ Provides actionable recommendations ✅ Reduces manual workflow by 64%


Skill Type: Automated Routine Category: Workflow Automation Tier: Core (Always Available) Version: 1.0.0

Score

Total Score

75/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

+10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon