-
Notifications
You must be signed in to change notification settings - Fork 628
Expand file tree
/
Copy pathsession_start.py
More file actions
executable file
·195 lines (164 loc) · 6.05 KB
/
Copy pathsession_start.py
File metadata and controls
executable file
·195 lines (164 loc) · 6.05 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
#!/usr/bin/env -S uv run --script
# /// script
# requires-python = ">=3.11"
# dependencies = [
# "python-dotenv",
# ]
# ///
import argparse
import json
import os
import sys
import subprocess
from pathlib import Path
from datetime import datetime
try:
from dotenv import load_dotenv
load_dotenv()
except ImportError:
pass # dotenv is optional
from _log_common import append_log_data
def get_git_status():
"""Get current git status information."""
try:
# Get current branch
branch_result = subprocess.run(
['git', 'rev-parse', '--abbrev-ref', 'HEAD'],
cwd=os.getenv('CLAUDE_PROJECT_DIR'),
capture_output=True,
text=True,
timeout=5
)
current_branch = branch_result.stdout.strip() if branch_result.returncode == 0 else "unknown"
# Get uncommitted changes count
status_result = subprocess.run(
['git', 'status', '--porcelain'],
cwd=os.getenv('CLAUDE_PROJECT_DIR'),
capture_output=True,
text=True,
timeout=5
)
if status_result.returncode == 0:
changes = status_result.stdout.strip().split('\n') if status_result.stdout.strip() else []
uncommitted_count = len(changes)
else:
uncommitted_count = 0
return current_branch, uncommitted_count
except Exception:
return None, None
def get_recent_issues():
"""Get recent GitHub issues if gh CLI is available."""
try:
# Check if gh is available
gh_check = subprocess.run(['which', 'gh'], capture_output=True)
if gh_check.returncode != 0:
return None
# Get recent open issues
result = subprocess.run(
['gh', 'issue', 'list', '--limit', '5', '--state', 'open'],
cwd=os.getenv('CLAUDE_PROJECT_DIR'),
capture_output=True,
text=True,
timeout=10
)
if result.returncode == 0 and result.stdout.strip():
return result.stdout.strip()
except Exception:
pass
return None
def load_development_context(source):
"""Load relevant development context based on session source."""
context_parts = []
# Add timestamp
context_parts.append(f"Session started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
context_parts.append(f"Session source: {source}")
# Add git information
branch, changes = get_git_status()
if branch:
context_parts.append(f"Git branch: {branch}")
if changes > 0:
context_parts.append(f"Uncommitted changes: {changes} files")
# Load project-specific context files if they exist
context_files = [
".claude/CONTEXT.md",
".claude/TODO.md",
"TODO.md",
".github/ISSUE_TEMPLATE.md"
]
project_dir = Path(os.getenv("CLAUDE_PROJECT_DIR", ""))
for file_path in context_files:
full_path = project_dir / file_path
if full_path.exists():
try:
with open(full_path, 'rt') as f:
content = f.read().strip()
if content:
context_parts.append(f"\n--- Content from {file_path} ---")
context_parts.append(content[:1000]) # Limit to first 1000 chars
except Exception:
pass
# Add recent issues if available
issues = get_recent_issues()
if issues:
context_parts.append("\n--- Recent GitHub Issues ---")
context_parts.append(issues)
return "\n".join(context_parts)
def main():
try:
# Parse command line arguments
parser = argparse.ArgumentParser()
parser.add_argument('--load-context', action='store_true',
help='Load development context at session start')
parser.add_argument('--announce', action='store_true',
help='Announce session start via TTS')
args = parser.parse_args()
# Read JSON input from stdin
input_data = json.loads(sys.stdin.read())
# Extract fields
session_id = input_data.get('session_id', 'unknown')
source = input_data.get('source', 'unknown') # "startup", "resume", or "clear"
# Log the session start event
append_log_data('session_start.json', input_data)
# Load development context if requested
if args.load_context:
context = load_development_context(source)
if context:
# Using JSON output to add context
output = {
"hookSpecificOutput": {
"hookEventName": "SessionStart",
"additionalContext": context
}
}
print(json.dumps(output))
sys.exit(0)
# Announce session start if requested
if args.announce:
try:
# Try to use TTS to announce session start
script_dir = Path(__file__).parent
tts_script = script_dir / "utils" / "tts" / "pyttsx3_tts.py"
if tts_script.exists():
messages = {
"startup": "Claude Code session started",
"resume": "Resuming previous session",
"clear": "Starting fresh session"
}
message = messages.get(source, "Session started")
subprocess.run(
["uv", "run", str(tts_script), message],
capture_output=True,
timeout=5
)
except Exception:
pass
# Success
sys.exit(0)
except json.JSONDecodeError:
# Handle JSON decode errors gracefully
sys.exit(0)
except Exception:
# Handle any other errors gracefully
sys.exit(0)
if __name__ == '__main__':
main()