Set up /pause for Claude Code - auto-rename sessions, create terminal deeplinks, set task manager reminders
Copy everything in the box below and paste it into Claude Code.
Help me set up a /pause command for Claude Code session management.
## What this does
When I run "/pause for 3 days", it:
1. **Auto-renames the current session** using the marker approach (works even with multiple concurrent sessions!)
2. Creates a one-click terminal deeplink to resume
3. Creates a reminder in my task manager with the link + context
Later: reminder pops up → I click the link → terminal opens → runs `claude --resume "Session Name"` → I'm back exactly where I left off.
## Walk me through setup
Ask me two questions:
**Question 1: Which terminal do you use?**
- Warp
- iTerm2
- Terminal.app
- Hyper/Alacritty/Kitty
- Other
**Question 2: Which task manager do you use?**
- Todoist
- Things 3
- Apple Reminders
- Notion
- Linear
- None / I'll just copy the link manually
Then create the script and command file based on my answers.
## Implementation details you'll need
### Core session detection - THE MARKER APPROACH (use this exactly)
The marker approach reliably identifies THIS session even with concurrent sessions:
1. Generate unique marker → echo it → marker is written to session JSONL file
2. Search all session files for that marker → found file = THIS session
3. Append custom-title entry → session is renamed
```python
import json, os, re, sys, uuid, glob
from pathlib import Path
def get_sessions_dir():
"""Get the Claude sessions directory for the current project."""
cwd = os.getcwd()
project_key = cwd.replace('/', '-')
sessions_dir = Path.home() / '.claude' / 'projects' / project_key
if not sessions_dir.exists():
projects_dir = Path.home() / '.claude' / 'projects'
for d in projects_dir.iterdir():
if d.is_dir() and project_key in str(d):
return d
raise RuntimeError(f"No project dir found for {cwd}")
return sessions_dir
def generate_marker() -> str:
"""Generate a unique marker. Must be echoed to be captured in session file."""
marker = f"__PAUSE_MARKER_{uuid.uuid4().hex}__"
print(marker)
return marker
def find_session_by_marker(marker: str):
"""Find the session file containing the marker. Most reliable method."""
sessions_dir = get_sessions_dir()
for filepath in glob.glob(str(sessions_dir / '*.jsonl')):
try:
with open(filepath, 'r', encoding='utf-8', errors='ignore') as f:
if marker in f.read():
return Path(filepath).stem, Path(filepath)
except Exception:
continue
return None
def rename_session(session_id: str, jsonl_path: Path, name: str):
"""Rename by appending custom-title entry to the jsonl file."""
entry = {
"type": "custom-title",
"customTitle": name,
"sessionId": session_id
}
with open(jsonl_path, 'a') as f:
# CRITICAL: Write with trailing newline to prevent concatenation
# with Claude's next write (this breaks parsing otherwise!)
f.write(json.dumps(entry) + '\n')
f.flush()
os.fsync(f.fileno())
print(f"✓ Session renamed: {name}")
CRITICAL: Two-step process required from Claude
The script must support a marker command for generating markers:
def main():
if len(sys.argv) < 2:
print("Usage: pause.py marker | pause.py 'Name' 'due' 'context' 'marker'")
sys.exit(1)
# Step 1: Generate marker (Claude calls this first, echoes output)
if sys.argv[1] == "marker":
generate_marker()
return
# Step 2: Pause the session (Claude calls this with the marker)
name = sys.argv[1]
due = sys.argv[2] if len(sys.argv) > 2 else "tomorrow"
context = sys.argv[3] if len(sys.argv) > 3 else "Continue where we left off"
marker = sys.argv[4] if len(sys.argv) > 4 else None
if marker:
result = find_session_by_marker(marker)
if result:
session_id, jsonl_path = result
else:
print("⚠️ Marker not found, using fallback")
session_id, jsonl_path = get_current_session_fallback()
else:
print("⚠️ No marker - less reliable with concurrent sessions")
session_id, jsonl_path = get_current_session_fallback()
# ... rest of implementation (rename, create deeplink, create task)Warp:
def create_warp_config(name: str, cwd: str) -> str:
safe_name = re.sub(r'[^a-zA-Z0-9_-]', '-', name.lower())
safe_name = re.sub(r'-+', '-', safe_name).strip('-')
config_dir = Path.home() / '.warp' / 'launch_configurations'
config_dir.mkdir(parents=True, exist_ok=True)
config_path = config_dir / f"parked-{safe_name}.yaml"
# CRITICAL: name field MUST match filename or deeplink silently fails
config = f'''name: "parked-{safe_name}"
windows:
- tabs:
- title: "{name}"
layout:
cwd: "{cwd}"
commands:
- exec: claude --resume "{name}"
'''
config_path.write_text(config)
return f"warp://launch/parked-{safe_name}"iTerm2:
def create_iterm_command(name: str, cwd: str) -> str:
script = f'''osascript -e 'tell app "iTerm2" to create window with default profile command "cd {cwd} && claude --resume \\"{name}\\""' '''
return scriptTerminal.app:
def create_terminal_command(name: str, cwd: str) -> str:
script = f'''osascript -e 'tell app "Terminal" to do script "cd {cwd} && claude --resume \\"{name}\\""' '''
return scriptOther terminals: Just output claude --resume "{name}" and tell them to run it manually.
Todoist:
import requests
def create_todoist_task(name, due, context, deeplink, session_id):
TOKEN = os.environ.get("TODOIST_API_TOKEN") # or hardcode it
description = f"""## Resume
{deeplink}
## Manual
claude --resume "{name}"
## Context
{context}
## Session ID (fallback)
{session_id}
"""
requests.post(
"https://api.todoist.com/rest/v2/tasks",
headers={"Authorization": f"Bearer {TOKEN}"},
json={
"content": f"Resume: {name}",
"description": description,
"due_string": due,
"priority": 2
}
)Token from: Todoist Settings → Integrations → Developer
Things 3:
import subprocess, urllib.parse
def create_things_task(name, due, context, deeplink, session_id):
notes = f"{deeplink}\n\n{context}\n\nSession: {session_id}"
url = f"things:///add?title={urllib.parse.quote(f'Resume: {name}')}¬es={urllib.parse.quote(notes)}&when={due}"
subprocess.run(["open", url])Apple Reminders / Notion / Linear: See original implementations - they work the same, just pass the deeplink and context.
None: Just print the deeplink and manual command.
Create ~/.claude/commands/pause.md:
# /pause - Pause this conversation for later
When user runs `/pause [timeframe]`:
1. **Generate session name** (3-6 words, captures what we worked on)
2. **Gather context:**
- What was accomplished this session
- What's blocked or waiting on something
- What to do first when resuming
- Key files created or modified
3. **Run the script (TWO-STEP PROCESS - CRITICAL):**
Step 1: Generate marker (must complete before step 2)
```bash
MARKER=$(~/.claude/scripts/pause.py marker) && echo "$MARKER"Step 2: Pause the session using the marker (separate bash call)
~/.claude/scripts/pause.py "[NAME]" "[TIMEFRAME]" "[CONTEXT]" "$MARKER"- Confirm: ⏸️ Paused: [NAME] ✓ Session renamed (via marker) ✓ Terminal config created ✓ Reminder set for [date]
## How session renaming actually works (for the nerds)
Claude Code stores sessions as JSONL files at `~/.claude/projects/[project-key]/[uuid].jsonl`.
To rename a session, you append this entry:
```json
{"type": "custom-title", "customTitle": "My Session Name", "sessionId": "uuid-here"}
The gotchas we discovered:
- Field is
customTitle(nottitle) - took reverse-engineering to figure out - Must include
sessionIdfield - Entry MUST have a trailing newline - without it, Claude's next write concatenates directly after your entry, breaking the JSONL format
- With concurrent sessions, "most recently modified file" heuristics fail - you might rename the wrong session
The marker approach solves concurrent sessions:
- Generate a unique marker string (UUID-based)
- Echo it - this output gets written to THIS session's JSONL file as part of the tool result
- Search all session files for that marker - it only exists in THIS session's file
- Now you know exactly which file to modify
This is why two bash calls are required: the marker must be written to the file (when Step 1 completes) before Step 2 can search for it.
Test it by running /pause for a day in a session. Should:
- Rename the session (verify with
/resume- you should see your custom name) - Create terminal config (check ~/.warp/launch_configurations/ if using Warp)
- Create task in your task manager
Then test the deeplink actually works by clicking it.
- Warp deeplink just brings Warp to front: The
name:field in the YAML doesn't match the filename. Must be exact match without .yaml extension. - "No project dir found": Run from same directory where you started Claude.
- Session not renamed correctly: Make sure you're using the two-step marker approach. Without the marker, the script has to guess which session is yours (unreliable with concurrent sessions).
- Entry not appearing in
/resume: Check that your script writes with a trailing newline, not a leading one.