claude-code-tools 0.2.1__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of claude-code-tools might be problematic. Click here for more details.
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/PKG-INFO +13 -2
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/README.md +12 -1
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/__init__.py +1 -1
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/find_claude_session.py +40 -26
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/find_codex_session.py +14 -17
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/pyproject.toml +2 -2
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/.gitignore +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/LICENSE +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/codex_bridge_mcp.py +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/dotenv_vault.py +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/env_safe.py +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/tmux_cli_controller.py +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/tmux_remote_controller.py +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/cc-codex-instructions.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/claude-code-chutes.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/claude-code-tmux-tutorials.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/dot-zshrc.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/find-claude-session.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/lmsh.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/reddit-post.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/tmux-cli-instructions.md +0 -0
- {claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/docs/vault-documentation.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: claude-code-tools
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Collection of tools for working with Claude Code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -215,10 +215,16 @@ fcs "keywords" -g
|
|
|
215
215
|
|
|
216
216
|
### Features
|
|
217
217
|
|
|
218
|
+
- **Action menu** after session selection:
|
|
219
|
+
- Resume session (default)
|
|
220
|
+
- Show session file path
|
|
221
|
+
- Copy session file to file (*.jsonl) or directory
|
|
218
222
|
- Interactive session selection with previews
|
|
219
|
-
- Cross-project search capabilities
|
|
223
|
+
- Cross-project search capabilities (local by default, `-g` for global)
|
|
224
|
+
- Shows last user message preview (filtered, multi-line wrapping)
|
|
220
225
|
- Automatic session resumption with `claude -r`
|
|
221
226
|
- Persistent directory changes when resuming cross-project sessions
|
|
227
|
+
- Press Enter to cancel (no need for Ctrl+C)
|
|
222
228
|
|
|
223
229
|
Note: You can also use `find-claude-session` directly, but directory changes
|
|
224
230
|
won't persist after exiting Claude Code.
|
|
@@ -259,6 +265,10 @@ find-codex-session "keywords" --codex-home /custom/path
|
|
|
259
265
|
|
|
260
266
|
### Features
|
|
261
267
|
|
|
268
|
+
- **Action menu** after session selection:
|
|
269
|
+
- Resume session (default)
|
|
270
|
+
- Show session file path
|
|
271
|
+
- Copy session file to file (*.jsonl) or directory
|
|
262
272
|
- **Project filtering**: Search current project only (default) or all projects with `-g`
|
|
263
273
|
- Case-insensitive AND keyword search across all session content
|
|
264
274
|
- Interactive session selection with Rich table display
|
|
@@ -267,6 +277,7 @@ find-codex-session "keywords" --codex-home /custom/path
|
|
|
267
277
|
- Cross-project session support with directory change prompts
|
|
268
278
|
- Reverse chronological ordering (most recent first)
|
|
269
279
|
- Multi-line preview wrapping for better readability
|
|
280
|
+
- Press Enter to cancel (no need for Ctrl+C)
|
|
270
281
|
|
|
271
282
|
Looks like this --
|
|
272
283
|
|
|
@@ -201,10 +201,16 @@ fcs "keywords" -g
|
|
|
201
201
|
|
|
202
202
|
### Features
|
|
203
203
|
|
|
204
|
+
- **Action menu** after session selection:
|
|
205
|
+
- Resume session (default)
|
|
206
|
+
- Show session file path
|
|
207
|
+
- Copy session file to file (*.jsonl) or directory
|
|
204
208
|
- Interactive session selection with previews
|
|
205
|
-
- Cross-project search capabilities
|
|
209
|
+
- Cross-project search capabilities (local by default, `-g` for global)
|
|
210
|
+
- Shows last user message preview (filtered, multi-line wrapping)
|
|
206
211
|
- Automatic session resumption with `claude -r`
|
|
207
212
|
- Persistent directory changes when resuming cross-project sessions
|
|
213
|
+
- Press Enter to cancel (no need for Ctrl+C)
|
|
208
214
|
|
|
209
215
|
Note: You can also use `find-claude-session` directly, but directory changes
|
|
210
216
|
won't persist after exiting Claude Code.
|
|
@@ -245,6 +251,10 @@ find-codex-session "keywords" --codex-home /custom/path
|
|
|
245
251
|
|
|
246
252
|
### Features
|
|
247
253
|
|
|
254
|
+
- **Action menu** after session selection:
|
|
255
|
+
- Resume session (default)
|
|
256
|
+
- Show session file path
|
|
257
|
+
- Copy session file to file (*.jsonl) or directory
|
|
248
258
|
- **Project filtering**: Search current project only (default) or all projects with `-g`
|
|
249
259
|
- Case-insensitive AND keyword search across all session content
|
|
250
260
|
- Interactive session selection with Rich table display
|
|
@@ -253,6 +263,7 @@ find-codex-session "keywords" --codex-home /custom/path
|
|
|
253
263
|
- Cross-project session support with directory change prompts
|
|
254
264
|
- Reverse chronological ordering (most recent first)
|
|
255
265
|
- Multi-line preview wrapping for better readability
|
|
266
|
+
- Press Enter to cancel (no need for Ctrl+C)
|
|
256
267
|
|
|
257
268
|
Looks like this --
|
|
258
269
|
|
{claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/find_claude_session.py
RENAMED
|
@@ -220,17 +220,17 @@ def get_session_preview(filepath: Path) -> str:
|
|
|
220
220
|
return last_user_message if last_user_message else "No preview available"
|
|
221
221
|
|
|
222
222
|
|
|
223
|
-
def find_sessions(keywords: List[str], global_search: bool = False, claude_home: Optional[str] = None) -> List[Tuple[str, float, int, str, str, str, Optional[str]]]:
|
|
223
|
+
def find_sessions(keywords: List[str], global_search: bool = False, claude_home: Optional[str] = None) -> List[Tuple[str, float, float, int, str, str, str, Optional[str]]]:
|
|
224
224
|
"""
|
|
225
225
|
Find all Claude Code sessions containing the specified keywords.
|
|
226
|
-
|
|
226
|
+
|
|
227
227
|
Args:
|
|
228
228
|
keywords: List of keywords to search for
|
|
229
229
|
global_search: If True, search all projects; if False, search current project only
|
|
230
230
|
claude_home: Optional custom Claude home directory (defaults to ~/.claude)
|
|
231
|
-
|
|
231
|
+
|
|
232
232
|
Returns:
|
|
233
|
-
List of tuples (session_id, modification_time, line_count, project_name, preview, project_path, git_branch) sorted by modification time
|
|
233
|
+
List of tuples (session_id, modification_time, creation_time, line_count, project_name, preview, project_path, git_branch) sorted by modification time
|
|
234
234
|
"""
|
|
235
235
|
matching_sessions = []
|
|
236
236
|
|
|
@@ -256,23 +256,29 @@ def find_sessions(keywords: List[str], global_search: bool = False, claude_home:
|
|
|
256
256
|
matches, line_count, git_branch = search_keywords_in_file(jsonl_file, keywords)
|
|
257
257
|
if matches:
|
|
258
258
|
session_id = jsonl_file.stem
|
|
259
|
-
|
|
259
|
+
stat = jsonl_file.stat()
|
|
260
|
+
mod_time = stat.st_mtime
|
|
261
|
+
# Get creation time (birthtime on macOS, ctime elsewhere)
|
|
262
|
+
create_time = getattr(stat, 'st_birthtime', stat.st_ctime)
|
|
260
263
|
preview = get_session_preview(jsonl_file)
|
|
261
|
-
matching_sessions.append((session_id, mod_time, line_count, project_name, preview, original_path, git_branch))
|
|
264
|
+
matching_sessions.append((session_id, mod_time, create_time, line_count, project_name, preview, original_path, git_branch))
|
|
262
265
|
|
|
263
266
|
progress.advance(task)
|
|
264
267
|
else:
|
|
265
268
|
# Fallback without rich
|
|
266
269
|
for project_dir, original_path in projects:
|
|
267
270
|
project_name = extract_project_name(original_path)
|
|
268
|
-
|
|
271
|
+
|
|
269
272
|
for jsonl_file in project_dir.glob("*.jsonl"):
|
|
270
273
|
matches, line_count, git_branch = search_keywords_in_file(jsonl_file, keywords)
|
|
271
274
|
if matches:
|
|
272
275
|
session_id = jsonl_file.stem
|
|
273
|
-
|
|
276
|
+
stat = jsonl_file.stat()
|
|
277
|
+
mod_time = stat.st_mtime
|
|
278
|
+
# Get creation time (birthtime on macOS, ctime elsewhere)
|
|
279
|
+
create_time = getattr(stat, 'st_birthtime', stat.st_ctime)
|
|
274
280
|
preview = get_session_preview(jsonl_file)
|
|
275
|
-
matching_sessions.append((session_id, mod_time, line_count, project_name, preview, original_path, git_branch))
|
|
281
|
+
matching_sessions.append((session_id, mod_time, create_time, line_count, project_name, preview, original_path, git_branch))
|
|
276
282
|
else:
|
|
277
283
|
# Search current project only
|
|
278
284
|
claude_dir = get_claude_project_dir(claude_home)
|
|
@@ -287,9 +293,12 @@ def find_sessions(keywords: List[str], global_search: bool = False, claude_home:
|
|
|
287
293
|
matches, line_count, git_branch = search_keywords_in_file(jsonl_file, keywords)
|
|
288
294
|
if matches:
|
|
289
295
|
session_id = jsonl_file.stem
|
|
290
|
-
|
|
296
|
+
stat = jsonl_file.stat()
|
|
297
|
+
mod_time = stat.st_mtime
|
|
298
|
+
# Get creation time (birthtime on macOS, ctime elsewhere)
|
|
299
|
+
create_time = getattr(stat, 'st_birthtime', stat.st_ctime)
|
|
291
300
|
preview = get_session_preview(jsonl_file)
|
|
292
|
-
matching_sessions.append((session_id, mod_time, line_count, project_name, preview, os.getcwd(), git_branch))
|
|
301
|
+
matching_sessions.append((session_id, mod_time, create_time, line_count, project_name, preview, os.getcwd(), git_branch))
|
|
293
302
|
|
|
294
303
|
# Sort by modification time (newest first)
|
|
295
304
|
matching_sessions.sort(key=lambda x: x[1], reverse=True)
|
|
@@ -326,19 +335,22 @@ def display_interactive_ui(sessions: List[Tuple[str, float, int, str, str, str,
|
|
|
326
335
|
table.add_column("Session ID", style="dim")
|
|
327
336
|
table.add_column("Project", style="green")
|
|
328
337
|
table.add_column("Branch", style="magenta")
|
|
329
|
-
table.add_column("Date", style="blue")
|
|
338
|
+
table.add_column("Date-Range", style="blue")
|
|
330
339
|
table.add_column("Lines", style="cyan", justify="right")
|
|
331
|
-
table.add_column("
|
|
340
|
+
table.add_column("Last User Message", style="white", max_width=60, overflow="fold")
|
|
332
341
|
|
|
333
|
-
for idx, (session_id, mod_time, line_count, project_name, preview, _, git_branch) in enumerate(display_sessions, 1):
|
|
334
|
-
|
|
342
|
+
for idx, (session_id, mod_time, create_time, line_count, project_name, preview, _, git_branch) in enumerate(display_sessions, 1):
|
|
343
|
+
# Format: "10/04 - 10/09 13:45"
|
|
344
|
+
create_date = datetime.fromtimestamp(create_time).strftime('%m/%d')
|
|
345
|
+
mod_date = datetime.fromtimestamp(mod_time).strftime('%m/%d %H:%M')
|
|
346
|
+
date_display = f"{create_date} - {mod_date}"
|
|
335
347
|
branch_display = git_branch if git_branch else "N/A"
|
|
336
348
|
table.add_row(
|
|
337
349
|
str(idx),
|
|
338
350
|
session_id[:8] + "...",
|
|
339
351
|
project_name,
|
|
340
352
|
branch_display,
|
|
341
|
-
|
|
353
|
+
date_display,
|
|
342
354
|
str(line_count),
|
|
343
355
|
preview
|
|
344
356
|
)
|
|
@@ -402,13 +414,13 @@ def display_interactive_ui(sessions: List[Tuple[str, float, int, str, str, str,
|
|
|
402
414
|
ui_console.print("[red]Invalid choice. Please try again.[/red]")
|
|
403
415
|
|
|
404
416
|
|
|
405
|
-
def show_action_menu(session_info: Tuple[str, float, int, str, str, str, Optional[str]]) -> Optional[str]:
|
|
417
|
+
def show_action_menu(session_info: Tuple[str, float, float, int, str, str, str, Optional[str]]) -> Optional[str]:
|
|
406
418
|
"""
|
|
407
419
|
Show action menu for selected session.
|
|
408
420
|
|
|
409
421
|
Returns: action choice ('resume', 'path', 'copy') or None if cancelled
|
|
410
422
|
"""
|
|
411
|
-
session_id, _, _, project_name, _, project_path, git_branch = session_info
|
|
423
|
+
session_id, _, _, _, project_name, _, project_path, git_branch = session_info
|
|
412
424
|
|
|
413
425
|
print(f"\n=== Session: {session_id[:8]}... ===")
|
|
414
426
|
print(f"Project: {project_name}")
|
|
@@ -649,7 +661,7 @@ To persist directory changes when resuming sessions:
|
|
|
649
661
|
return
|
|
650
662
|
|
|
651
663
|
session_id = selected_session[0]
|
|
652
|
-
project_path = selected_session[
|
|
664
|
+
project_path = selected_session[6] # Updated index after adding creation_time
|
|
653
665
|
|
|
654
666
|
# Perform selected action
|
|
655
667
|
if action == "resume":
|
|
@@ -665,22 +677,24 @@ To persist directory changes when resuming sessions:
|
|
|
665
677
|
# Fallback: print session IDs as before
|
|
666
678
|
if not args.shell:
|
|
667
679
|
print("\nMatching sessions:")
|
|
668
|
-
for idx, (session_id, mod_time, line_count, project_name, preview, project_path, git_branch) in enumerate(matching_sessions[:args.num_matches], 1):
|
|
669
|
-
|
|
680
|
+
for idx, (session_id, mod_time, create_time, line_count, project_name, preview, project_path, git_branch) in enumerate(matching_sessions[:args.num_matches], 1):
|
|
681
|
+
create_date = datetime.fromtimestamp(create_time).strftime('%m/%d')
|
|
682
|
+
mod_date = datetime.fromtimestamp(mod_time).strftime('%m/%d %H:%M')
|
|
683
|
+
date_display = f"{create_date} - {mod_date}"
|
|
670
684
|
branch_display = git_branch if git_branch else "N/A"
|
|
671
685
|
if getattr(args, 'global'):
|
|
672
|
-
print(f"{idx}. {session_id} | {project_name} | {branch_display} | {
|
|
686
|
+
print(f"{idx}. {session_id} | {project_name} | {branch_display} | {date_display} | {line_count} lines", file=sys.stderr if args.shell else sys.stdout)
|
|
673
687
|
else:
|
|
674
|
-
print(f"{idx}. {session_id} | {branch_display} | {
|
|
675
|
-
|
|
688
|
+
print(f"{idx}. {session_id} | {branch_display} | {date_display} | {line_count} lines", file=sys.stderr if args.shell else sys.stdout)
|
|
689
|
+
|
|
676
690
|
if len(matching_sessions) > args.num_matches:
|
|
677
691
|
print(f"\n... and {len(matching_sessions) - args.num_matches} more sessions", file=sys.stderr if args.shell else sys.stdout)
|
|
678
|
-
|
|
692
|
+
|
|
679
693
|
# Simple selection without rich
|
|
680
694
|
if len(matching_sessions) == 1:
|
|
681
695
|
if not args.shell:
|
|
682
696
|
print("\nOnly one match found. Resuming automatically...")
|
|
683
|
-
session_id, _, _, _, _, project_path, _ = matching_sessions[0]
|
|
697
|
+
session_id, _, _, _, _, _, project_path, _ = matching_sessions[0]
|
|
684
698
|
resume_session(session_id, project_path, shell_mode=args.shell)
|
|
685
699
|
else:
|
|
686
700
|
try:
|
|
@@ -242,19 +242,15 @@ def find_sessions(
|
|
|
242
242
|
if current_cwd and metadata["cwd"] != current_cwd:
|
|
243
243
|
continue
|
|
244
244
|
|
|
245
|
-
#
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
date_str = timestamp_str[:16]
|
|
255
|
-
else:
|
|
256
|
-
# Fallback to directory date
|
|
257
|
-
date_str = f"{year_dir.name}-{month_dir.name}-{day_dir.name}"
|
|
245
|
+
# Get file stats for timestamps
|
|
246
|
+
stat = session_file.stat()
|
|
247
|
+
mod_time = stat.st_mtime
|
|
248
|
+
create_time = getattr(stat, 'st_birthtime', stat.st_ctime)
|
|
249
|
+
|
|
250
|
+
# Format dates: "10/04 - 10/09 13:45"
|
|
251
|
+
create_date = datetime.fromtimestamp(create_time).strftime("%m/%d")
|
|
252
|
+
mod_date = datetime.fromtimestamp(mod_time).strftime("%m/%d %H:%M")
|
|
253
|
+
date_str = f"{create_date} - {mod_date}"
|
|
258
254
|
|
|
259
255
|
matches.append(
|
|
260
256
|
{
|
|
@@ -262,6 +258,7 @@ def find_sessions(
|
|
|
262
258
|
"project": get_project_name(metadata["cwd"]),
|
|
263
259
|
"branch": metadata["branch"] or "",
|
|
264
260
|
"date": date_str,
|
|
261
|
+
"mod_time": mod_time, # For sorting
|
|
265
262
|
"lines": line_count,
|
|
266
263
|
"preview": preview or "No preview",
|
|
267
264
|
"cwd": metadata["cwd"],
|
|
@@ -273,8 +270,8 @@ def find_sessions(
|
|
|
273
270
|
if len(matches) >= num_matches * 3:
|
|
274
271
|
break
|
|
275
272
|
|
|
276
|
-
# Sort by
|
|
277
|
-
matches.sort(key=lambda x: x["
|
|
273
|
+
# Sort by modification time (newest first) and limit
|
|
274
|
+
matches.sort(key=lambda x: x["mod_time"], reverse=True)
|
|
278
275
|
return matches[:num_matches]
|
|
279
276
|
|
|
280
277
|
|
|
@@ -297,9 +294,9 @@ def display_interactive_ui(
|
|
|
297
294
|
table.add_column("Session ID", style="yellow", no_wrap=True)
|
|
298
295
|
table.add_column("Project", style="green")
|
|
299
296
|
table.add_column("Branch", style="magenta")
|
|
300
|
-
table.add_column("Date", style="blue")
|
|
297
|
+
table.add_column("Date-Range", style="blue")
|
|
301
298
|
table.add_column("Lines", justify="right")
|
|
302
|
-
table.add_column("
|
|
299
|
+
table.add_column("Last User Message", style="dim", max_width=60, overflow="fold")
|
|
303
300
|
|
|
304
301
|
for i, match in enumerate(matches, 1):
|
|
305
302
|
table.add_row(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "claude-code-tools"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.3"
|
|
4
4
|
description = "Collection of tools for working with Claude Code"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -43,7 +43,7 @@ exclude = [
|
|
|
43
43
|
|
|
44
44
|
[tool.commitizen]
|
|
45
45
|
name = "cz_conventional_commits"
|
|
46
|
-
version = "0.2.
|
|
46
|
+
version = "0.2.3"
|
|
47
47
|
tag_format = "v$version"
|
|
48
48
|
version_files = [
|
|
49
49
|
"pyproject.toml:version",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/tmux_cli_controller.py
RENAMED
|
File without changes
|
{claude_code_tools-0.2.1 → claude_code_tools-0.2.3}/claude_code_tools/tmux_remote_controller.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|