Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
7481990
Add FocusConfig type and core focus module
Mar 2, 2026
8ebcd01
Add focus command with setup wizard and session management
Mar 2, 2026
fa19e7a
Wire focus into CLI, configure menu, and skill catalog
Mar 2, 2026
a4e4627
Add c-focus SKILL.md and Focus Mode section in CLAUDE.md
Mar 2, 2026
1a708f6
Fix focus setup: run detection before clack prompts
Mar 2, 2026
42ee3e6
Remove HN from default blocked sites list
Mar 2, 2026
dad5747
Clean up site/app selection flow in focus setup
Mar 2, 2026
4ce1376
Fix custom sites input submitting placeholder as value
Mar 2, 2026
28d8548
Only show music option when a source is detected
Mar 2, 2026
2aff840
Add Custom option to site picker + music presets per source
Mar 2, 2026
ce00d31
Fix YouTube music: use ytsearch for preset queries
Mar 2, 2026
2986917
Add background timer that notifies when focus session ends
Mar 3, 2026
acdd495
Fix 6 bugs found in focus mode audit
Mar 3, 2026
3f9dd36
Add non-interactive focus commands for Claude Code
Mar 3, 2026
3c3ae4a
Auto-end focus session with Claude summary via Telegram
Mar 3, 2026
c563f56
Rewrite SKILL.md: Claude orchestrates focus directly
Mar 3, 2026
8b77eb6
Generate personalized SKILL.md from focus setup wizard
Mar 3, 2026
68117b5
Remove focus from skill catalog β€” setup handles everything
Mar 3, 2026
6eb2971
Remove JSON read instruction from generated SKILL.md
Mar 3, 2026
8fb709b
Simplify SKILL.md to static template pointing to JSON
Mar 3, 2026
9edccaa
Make openpaw focus show config instead of starting a session
Mar 3, 2026
ac7ed86
Sync repo SKILL.md template with installed version
Mar 3, 2026
0a5b9d2
Use select options for light color instead of text input
Mar 3, 2026
8105656
Ask where to install focus skill in setup wizard
Mar 3, 2026
497276a
Update setup outro to point to Claude instead of CLI
Mar 3, 2026
bcda1dc
Add paw walk animation between focus setup wizard steps
Mar 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
153 changes: 153 additions & 0 deletions skills/c-focus/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
---
name: c-focus
description: Focus Mode β€” orchestrate distraction blocking, environment setup, and session tracking.
tags: [focus, productivity, deep-work, pomodoro, distraction-blocking]
---

## What This Skill Does

You orchestrate focus sessions by reading the user's config and running shell commands directly.

## Config

Read `~/.config/openpaw/focus.json` for preferences. If missing, suggest: `openpaw focus setup`

```json
{
"duration": 90,
"bluetooth": { "device": "AirPods Pro" },
"music": { "source": "spotify", "query": "lo-fi beats" },
"blockedSites": {
"always": ["x.com", "reddit.com"],
"askEachTime": ["youtube.com"]
},
"quitApps": {
"always": ["Messages", "Mail"],
"askEachTime": ["Discord"]
},
"lights": { "room": "Office", "brightness": 30, "color": "warm" },
"dnd": true,
"slackDnd": true,
"timer": true,
"obsidianLog": true
}
```

## Starting a Focus Session

When the user says "focus", "deep work", "lock in", or similar:

1. Read `~/.config/openpaw/focus.json`
2. Check `~/.config/openpaw/focus-session.json` β€” if it exists, a session is already active
3. If there are `askEachTime` sites or apps, ask the user which to include this session
4. Tell the user what you're about to do, then execute each enabled step:

### Commands to Run (in order)

**Block websites** (if `blockedSites` configured):
```bash
# For each site in always + user-approved askEachTime list:
echo "127.0.0.1 site.com # OPENPAW-FOCUS
127.0.0.1 www.site.com # OPENPAW-FOCUS" | sudo tee -a /etc/hosts > /dev/null
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
```

**Quit apps** (if `quitApps` configured):
```bash
osascript -e 'quit app "AppName"'
```

**Connect bluetooth** (if `bluetooth` configured):
```bash
blu connect "device name"
```

**Play music** (if `music` configured):
```bash
# spotify:
spogo search playlist "query" --play
# apple-music:
osascript -e 'tell application "Music" to play playlist "query"'
# sonos:
sonos play "query"
# youtube (yt-dlp β€” prefix non-URLs with ytsearch1:):
yt-dlp -x --audio-format mp3 -o "/tmp/openpaw-focus.%(ext)s" "ytsearch1:query" && afplay /tmp/openpaw-focus.mp3 &
```

**Set lights** (if `lights` configured):
```bash
openhue set room "room" --on --brightness N --color "color"
```

**Enable DND** (if `dnd: true`):
```bash
defaults -currentHost write ~/Library/Preferences/ByHost/com.apple.notificationcenterui doNotDisturb -boolean true
killall NotificationCenter
```

**Slack DND** (if `slackDnd: true`):
```bash
slack dnd set <duration>
```

**Write the session file** to `~/.config/openpaw/focus-session.json`:
```json
{
"startedAt": "<ISO timestamp>",
"endsAt": "<ISO timestamp + duration>",
"config": { ... },
"blockedSiteAttempts": 0,
"gitCommitsBefore": <output of git rev-list --count HEAD>
}
```

**Start the auto-end timer:**
```bash
openpaw focus auto-end &
```
This sleeps for the duration, then restores everything and sends a summary via Telegram.

Or run `openpaw focus start` to do all of the above automatically.

## Ending a Focus Session

When the user says "stop focus", "end focus", "I'm done", or the timer fires:

1. **Restore environment:**
```bash
# Unblock sites
sudo sed -i '' '/OPENPAW-FOCUS/d' /etc/hosts
sudo dscacheutil -flushcache
# Disable DND
defaults -currentHost write ~/Library/Preferences/ByHost/com.apple.notificationcenterui doNotDisturb -boolean false
killall NotificationCenter
# Stop music (use the matching command for the source)
spogo pause
```

2. **Generate receipt:**
```bash
git rev-list --count HEAD # subtract gitCommitsBefore from session file
git diff --stat HEAD~N HEAD
```

3. **Summarize naturally** β€” how long they focused, commits made, lines added/removed. Be encouraging.
4. **Log to Obsidian** if `obsidianLog: true`
5. Delete `~/.config/openpaw/focus-session.json`

## Reconfigure

```bash
openpaw focus setup # Interactive wizard
openpaw focus configure # Alias
```

## Guidelines

- Only start focus when the user explicitly asks β€” never suggest unprompted
- Always tell the user what you're doing before each step
- If a command fails (e.g. sudo denied), tell the user and continue with other steps
- Skip any step whose config field is missing or false
- Reference SOUL.md for personal preferences
- When ending, write a human summary β€” don't just dump numbers
1 change: 0 additions & 1 deletion src/catalog/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,6 @@ export const skills: Skill[] = [
platforms: ["darwin", "linux", "win32"],
depends: ["email", "calendar"],
},

// ── Browser & Automation ──
{
id: "browser",
Expand Down
3 changes: 2 additions & 1 deletion src/commands/configure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export async function configureCommand(): Promise<void> {
{ value: "soul", label: "Edit personality", hint: "name, tone, verbosity" },
{ value: "dashboard", label: "Open dashboard", hint: "task manager in browser" },
{ value: "telegram", label: "Telegram setup", hint: "configure bot bridge" },
{ value: "schedule", label: "Manage schedules", hint: "recurring tasks + cost control" },
{ value: "focus setup", label: "Focus Mode", hint: "block distractions, set the mood" },
{ value: "schedule", label: "Manage schedules", hint: "recurring tasks + cost control" },
{ value: "status", label: "View status", hint: "see what's installed" },
{ value: "doctor", label: "Run diagnostics", hint: "check for issues" },
],
Expand Down
Loading
Loading