powershell-terminal-mcp 0.1.0__py3-none-any.whl

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.
Files changed (48) hide show
  1. config/config.yaml +245 -0
  2. powershell_terminal_mcp-0.1.0.dist-info/METADATA +459 -0
  3. powershell_terminal_mcp-0.1.0.dist-info/RECORD +48 -0
  4. powershell_terminal_mcp-0.1.0.dist-info/WHEEL +5 -0
  5. powershell_terminal_mcp-0.1.0.dist-info/entry_points.txt +2 -0
  6. powershell_terminal_mcp-0.1.0.dist-info/licenses/LICENSE +21 -0
  7. powershell_terminal_mcp-0.1.0.dist-info/top_level.txt +2 -0
  8. src/__init__.py +38 -0
  9. src/__main__.py +28 -0
  10. src/completion_token.py +99 -0
  11. src/config/__init__.py +27 -0
  12. src/config/config_dataclasses.py +225 -0
  13. src/config/config_init.py +33 -0
  14. src/config/config_loader.py +222 -0
  15. src/db.py +175 -0
  16. src/mcp_server.py +298 -0
  17. src/output/__init__.py +24 -0
  18. src/output/output_buffer.py +16 -0
  19. src/output/output_buffer_base.py +106 -0
  20. src/output/output_filter.py +165 -0
  21. src/output/output_filter_commands.py +156 -0
  22. src/output/output_filter_decision.py +113 -0
  23. src/pwsh/__init__.py +7 -0
  24. src/pwsh/output_clean.py +38 -0
  25. src/pwsh/pwsh_io.py +23 -0
  26. src/pwsh/pwsh_launch.py +188 -0
  27. src/pwsh/pwsh_reader.py +47 -0
  28. src/pwsh/pwsh_session.py +200 -0
  29. src/pwsh/session_output.py +109 -0
  30. src/shared_state.py +252 -0
  31. src/static/fragments/head.html +4 -0
  32. src/static/fragments/terminal_container.html +1 -0
  33. src/static/fragments/transfer_panel.html +7 -0
  34. src/static/terminal.css +284 -0
  35. src/static/terminal.js +378 -0
  36. src/static/transfer-panel.js +130 -0
  37. src/static/vendor/xterm-addon-fit.js +2 -0
  38. src/static/vendor/xterm.css +209 -0
  39. src/static/vendor/xterm.js +2 -0
  40. src/utils/__init__.py +24 -0
  41. src/utils/utils.py +22 -0
  42. src/utils/utils_format.py +21 -0
  43. src/utils/utils_output.py +174 -0
  44. src/utils/utils_text.py +61 -0
  45. src/web/__init__.py +11 -0
  46. src/web/web_terminal.py +160 -0
  47. src/web/web_terminal_ui.py +52 -0
  48. src/web/web_terminal_websocket.py +216 -0
config/config.yaml ADDED
@@ -0,0 +1,245 @@
1
+ # Remote Terminal Configuration File
2
+ # Version: 3.0 - Multi-Server Support
3
+ # Note: Server connection details moved to hosts.yaml
4
+
5
+ # Connection management settings (apply to all servers)
6
+ connection:
7
+ keepalive_interval: 30 # seconds
8
+ reconnect_attempts: 3
9
+ connection_timeout: 10
10
+
11
+ # Command Execution Settings
12
+ command_execution:
13
+ # Timeout settings
14
+ default_timeout: 10 # CHANGED: 30 → 10 for better responsiveness
15
+ max_timeout: 3600 # Maximum allowed (1 hour)
16
+
17
+ # Prompt detection timing
18
+ prompt_grace_period: 0.3 # Wait after prompt for trailing output (seconds)
19
+ check_interval: 0.5 # How often to check for completion (seconds)
20
+
21
+ # Command tracking
22
+ max_command_history: 50 # Maximum commands to keep in history
23
+ cleanup_interval: 300 # Clean old commands every N seconds
24
+
25
+ # Warning thresholds
26
+ warn_on_long_timeout: 60 # Warn if timeout exceeds this value
27
+
28
+ # Prompt Detection Configuration
29
+ prompt_detection:
30
+ # Prompt patterns to detect command completion
31
+
32
+
33
+ patterns:
34
+ - '(\(.+\)\s+)?{user}@{host}:.*$\s*' # Optional venv + any path
35
+ - '(\(.+\)\s+)?{user}@{host}:.*#\s*' # Optional venv + root prompt
36
+ - '(\(.+\)\s+)?root@{host}:~#\s*' # Optional venv + root home
37
+ - '(\(.+\)\s+)?root@{host}:.*#\s*' # Optional venv + root any dir
38
+
39
+ # Verification settings
40
+ verification_enabled: true
41
+ verification_delay: 0.3 # Seconds to wait before confirming prompt
42
+
43
+ # Commands that change the prompt
44
+ prompt_changing_commands:
45
+ - command: "sudo su"
46
+ new_pattern: "root@{host}:.*[#$]"
47
+ - command: "sudo -i"
48
+ new_pattern: "root@{host}:.*[#$]"
49
+ - command: "su"
50
+ new_pattern: ".*@.*[#$]"
51
+ - command: "ssh"
52
+ new_pattern: ".*@.*[$#]"
53
+ - command: "docker exec"
54
+ new_pattern: ".*[@#]"
55
+
56
+ # Sudo preauth settings
57
+ sudo:
58
+ # How long sudo preauth is valid (seconds)
59
+ # Default: 300 (5 minutes)
60
+ # Should match or be less than sudoers timestamp_timeout
61
+ preauth_validity_seconds: 300
62
+
63
+ # Background command detection
64
+ background_command_pattern: "&\\s*$"
65
+ warn_on_background: true
66
+
67
+ # Debug logging - set to true to log every poll and every line tested
68
+ # Useful for diagnosing prompt pattern issues
69
+ # WARNING: Very verbose - only enable when troubleshooting
70
+ debug_logging: false
71
+
72
+ # Output Buffer Configuration
73
+ buffer:
74
+ max_lines: 10000
75
+ cleanup_on_full: true
76
+
77
+ # Terminal Display Configuration
78
+ terminal:
79
+ scrollback_lines: 1000
80
+ theme: "dark"
81
+ font_size: 14
82
+ font_family: "Consolas, Monaco, monospace"
83
+ cursor_blink: true
84
+ cursor_style: "block"
85
+
86
+ # Command History Configuration
87
+ history:
88
+ enabled: true
89
+ file: "~/.remote_terminal_history"
90
+ max_commands: 1000
91
+ save_on_exit: true
92
+ load_on_start: true
93
+
94
+ # Keyboard Shortcuts Configuration
95
+ shortcuts:
96
+ copy: "Ctrl+C"
97
+ paste: "Ctrl+V"
98
+ clear: "Ctrl+L"
99
+ search: "Ctrl+F"
100
+ interrupt: "Ctrl+C"
101
+ history_previous: "ArrowUp"
102
+ history_next: "ArrowDown"
103
+ history_search: "Ctrl+R"
104
+
105
+ # Search Configuration
106
+ search:
107
+ case_sensitive: true
108
+ highlight_color: "#ffff00"
109
+ wrap_around: true
110
+
111
+ # Claude AI Integration Configuration
112
+ claude:
113
+ auto_send_errors: true
114
+
115
+ # Output mode settings
116
+ output_modes:
117
+ full_output_threshold: 100
118
+ preview_head_lines: 10
119
+ preview_tail_lines: 10
120
+ installation_summary_lines: 10 # Last N lines for successful installations
121
+ max_error_contexts: 10 # Maximum errors to return with context
122
+
123
+ # Commands that produce large output (use summary mode)
124
+ summary_mode_commands:
125
+ - "apt"
126
+ - "apt-get"
127
+ - "yum"
128
+ - "dnf"
129
+ - "pip install"
130
+ - "npm install"
131
+ - "yarn install"
132
+ - "make"
133
+ - "cargo build"
134
+ - "docker build"
135
+ - "mvn"
136
+ - "gradle"
137
+ - "composer install"
138
+ - "composer update"
139
+
140
+ # Commands where full output is needed
141
+ analysis_commands:
142
+ - "grep"
143
+ - "awk"
144
+ - "sed"
145
+ - "find"
146
+ - "jq"
147
+ - "locate"
148
+
149
+ # Output thresholds by command type
150
+ thresholds:
151
+ system_info: 50
152
+ network_info: 100
153
+ file_listing: 50
154
+ file_viewing: 100
155
+ install: 100
156
+ generic: 50
157
+
158
+ # Truncation settings
159
+ truncation:
160
+ head_lines: 30
161
+ tail_lines: 20
162
+
163
+ # Error patterns to detect
164
+ error_patterns:
165
+ - "ERROR"
166
+ - "FAILED"
167
+ - "FATAL"
168
+ - "Cannot"
169
+ - "Permission denied"
170
+ - "No such file"
171
+ - "command not found"
172
+ - "error:"
173
+ - "Error:"
174
+ - "E:"
175
+ - "failed"
176
+ - "Failed"
177
+ - "fatal"
178
+ - "Fatal"
179
+ - "unable to"
180
+ - "Unable to"
181
+ - "could not"
182
+ - "Could not"
183
+ - "cannot"
184
+ - "Can't"
185
+ - "can't"
186
+ - "Couldn't"
187
+ - "couldn't"
188
+ - "not found"
189
+ - "Not found"
190
+ - "Err:"
191
+ - "Aborting"
192
+ - "aborting"
193
+ - "denied"
194
+ - "Denied"
195
+
196
+ # Web Server Configuration
197
+ server:
198
+ host: "localhost"
199
+ port: 8080 # MCP mode web terminal
200
+ auto_open_browser: true
201
+ reload: false
202
+
203
+ # Standalone mode settings (when running standalone_mcp.py)
204
+ standalone:
205
+ terminal_port: 8082 # Web terminal port (different from MCP to avoid conflicts)
206
+ control_port: 8081 # Control panel port
207
+
208
+
209
+ # Logging Configuration
210
+ logging:
211
+ level: "INFO"
212
+ file: "remote_terminal.log"
213
+ max_size_mb: 10
214
+ backup_count: 3
215
+ format: "%(asctime)s - %(name)s - %(levelname)s - %(message)s"
216
+
217
+ # Database configuration removed - SQLite auto-configured
218
+
219
+ # SLIM MODE - Tool visibility workaround
220
+ # Claude has a known bug/limitation where it can only reliably load ~20 MCP tools.
221
+ # When all 40 tools are published, Claude silently drops roughly half of them
222
+ # and they become completely inaccessible - even manual prompting cannot recover them.
223
+ # As a temporary workaround, slim_mode hides lesser-used tools so only the
224
+ # essential 19 are published, keeping us under the ~20 tool visibility limit.
225
+ #
226
+ # Set to false to publish all 40 tools (expect ~20 to be invisible to AI).
227
+ #
228
+ # PUBLISHED (19 tools):
229
+ # Hosts: list_servers, select_server, get_current_server, set_default_server
230
+ # Commands: execute_command, check_command_status, get_command_output,
231
+ # cancel_command, list_session_commands, list_command_history
232
+ # Info: get_terminal_status
233
+ # SFTP: upload_file, download_file, list_remote_directory,
234
+ # get_remote_file_info, upload_directory, download_directory
235
+ # Batch: execute_script_content, build_script_from_commands
236
+ #
237
+ # HIDDEN (21 tools - still implemented, just not advertised to AI):
238
+ # Hosts: add_server, remove_server, update_server
239
+ # Conversations: start_conversation, resume_conversation, end_conversation,
240
+ # get_conversation_commands, list_conversations, update_command_status
241
+ # Recipes: create_recipe, list_recipes, get_recipe, execute_recipe,
242
+ # delete_recipe, create_recipe_from_commands, update_recipe
243
+ # Batch mgmt: list_batch_scripts, get_batch_script, save_batch_script,
244
+ # execute_script_content_by_id, delete_batch_script
245
+ slim_mode: true
@@ -0,0 +1,459 @@
1
+ Metadata-Version: 2.4
2
+ Name: powershell-terminal-mcp
3
+ Version: 0.1.0
4
+ Summary: Shared AI + user PowerShell session on Windows — execute commands, run scripts, automate your PC
5
+ Author-email: Tim <tim00r@github.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/TiM00R/powershell-terminal-mcp
8
+ Project-URL: Repository, https://github.com/TiM00R/powershell-terminal-mcp
9
+ Keywords: mcp,model-context-protocol,powershell,windows,conpty,terminal,local-terminal,automation,claude,ai
10
+ Classifier: Development Status :: 3 - Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: Intended Audience :: System Administrators
13
+ Classifier: Operating System :: Microsoft :: Windows
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
19
+ Classifier: Topic :: System :: Systems Administration
20
+ Classifier: Topic :: Terminals
21
+ Requires-Python: >=3.10
22
+ Description-Content-Type: text/markdown
23
+ License-File: LICENSE
24
+ Requires-Dist: nicegui>=1.4.0
25
+ Requires-Dist: pywinpty>=2.0.10
26
+ Requires-Dist: pyyaml>=6.0
27
+ Requires-Dist: mcp>=1.0.0
28
+ Requires-Dist: starlette>=0.27.0
29
+ Provides-Extra: dev
30
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
31
+ Requires-Dist: black>=23.0.0; extra == "dev"
32
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
33
+ Dynamic: license-file
34
+
35
+ <!-- mcp-name: powershell-terminal -->
36
+ # PowerShell Terminal
37
+
38
+ **Shared AI + user PowerShell session on Windows — execute commands, run scripts, automate your PC**
39
+
40
+ PowerShell Terminal lets Claude (the AI assistant) run commands in a persistent, interactive PowerShell 7 session on your Windows machine through a real pseudo-terminal (ConPTY). Watch every command stream into your browser in real time while Claude receives smart-filtered output optimized for token efficiency.
41
+
42
+ ---
43
+
44
+ ## 🎯 What Is This?
45
+
46
+ Imagine telling Claude:
47
+
48
+ ```
49
+ "Check what Python version I have and install requests if it's missing"
50
+ "Run my build script and tell me if anything failed"
51
+ "Find all .log files modified today and show me any errors"
52
+ "Save this cleanup script and run it every time I ask"
53
+ ```
54
+
55
+ And Claude does it — executing commands in your real PowerShell session, analyzing output, saving reusable scripts, and taking action on your behalf.
56
+
57
+ **That's PowerShell Terminal.**
58
+
59
+ ---
60
+
61
+ ## ✨ Key Features
62
+
63
+ ### Core Capabilities
64
+
65
+ - **🖥️ Real PowerShell Session** — Persistent `pwsh` (PS7) or PS5.1 session via ConPTY; state carries across commands (working directory, variables, activated venv)
66
+ - **🌐 Shared Human + AI Terminal** — NiceGUI + xterm.js web terminal at `http://localhost:8090`; type your own commands alongside Claude's
67
+ - **🔄 Multi-Terminal Sync** — Open multiple browser tabs, all perfectly synchronized
68
+ - **🪟 No Popup Windows** — Native console executables (`git`, `python`, `ipconfig`, full paths) run inside ConPTY without spawning new windows
69
+ - **✂️ Dual-Stream Output** — You see full output in the browser; Claude receives a token-reduced summary
70
+ - **✅ Reliable Completion Detection** — Exit codes and command completion detected via invisible prompt token in OSC escape sequences — no fragile regex matching
71
+ - **⌨️ Interactive Commands** — Commands that prompt for input (`Read-Host`) work; Claude can send input and interrupt with Ctrl+C
72
+ - **📚 Script Library** — Save and reuse named `.ps1` scripts; full output persisted on script runs
73
+ - **🗄️ Command History** — Commands grouped into conversations and logged to SQLite with selective output persistence
74
+
75
+ ### The Interactive Web Terminal
76
+
77
+ PowerShell Terminal provides a **fully interactive terminal window** in your browser at `http://localhost:8090` — it looks and feels just like a native PowerShell window:
78
+
79
+ **You can:**
80
+ - Type commands directly (just like any terminal)
81
+ - Right-click to Copy/Paste, or use Ctrl+Shift+C / Ctrl+Shift+V
82
+ - Scroll through the full session scrollback
83
+ - Watch every command Claude runs appear in real time
84
+
85
+ **Claude can:**
86
+ - Execute commands that stream into your terminal
87
+ - See results instantly
88
+ - Continue working while you watch
89
+
90
+ **The key advantage:** Complete visibility and control. Every command Claude runs appears in your terminal in real time. You're never in the dark — it's like sitting side-by-side with an assistant who types commands while you watch the screen.
91
+
92
+ **Multi-Terminal Support:** Open multiple browser windows at `http://localhost:8090` — they all stay perfectly synchronized via WebSocket broadcast. Type in one terminal, see it in all terminals instantly.
93
+
94
+ ### The Dual-Stream Architecture
95
+
96
+ ```
97
+ PowerShell Session Output (ConPTY)
98
+ |
99
+ [Raw Output]
100
+ |
101
+ ---------+---------
102
+ | |
103
+ [FULL] [FILTERED]
104
+ | |
105
+ v v
106
+ Web Terminal Claude
107
+ (You see all) (Smart summary)
108
+ ```
109
+
110
+ - **You:** Full output, colors, and scrollback in the browser terminal
111
+ - **Claude:** Token-efficient filtered summary
112
+ - **Both:** Same live PowerShell session, synchronized state
113
+
114
+ ### Native Exe — No Popup Windows
115
+
116
+ A key problem with running an AI-controlled terminal on Windows: native console executables like `python`, `git`, `ipconfig`, or any `.exe` would spawn a separate `conhost.exe` popup window, breaking the in-terminal experience.
117
+
118
+ PowerShell Terminal solves this completely:
119
+
120
+ - A **PostCommandLookupAction hook** intercepts every native CUI executable before it runs
121
+ - A **PE header check** distinguishes console apps (CUI) from GUI apps — GUI apps like `notepad` and `code` open normally without blocking
122
+ - Execution is handled via `System.Diagnostics.Process` with `CreateNoWindow=true` and redirected I/O, so output flows through ConPTY instead of a new window
123
+ - Works for **short names** (`git`, `python`), **full paths** (`D:\tools\ffmpeg.exe`), and **any exe not known in advance**
124
+
125
+ ---
126
+
127
+ ## 🚀 Quick Start
128
+
129
+ ### Requirements
130
+
131
+ - Windows 10 1809+ or Windows 11 (ConPTY required)
132
+ - PowerShell 7 (`pwsh`) recommended; falls back to Windows PowerShell 5.1
133
+ - Python 3.10+
134
+
135
+ ### Option A — Install from PyPI
136
+
137
+ **Step 1: Create a virtual environment**
138
+
139
+ ```powershell
140
+ mkdir D:\powershell_terminal
141
+ cd D:\powershell_terminal
142
+ py -m venv .venv
143
+ .\.venv\Scripts\Activate.ps1
144
+ ```
145
+
146
+ **Step 2: Install the package**
147
+
148
+ ```powershell
149
+ pip install powershell-terminal-mcp
150
+ ```
151
+
152
+ **Step 3: Register with Claude Desktop**
153
+
154
+ ```powershell
155
+ notepad $env:APPDATA\Claude\claude_desktop_config.json
156
+ ```
157
+
158
+ Add:
159
+
160
+ ```json
161
+ {
162
+ "mcpServers": {
163
+ "powershell-terminal": {
164
+ "command": "D:\\powershell_terminal\\.venv\\Scripts\\powershell-terminal-mcp.exe"
165
+ }
166
+ }
167
+ }
168
+ ```
169
+
170
+ ---
171
+
172
+ ### Option B — Install from Source (dev)
173
+
174
+ **Step 1: Clone the repo**
175
+
176
+ ```powershell
177
+ git clone https://github.com/TiM00R/powershell-terminal-mcp D:\powershell_terminal
178
+ cd D:\powershell_terminal
179
+ ```
180
+
181
+ **Step 2: Create the virtual environment and install dependencies**
182
+
183
+ ```powershell
184
+ .\setup_venv.ps1
185
+ ```
186
+
187
+ This creates `.venv`, installs all dependencies (including `pywinpty`), and installs the project in editable mode.
188
+
189
+ **Step 3: Register with Claude Desktop**
190
+
191
+ ```powershell
192
+ notepad $env:APPDATA\Claude\claude_desktop_config.json
193
+ ```
194
+
195
+ Add:
196
+
197
+ ```json
198
+ {
199
+ "mcpServers": {
200
+ "powershell-terminal": {
201
+ "command": "D:\\powershell_terminal\\.venv\\Scripts\\python.exe",
202
+ "args": ["D:\\powershell_terminal\\src\\mcp_server.py"]
203
+ }
204
+ }
205
+ }
206
+ ```
207
+
208
+ ---
209
+
210
+ Fully quit and relaunch Claude Desktop (system tray → Exit), then open a new conversation. On the first tool call the server starts the PowerShell session and opens the web terminal at `http://localhost:8090`.
211
+
212
+ ---
213
+
214
+ ## 💡 Usage Examples
215
+
216
+ ### Running Commands
217
+
218
+ ```
219
+ "What Python version do I have?"
220
+ "Run git status in D:\myproject"
221
+ "List all files modified today in my Downloads folder"
222
+ "Check if port 8080 is in use"
223
+ ```
224
+
225
+ ### Scripts & Automation
226
+
227
+ ```
228
+ "Save this build script and run it"
229
+ "Run my cleanup script"
230
+ "List my saved scripts"
231
+ ```
232
+
233
+ ### Diagnostics & System Info
234
+
235
+ ```
236
+ "Check disk space on all drives"
237
+ "What processes are using the most memory?"
238
+ "Show me the last 20 lines of the application event log"
239
+ "Is the Docker daemon running?"
240
+ ```
241
+
242
+ ### Development Workflows
243
+
244
+ ```
245
+ "Activate the venv and run the tests"
246
+ "Install requests and check if it imports correctly"
247
+ "Run git log --oneline -10 and summarize what changed"
248
+ ```
249
+
250
+ ---
251
+
252
+ ## 🎨 Example Session
253
+
254
+ **You:**
255
+ > Run my test suite and tell me what failed
256
+
257
+ **Claude:**
258
+ > I'll run the tests now...
259
+
260
+ *Web terminal opens automatically at http://localhost:8090*
261
+
262
+ **Web Terminal shows (real-time):**
263
+ ```
264
+ PS D:\myproject> python -m pytest tests/ -v
265
+ ============================= test session starts ==============================
266
+ collected 42 items
267
+
268
+ tests/test_api.py::test_login PASSED [ 2%]
269
+ tests/test_api.py::test_auth_required PASSED [ 4%]
270
+ tests/test_db.py::test_connection FAILED [ 26%]
271
+ ...
272
+ ========================= 3 failed, 39 passed in 8.42s =========================
273
+ ```
274
+
275
+ **Claude receives (filtered summary):**
276
+ ```
277
+ pytest: 42 tests, 3 failed, 39 passed (8.4s)
278
+ Failed: test_connection, test_insert_duplicate, test_rollback
279
+ ```
280
+
281
+ **Claude responds:**
282
+ > 3 tests failed, all in `test_db.py` — looks like a database connection issue. Want me to look at the error details and fix them?
283
+
284
+ ---
285
+
286
+ ## 🏗️ Architecture
287
+
288
+ ### How It Works
289
+
290
+ ```
291
+ Claude <--stdio JSON-RPC--> mcp_server.py
292
+ |
293
+ SharedTerminalState
294
+ / | \
295
+ PwshSession OutputBuffer SmartOutputFilter SQLite (db.py)
296
+ (ConPTY via (full human (AI token- (conversations,
297
+ pywinpty) scrollback) reduced view) commands, scripts)
298
+ |
299
+ NiceGUI + xterm.js web terminal (shared, multi-tab)
300
+ ```
301
+
302
+ - A single `pwsh` process runs inside a ConPTY (`pywinpty`). A background thread reads its output into a circular buffer.
303
+ - The session's prompt is overridden (in the MCP session only) to emit a unique completion token + exit status inside invisible OSC escape sequences. The browser swallows them; the server detects them in the raw stream.
304
+ - An output start-marker (emitted via a PSReadLine Enter handler, also invisible) lets the server separate a command's real output from the terminal's echo of the typed command.
305
+ - Human keystrokes from the browser are passed through raw and are not tracked by the AI's completion detection, so the two streams never collide.
306
+
307
+ ### Project Structure
308
+
309
+ ```
310
+ powershell_terminal/
311
+ ├── config/
312
+ │ └── config.yaml # Web port, filter thresholds, error patterns
313
+ ├── data/
314
+ │ └── commands.db # SQLite: conversations, commands, scripts
315
+ ├── scripts/ # Headless test harnesses
316
+ │ ├── test_pwsh_session.py # Session: completion, exit codes, interactive, Ctrl+C
317
+ │ ├── test_session_output.py # Buffer + dual-stream filter
318
+ │ └── test_mcp_dispatch.py # All MCP tools via direct dispatch
319
+ ├── src/
320
+ │ ├── config/ # Configuration loading
321
+ │ ├── output/ # Output filtering and buffering
322
+ │ ├── pwsh/ # PowerShell session (ConPTY)
323
+ │ │ ├── pwsh_launch.py # Shell spawn, init script, native exe hook
324
+ │ │ ├── pwsh_session.py # Session lifecycle, run_command, send_input
325
+ │ │ ├── session_output.py # Dual-stream wrapper (raw + filtered)
326
+ │ │ └── completion_token.py # Prompt token and OSC escape injection
327
+ │ ├── web/
328
+ │ │ └── web_terminal.py # NiceGUI + xterm.js web terminal
329
+ │ ├── db.py # SQLite database layer
330
+ │ ├── mcp_server.py # MCP server entry point (all tools)
331
+ │ └── shared_state.py # Global session hub
332
+ ├── setup_venv.ps1 # One-command environment setup
333
+ └── run_web.py # Launch web terminal standalone (no Claude)
334
+ ```
335
+
336
+ ### Technology Stack
337
+
338
+ - **Python 3.10+** — Core language
339
+ - **MCP Protocol** — Claude integration (stdio JSON-RPC)
340
+ - **pywinpty** — ConPTY pseudo-terminal on Windows
341
+ - **NiceGUI + WebSockets** — Web terminal with multi-tab sync
342
+ - **SQLite** — Command history and script storage
343
+ - **xterm.js** — Browser terminal renderer
344
+
345
+ ---
346
+
347
+ ## 🔧 MCP Tools Reference
348
+
349
+ ### Terminal / Execution
350
+
351
+ | Tool | Description |
352
+ |------|-------------|
353
+ | `execute_command(command, timeout?)` | Run a command; returns filtered output + exit code. Returns `status: "running"` on timeout. |
354
+ | `get_command_output(command_id, raw?)` | Fetch a prior command's output by id. |
355
+ | `send_input(text)` | Answer a running interactive command, then wait for completion. |
356
+ | `send_interrupt()` | Send Ctrl+C to the running command. |
357
+ | `get_terminal_status()` | Session alive? Web terminal URL. |
358
+ | `restart_session()` | Kill and respawn the PowerShell session (clears all state). |
359
+ | `open_terminal()` | Open (or re-open) the web terminal in the browser. |
360
+
361
+ ### Scripts
362
+
363
+ | Tool | Description |
364
+ |------|-------------|
365
+ | `save_script(name, content)` | Save (or overwrite) a named `.ps1` script. |
366
+ | `list_scripts()` | List all saved scripts. |
367
+ | `run_script(name, timeout?)` | Run a saved script; full output is always persisted. |
368
+
369
+ ### Conversations (History)
370
+
371
+ | Tool | Description |
372
+ |------|-------------|
373
+ | `start_conversation(label?)` | Group subsequent commands; returns `conversation_id`. |
374
+ | `end_conversation(conversation_id?, status?)` | End the active (or specified) conversation. |
375
+ | `list_conversations(limit?)` | List recent conversations. |
376
+ | `get_conversation_commands(conversation_id)` | Commands logged under a conversation. |
377
+
378
+ ---
379
+
380
+ ## 🔧 Configuration
381
+
382
+ `config.yaml` (project root) controls:
383
+ - `server.host` / `server.port` — Web terminal address (default `localhost:8090`)
384
+ - Output filter thresholds and error patterns
385
+ - SQLite database lives at `data\commands.db` in the project root
386
+
387
+ ---
388
+
389
+ ## 🛡️ Security Considerations
390
+
391
+ - Web terminal bound to `localhost` only — not exposed to the network
392
+ - Full command audit trail in SQLite
393
+ - The init script runs in the MCP's own session only — **your `$PROFILE`, normal PowerShell, and prompt are never modified**
394
+ - Claude runs commands in your local user context with your normal permissions
395
+
396
+ ---
397
+
398
+ ## 🐛 Known Issues & Limitations
399
+
400
+ 1. **Windows only** — ConPTY is a Windows API; Linux/Mac not supported
401
+ 2. **Interactive TUI apps not supported** — Commands that take over the terminal (e.g. `vim`, `htop`) will hang; use `-NonInteractive` alternatives
402
+ 3. **Single session** — One shared PowerShell session; no per-command isolation
403
+
404
+ ---
405
+
406
+ ## 🔍 Development
407
+
408
+ Run the headless test harnesses without Claude Desktop:
409
+
410
+ ```powershell
411
+ .\.venv\Scripts\python.exe scripts\test_pwsh_session.py # session: completion, exit codes, interactive, Ctrl+C, restart
412
+ .\.venv\Scripts\python.exe scripts\test_session_output.py # buffer + dual-stream filter
413
+ .\.venv\Scripts\python.exe scripts\test_mcp_dispatch.py # all MCP tools via direct dispatch
414
+ python run_web.py # launch web terminal standalone
415
+ ```
416
+
417
+ ---
418
+
419
+ ## 📜 Version History
420
+
421
+ ### v0.1.0 (July 2026) — Initial public release
422
+
423
+ - ✅ ConPTY-based persistent PowerShell 7 session via `pywinpty`
424
+ - ✅ Shared human + AI terminal: NiceGUI + xterm.js web terminal, multi-tab WebSocket sync
425
+ - ✅ Native exe fix: all CUI executables run inside ConPTY without popup windows (`System.Diagnostics.Process` + `CreateNoWindow=true` + redirected I/O)
426
+ - ✅ PostCommandLookupAction hook covers short names, full paths, and any unknown exe
427
+ - ✅ PE header subsystem check: GUI apps (notepad, code) bypass the hook and open normally
428
+ - ✅ PATHEXT fix: session always gets a correct PATHEXT so bare command names resolve reliably
429
+ - ✅ Dual-stream output: full output in browser, token-reduced view for Claude
430
+ - ✅ Reliable command completion via prompt token in invisible OSC escape sequences
431
+ - ✅ Interactive commands: `Read-Host`, `Ctrl+C`, `send_input`
432
+ - ✅ SQLite history: conversations, commands (selective persistence), saved scripts
433
+ - ✅ Full MCP tool set: execute, send_input, interrupt, restart, scripts, conversations
434
+
435
+ ---
436
+
437
+ ## 🤝 Contributing
438
+
439
+ This is Tim's personal project. If you'd like to contribute:
440
+
441
+ 1. Test on your setup and document any issues found
442
+ 2. Suggest improvements or missing features
443
+ 3. Share useful scripts you create
444
+
445
+ ---
446
+
447
+ ## 📄 License
448
+
449
+ MIT
450
+
451
+ ---
452
+
453
+ **Ready to let Claude run PowerShell for you? Register the MCP server in Claude Desktop and open a new conversation to get started.**
454
+
455
+ ---
456
+
457
+ **Version:** 0.1.0
458
+ **Last Updated:** July 2026
459
+ **Maintainer:** Tim