claude-code-tools 0.1.17__tar.gz → 0.1.18__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.1.17 → claude_code_tools-0.1.18}/PKG-INFO +19 -13
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/README.md +18 -12
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/__init__.py +1 -1
- claude_code_tools-0.1.18/claude_code_tools/tmux_remote_controller.py +229 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/pyproject.toml +2 -2
- claude_code_tools-0.1.17/claude_code_tools/tmux_remote_controller.py +0 -69
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/.gitignore +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/LICENSE +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/dotenv_vault.py +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/env_safe.py +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/find_claude_session.py +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/tmux_cli_controller.py +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/docs/claude-code-chutes.md +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/docs/claude-code-tmux-tutorials.md +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/docs/dot-zshrc.md +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/docs/find-claude-session.md +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/docs/reddit-post.md +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/docs/tmux-cli-instructions.md +0 -0
- {claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/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.1.
|
|
3
|
+
Version: 0.1.18
|
|
4
4
|
Summary: Collection of tools for working with Claude Code
|
|
5
5
|
License-File: LICENSE
|
|
6
6
|
Requires-Python: >=3.11
|
|
@@ -213,7 +213,7 @@ env-safe --help # See all options
|
|
|
213
213
|
|
|
214
214
|
### Why env-safe?
|
|
215
215
|
|
|
216
|
-
|
|
216
|
+
Claude Code is completely blocked from directly accessing .env files - no reading, writing, or editing allowed. This prevents both accidental exposure of API keys and unintended modifications. The `env-safe` command provides the only approved way for Claude Code to inspect environment configuration safely, while any modifications must be done manually outside of Claude Code.
|
|
217
217
|
|
|
218
218
|
## 🛡️ Claude Code Safety Hooks
|
|
219
219
|
|
|
@@ -226,8 +226,8 @@ Code's behavior and prevent dangerous operations.
|
|
|
226
226
|
pattern
|
|
227
227
|
- **Git Safety** - Prevents dangerous `git add -A`, unsafe checkouts, and
|
|
228
228
|
accidental data loss
|
|
229
|
-
- **Environment Security** - Blocks
|
|
230
|
-
command
|
|
229
|
+
- **Environment Security** - Blocks all .env file operations (read/write/edit),
|
|
230
|
+
suggests `env-safe` command for safe inspection
|
|
231
231
|
- **Context Management** - Blocks reading files >500 lines to prevent context
|
|
232
232
|
bloat
|
|
233
233
|
- **Command Enhancement** - Enforces ripgrep (`rg`) over grep for better
|
|
@@ -235,20 +235,26 @@ Code's behavior and prevent dangerous operations.
|
|
|
235
235
|
|
|
236
236
|
### Quick Setup
|
|
237
237
|
|
|
238
|
-
1. Copy the
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
238
|
+
1. Copy the hooks configuration from `hooks/settings.sample.json`
|
|
239
|
+
|
|
240
|
+
2. Add the hooks to your global Claude settings at `~/.claude/settings.json`:
|
|
241
|
+
- If the file doesn't exist, create it
|
|
242
|
+
- Copy the "hooks" section from settings.sample.json
|
|
243
|
+
- Replace `/path/to/claude-code-tools` with your actual path to this repository
|
|
244
|
+
|
|
245
|
+
Example ~/.claude/settings.json:
|
|
246
|
+
```json
|
|
247
|
+
{
|
|
248
|
+
"hooks": {
|
|
249
|
+
// ... hooks configuration from settings.sample.json ...
|
|
250
|
+
}
|
|
251
|
+
}
|
|
247
252
|
```
|
|
248
253
|
|
|
249
254
|
### Available Hooks
|
|
250
255
|
|
|
251
256
|
- `bash_hook.py` - Comprehensive bash command safety checks
|
|
257
|
+
- `env_file_protection_hook.py` - Blocks all .env file operations
|
|
252
258
|
- `file_size_conditional_hook.py` - Prevents reading huge files
|
|
253
259
|
- `grep_block_hook.py` - Enforces ripgrep usage
|
|
254
260
|
- `notification_hook.sh` - Sends ntfy.sh notifications
|
|
@@ -200,7 +200,7 @@ env-safe --help # See all options
|
|
|
200
200
|
|
|
201
201
|
### Why env-safe?
|
|
202
202
|
|
|
203
|
-
|
|
203
|
+
Claude Code is completely blocked from directly accessing .env files - no reading, writing, or editing allowed. This prevents both accidental exposure of API keys and unintended modifications. The `env-safe` command provides the only approved way for Claude Code to inspect environment configuration safely, while any modifications must be done manually outside of Claude Code.
|
|
204
204
|
|
|
205
205
|
## 🛡️ Claude Code Safety Hooks
|
|
206
206
|
|
|
@@ -213,8 +213,8 @@ Code's behavior and prevent dangerous operations.
|
|
|
213
213
|
pattern
|
|
214
214
|
- **Git Safety** - Prevents dangerous `git add -A`, unsafe checkouts, and
|
|
215
215
|
accidental data loss
|
|
216
|
-
- **Environment Security** - Blocks
|
|
217
|
-
command
|
|
216
|
+
- **Environment Security** - Blocks all .env file operations (read/write/edit),
|
|
217
|
+
suggests `env-safe` command for safe inspection
|
|
218
218
|
- **Context Management** - Blocks reading files >500 lines to prevent context
|
|
219
219
|
bloat
|
|
220
220
|
- **Command Enhancement** - Enforces ripgrep (`rg`) over grep for better
|
|
@@ -222,20 +222,26 @@ Code's behavior and prevent dangerous operations.
|
|
|
222
222
|
|
|
223
223
|
### Quick Setup
|
|
224
224
|
|
|
225
|
-
1. Copy the
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
225
|
+
1. Copy the hooks configuration from `hooks/settings.sample.json`
|
|
226
|
+
|
|
227
|
+
2. Add the hooks to your global Claude settings at `~/.claude/settings.json`:
|
|
228
|
+
- If the file doesn't exist, create it
|
|
229
|
+
- Copy the "hooks" section from settings.sample.json
|
|
230
|
+
- Replace `/path/to/claude-code-tools` with your actual path to this repository
|
|
231
|
+
|
|
232
|
+
Example ~/.claude/settings.json:
|
|
233
|
+
```json
|
|
234
|
+
{
|
|
235
|
+
"hooks": {
|
|
236
|
+
// ... hooks configuration from settings.sample.json ...
|
|
237
|
+
}
|
|
238
|
+
}
|
|
234
239
|
```
|
|
235
240
|
|
|
236
241
|
### Available Hooks
|
|
237
242
|
|
|
238
243
|
- `bash_hook.py` - Comprehensive bash command safety checks
|
|
244
|
+
- `env_file_protection_hook.py` - Blocks all .env file operations
|
|
239
245
|
- `file_size_conditional_hook.py` - Prevents reading huge files
|
|
240
246
|
- `grep_block_hook.py` - Enforces ripgrep usage
|
|
241
247
|
- `notification_hook.sh` - Sends ntfy.sh notifications
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Remote Tmux Controller
|
|
4
|
+
|
|
5
|
+
Enables tmux-cli to work when run outside of tmux by:
|
|
6
|
+
- Auto-creating a detached tmux session on first use
|
|
7
|
+
- Managing commands in separate tmux windows (not panes)
|
|
8
|
+
- Providing an API compatible with the local (pane) controller
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
import subprocess
|
|
12
|
+
import time
|
|
13
|
+
import hashlib
|
|
14
|
+
from typing import Optional, List, Dict, Tuple, Union
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class RemoteTmuxController:
|
|
18
|
+
"""Remote controller that manages a dedicated tmux session and windows."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, session_name: str = "remote-cli-session"):
|
|
21
|
+
"""Initialize with session name and ensure the session exists."""
|
|
22
|
+
self.session_name = session_name
|
|
23
|
+
self.target_window: Optional[str] = None # e.g., "session:0" (active pane in that window)
|
|
24
|
+
print(f"Note: tmux-cli is running outside tmux. Managing windows in session '{session_name}'.")
|
|
25
|
+
print("For better integration, consider running from inside a tmux session.")
|
|
26
|
+
print("Use 'tmux-cli attach' to view the remote session.")
|
|
27
|
+
self._ensure_session()
|
|
28
|
+
|
|
29
|
+
# ----------------------------
|
|
30
|
+
# Internal utilities
|
|
31
|
+
# ----------------------------
|
|
32
|
+
def _run_tmux(self, args: List[str]) -> Tuple[str, int]:
|
|
33
|
+
result = subprocess.run(
|
|
34
|
+
['tmux'] + args,
|
|
35
|
+
capture_output=True,
|
|
36
|
+
text=True
|
|
37
|
+
)
|
|
38
|
+
return result.stdout.strip(), result.returncode
|
|
39
|
+
|
|
40
|
+
def _ensure_session(self) -> None:
|
|
41
|
+
"""Create the session if it doesn't exist (detached)."""
|
|
42
|
+
_, code = self._run_tmux(['has-session', '-t', self.session_name])
|
|
43
|
+
if code != 0:
|
|
44
|
+
# Create a detached session using user's default shell
|
|
45
|
+
# Return the session name just to force creation
|
|
46
|
+
self._run_tmux([
|
|
47
|
+
'new-session', '-d', '-s', self.session_name, '-P', '-F', '#{session_name}'
|
|
48
|
+
])
|
|
49
|
+
# Remember first window as default target
|
|
50
|
+
self.target_window = f"{self.session_name}:0"
|
|
51
|
+
else:
|
|
52
|
+
# If already exists and we don't have a target, set to active window
|
|
53
|
+
if not self.target_window:
|
|
54
|
+
win, code2 = self._run_tmux(['display-message', '-p', '-t', self.session_name, '#{session_name}:#{window_index}'])
|
|
55
|
+
if code2 == 0 and win:
|
|
56
|
+
self.target_window = win
|
|
57
|
+
|
|
58
|
+
def _window_target(self, pane: Optional[str]) -> str:
|
|
59
|
+
"""Resolve user-provided pane/window hint to a tmux target.
|
|
60
|
+
Accepts:
|
|
61
|
+
- None -> use last target window if set else active window in session
|
|
62
|
+
- digits (e.g., "1") -> session:index
|
|
63
|
+
- full tmux target (e.g., "name:1" or "name:1.0" or "%12") -> pass-through
|
|
64
|
+
"""
|
|
65
|
+
self._ensure_session()
|
|
66
|
+
if pane is None:
|
|
67
|
+
if self.target_window:
|
|
68
|
+
return self.target_window
|
|
69
|
+
# Fallback to active window in session
|
|
70
|
+
win, code = self._run_tmux(['display-message', '-p', '-t', self.session_name, '#{session_name}:#{window_index}'])
|
|
71
|
+
if code == 0 and win:
|
|
72
|
+
self.target_window = win
|
|
73
|
+
return win
|
|
74
|
+
# Final fallback: session:0
|
|
75
|
+
return f"{self.session_name}:0"
|
|
76
|
+
# If user supplied a simple index
|
|
77
|
+
if isinstance(pane, str) and pane.isdigit():
|
|
78
|
+
return f"{self.session_name}:{pane}"
|
|
79
|
+
# Otherwise assume user provided a pane/window target or pane id
|
|
80
|
+
return pane
|
|
81
|
+
|
|
82
|
+
def _active_pane_in_window(self, window_target: str) -> str:
|
|
83
|
+
"""Return a target that tmux can use to address the active pane of a window.
|
|
84
|
+
For tmux commands that accept pane targets, a window target resolves to its
|
|
85
|
+
active pane, so we can pass the window target directly.
|
|
86
|
+
Still, normalize to make intent clear.
|
|
87
|
+
"""
|
|
88
|
+
return window_target
|
|
89
|
+
|
|
90
|
+
def list_panes(self) -> List[Dict[str, str]]:
|
|
91
|
+
"""In remote mode, list windows in the managed session.
|
|
92
|
+
Returns a list shaped similarly to local list_panes, with keys:
|
|
93
|
+
id (window target), index, title (window name), active (bool), size (N/A)
|
|
94
|
+
"""
|
|
95
|
+
self._ensure_session()
|
|
96
|
+
out, code = self._run_tmux([
|
|
97
|
+
'list-windows', '-t', self.session_name,
|
|
98
|
+
'-F', '#{window_index}|#{window_name}|#{window_active}|#{window_width}x#{window_height}'
|
|
99
|
+
])
|
|
100
|
+
if code != 0 or not out:
|
|
101
|
+
return []
|
|
102
|
+
windows: List[Dict[str, str]] = []
|
|
103
|
+
for line in out.split('\n'):
|
|
104
|
+
if not line:
|
|
105
|
+
continue
|
|
106
|
+
idx, name, active, size = line.split('|')
|
|
107
|
+
windows.append({
|
|
108
|
+
'id': f"{self.session_name}:{idx}",
|
|
109
|
+
'index': idx,
|
|
110
|
+
'title': name,
|
|
111
|
+
'active': active == '1',
|
|
112
|
+
'size': size
|
|
113
|
+
})
|
|
114
|
+
return windows
|
|
115
|
+
|
|
116
|
+
def launch_cli(self, command: str, name: Optional[str] = None) -> Optional[str]:
|
|
117
|
+
"""Launch a command in a new window within the managed session.
|
|
118
|
+
Returns the window target (e.g., "session:1").
|
|
119
|
+
"""
|
|
120
|
+
self._ensure_session()
|
|
121
|
+
args = ['new-window', '-t', self.session_name, '-P', '-F', '#{session_name}:#{window_index}']
|
|
122
|
+
if name:
|
|
123
|
+
args.extend(['-n', name])
|
|
124
|
+
if command:
|
|
125
|
+
args.append(command)
|
|
126
|
+
out, code = self._run_tmux(args)
|
|
127
|
+
if code == 0 and out:
|
|
128
|
+
self.target_window = out
|
|
129
|
+
return out
|
|
130
|
+
return None
|
|
131
|
+
|
|
132
|
+
def send_keys(self, text: str, pane_id: Optional[str] = None, enter: bool = True,
|
|
133
|
+
delay_enter: Union[bool, float] = True):
|
|
134
|
+
"""Send keys to the active pane of a given window (or last target)."""
|
|
135
|
+
if not text:
|
|
136
|
+
return
|
|
137
|
+
target = self._active_pane_in_window(self._window_target(pane_id))
|
|
138
|
+
if enter and delay_enter:
|
|
139
|
+
# First send text (no Enter)
|
|
140
|
+
self._run_tmux(['send-keys', '-t', target, text])
|
|
141
|
+
# Delay
|
|
142
|
+
delay = 1.0 if isinstance(delay_enter, bool) else float(delay_enter)
|
|
143
|
+
time.sleep(delay)
|
|
144
|
+
# Then Enter
|
|
145
|
+
self._run_tmux(['send-keys', '-t', target, 'Enter'])
|
|
146
|
+
else:
|
|
147
|
+
args = ['send-keys', '-t', target, text]
|
|
148
|
+
if enter:
|
|
149
|
+
args.append('Enter')
|
|
150
|
+
self._run_tmux(args)
|
|
151
|
+
|
|
152
|
+
def capture_pane(self, pane_id: Optional[str] = None, lines: Optional[int] = None) -> str:
|
|
153
|
+
"""Capture output from the active pane of a window."""
|
|
154
|
+
target = self._active_pane_in_window(self._window_target(pane_id))
|
|
155
|
+
args = ['capture-pane', '-t', target, '-p']
|
|
156
|
+
if lines:
|
|
157
|
+
args.extend(['-S', f'-{lines}'])
|
|
158
|
+
out, _ = self._run_tmux(args)
|
|
159
|
+
return out
|
|
160
|
+
|
|
161
|
+
def wait_for_idle(self, pane_id: Optional[str] = None, idle_time: float = 2.0,
|
|
162
|
+
check_interval: float = 0.5, timeout: Optional[int] = None) -> bool:
|
|
163
|
+
"""Wait until captured output is unchanged for idle_time seconds."""
|
|
164
|
+
target = self._active_pane_in_window(self._window_target(pane_id))
|
|
165
|
+
start_time = time.time()
|
|
166
|
+
last_change = time.time()
|
|
167
|
+
last_hash = ""
|
|
168
|
+
while True:
|
|
169
|
+
if timeout is not None and (time.time() - start_time) > timeout:
|
|
170
|
+
return False
|
|
171
|
+
content, _ = self._run_tmux(['capture-pane', '-t', target, '-p'])
|
|
172
|
+
h = hashlib.md5(content.encode()).hexdigest()
|
|
173
|
+
if h != last_hash:
|
|
174
|
+
last_hash = h
|
|
175
|
+
last_change = time.time()
|
|
176
|
+
else:
|
|
177
|
+
if (time.time() - last_change) >= idle_time:
|
|
178
|
+
return True
|
|
179
|
+
time.sleep(check_interval)
|
|
180
|
+
|
|
181
|
+
def send_interrupt(self, pane_id: Optional[str] = None):
|
|
182
|
+
target = self._active_pane_in_window(self._window_target(pane_id))
|
|
183
|
+
self._run_tmux(['send-keys', '-t', target, 'C-c'])
|
|
184
|
+
|
|
185
|
+
def send_escape(self, pane_id: Optional[str] = None):
|
|
186
|
+
target = self._active_pane_in_window(self._window_target(pane_id))
|
|
187
|
+
self._run_tmux(['send-keys', '-t', target, 'Escape'])
|
|
188
|
+
|
|
189
|
+
def kill_window(self, window_id: Optional[str] = None):
|
|
190
|
+
target = self._window_target(window_id)
|
|
191
|
+
# Ensure the target refers to a window (not a %pane id)
|
|
192
|
+
# If user passed a pane id like %12, tmux can still resolve to its window
|
|
193
|
+
self._run_tmux(['kill-window', '-t', target])
|
|
194
|
+
if self.target_window == target:
|
|
195
|
+
self.target_window = None
|
|
196
|
+
|
|
197
|
+
def attach_session(self):
|
|
198
|
+
self._ensure_session()
|
|
199
|
+
# Attach will replace the current terminal view until the user detaches
|
|
200
|
+
subprocess.run(['tmux', 'attach-session', '-t', self.session_name])
|
|
201
|
+
|
|
202
|
+
def cleanup_session(self):
|
|
203
|
+
self._run_tmux(['kill-session', '-t', self.session_name])
|
|
204
|
+
self.target_window = None
|
|
205
|
+
|
|
206
|
+
def list_windows(self) -> List[Dict[str, str]]:
|
|
207
|
+
"""List all windows in the managed session with basic info."""
|
|
208
|
+
self._ensure_session()
|
|
209
|
+
out, code = self._run_tmux(['list-windows', '-t', self.session_name, '-F', '#{window_index}|#{window_name}|#{window_active}'])
|
|
210
|
+
if code != 0 or not out:
|
|
211
|
+
return []
|
|
212
|
+
windows: List[Dict[str, str]] = []
|
|
213
|
+
for line in out.split('\n'):
|
|
214
|
+
if not line:
|
|
215
|
+
continue
|
|
216
|
+
idx, name, active = line.split('|')
|
|
217
|
+
# Try to get active pane id for each window (best effort)
|
|
218
|
+
pane_out, _ = self._run_tmux(['display-message', '-p', '-t', f'{self.session_name}:{idx}', '#{pane_id}'])
|
|
219
|
+
windows.append({
|
|
220
|
+
'index': idx,
|
|
221
|
+
'name': name,
|
|
222
|
+
'active': active == '1',
|
|
223
|
+
'pane_id': pane_out or ''
|
|
224
|
+
})
|
|
225
|
+
return windows
|
|
226
|
+
|
|
227
|
+
def _resolve_pane_id(self, pane: Optional[str]) -> Optional[str]:
|
|
228
|
+
"""Resolve user-provided identifier to a tmux target string for remote ops."""
|
|
229
|
+
return self._window_target(pane)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "claude-code-tools"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.18"
|
|
4
4
|
description = "Collection of tools for working with Claude Code"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.11"
|
|
@@ -41,7 +41,7 @@ exclude = [
|
|
|
41
41
|
|
|
42
42
|
[tool.commitizen]
|
|
43
43
|
name = "cz_conventional_commits"
|
|
44
|
-
version = "0.1.
|
|
44
|
+
version = "0.1.18"
|
|
45
45
|
tag_format = "v$version"
|
|
46
46
|
version_files = [
|
|
47
47
|
"pyproject.toml:version",
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Remote Tmux Controller - Stub implementation
|
|
4
|
-
This is a minimal stub to prevent import errors when tmux-cli is used outside tmux.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import subprocess
|
|
8
|
-
from typing import Optional, List, Dict
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
class RemoteTmuxController:
|
|
12
|
-
"""Stub implementation of RemoteTmuxController to prevent import errors."""
|
|
13
|
-
|
|
14
|
-
def __init__(self, session_name: str = "remote-cli-session"):
|
|
15
|
-
"""Initialize with session name."""
|
|
16
|
-
self.session_name = session_name
|
|
17
|
-
print(f"Warning: RemoteTmuxController is not fully implemented.")
|
|
18
|
-
print(f"Remote mode functionality is currently unavailable.")
|
|
19
|
-
print(f"Please use tmux-cli from inside a tmux session for full functionality.")
|
|
20
|
-
|
|
21
|
-
def list_panes(self) -> List[Dict[str, str]]:
|
|
22
|
-
"""Return empty list."""
|
|
23
|
-
return []
|
|
24
|
-
|
|
25
|
-
def launch_cli(self, command: str, name: Optional[str] = None) -> Optional[str]:
|
|
26
|
-
"""Not implemented."""
|
|
27
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
28
|
-
|
|
29
|
-
def send_keys(self, text: str, pane_id: Optional[str] = None, enter: bool = True,
|
|
30
|
-
delay_enter: bool = True):
|
|
31
|
-
"""Not implemented."""
|
|
32
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
33
|
-
|
|
34
|
-
def capture_pane(self, pane_id: Optional[str] = None, lines: Optional[int] = None) -> str:
|
|
35
|
-
"""Not implemented."""
|
|
36
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
37
|
-
|
|
38
|
-
def wait_for_idle(self, pane_id: Optional[str] = None, idle_time: float = 2.0,
|
|
39
|
-
check_interval: float = 0.5, timeout: Optional[int] = None) -> bool:
|
|
40
|
-
"""Not implemented."""
|
|
41
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
42
|
-
|
|
43
|
-
def send_interrupt(self, pane_id: Optional[str] = None):
|
|
44
|
-
"""Not implemented."""
|
|
45
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
46
|
-
|
|
47
|
-
def send_escape(self, pane_id: Optional[str] = None):
|
|
48
|
-
"""Not implemented."""
|
|
49
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
50
|
-
|
|
51
|
-
def kill_window(self, window_id: Optional[str] = None):
|
|
52
|
-
"""Not implemented."""
|
|
53
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
54
|
-
|
|
55
|
-
def attach_session(self):
|
|
56
|
-
"""Not implemented."""
|
|
57
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
58
|
-
|
|
59
|
-
def cleanup_session(self):
|
|
60
|
-
"""Not implemented."""
|
|
61
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
62
|
-
|
|
63
|
-
def list_windows(self) -> List[Dict[str, str]]:
|
|
64
|
-
"""Not implemented."""
|
|
65
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
66
|
-
|
|
67
|
-
def _resolve_pane_id(self, pane: Optional[str]) -> Optional[str]:
|
|
68
|
-
"""Not implemented."""
|
|
69
|
-
raise NotImplementedError("Remote mode is not available. Please use tmux-cli from inside tmux.")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/find_claude_session.py
RENAMED
|
File without changes
|
{claude_code_tools-0.1.17 → claude_code_tools-0.1.18}/claude_code_tools/tmux_cli_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
|