agent-shell-py 0.3.1__tar.gz → 0.4.0__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.
Files changed (164) hide show
  1. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/AGENTS.md +44 -6
  2. agent_shell_py-0.4.0/PKG-INFO +120 -0
  3. agent_shell_py-0.4.0/README.md +111 -0
  4. agent_shell_py-0.4.0/docs/assets/agentshell-banner.png +0 -0
  5. agent_shell_py-0.4.0/docs/assets/agentshell-banner.svg +1 -0
  6. agent_shell_py-0.4.0/docs/development/package_management.md +24 -0
  7. agent_shell_py-0.4.0/docs/examples.md +516 -0
  8. agent_shell_py-0.4.0/examples/interactive_demo.py +129 -0
  9. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/skills/invoking-cli-agents/SKILL.md +27 -5
  10. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/skills/invoking-cli-agents/api-reference.md +61 -8
  11. agent_shell_py-0.4.0/src/agent_shell/__init__.py +33 -0
  12. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/_version.py +2 -2
  13. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/agent_adapter_protocol.py +16 -1
  14. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/claude_code_adapter.py +66 -1
  15. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/codex_adapter.py +52 -1
  16. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/copilot_cli_adapter.py +66 -1
  17. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/cursor_adapter.py +59 -1
  18. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/grok_adapter.py +76 -1
  19. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/health.py +2 -0
  20. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/opencode_adapter.py +79 -1
  21. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/pi_adapter.py +192 -1
  22. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/execution.py +56 -13
  23. agent_shell_py-0.4.0/src/agent_shell/herdr.py +629 -0
  24. agent_shell_py-0.4.0/src/agent_shell/herdr_protocol.py +45 -0
  25. agent_shell_py-0.4.0/src/agent_shell/herdr_worker.py +300 -0
  26. agent_shell_py-0.4.0/src/agent_shell/interactive.py +187 -0
  27. agent_shell_py-0.4.0/src/agent_shell/interactive_event_writer.py +19 -0
  28. agent_shell_py-0.4.0/src/agent_shell/interactive_terminal.py +234 -0
  29. agent_shell_py-0.4.0/src/agent_shell/interactive_worker.py +111 -0
  30. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/models/agent.py +12 -0
  31. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/process_cleanup.py +13 -68
  32. agent_shell_py-0.4.0/src/agent_shell/process_guardian.py +98 -0
  33. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/shell.py +41 -1
  34. agent_shell_py-0.4.0/src/agent_shell/terminal_protocol.py +42 -0
  35. agent_shell_py-0.4.0/src/agent_shell/terminal_window.py +710 -0
  36. agent_shell_py-0.4.0/src/agent_shell/terminal_worker.py +261 -0
  37. agent_shell_py-0.4.0/src/agent_shell/tmux.py +601 -0
  38. agent_shell_py-0.4.0/src/agent_shell/tmux_bridge.py +232 -0
  39. agent_shell_py-0.4.0/src/agent_shell/tmux_ownership.py +39 -0
  40. agent_shell_py-0.4.0/src/agent_shell/tmux_protocol.py +44 -0
  41. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_codex_e2e.py +9 -2
  42. agent_shell_py-0.4.0/tests/e2e/test_execution_host_e2e.py +293 -0
  43. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_health_check_e2e.py +9 -3
  44. agent_shell_py-0.4.0/tests/e2e/test_interactive_harness_e2e.py +136 -0
  45. agent_shell_py-0.4.0/tests/e2e/test_pi_packages_e2e.py +114 -0
  46. agent_shell_py-0.4.0/tests/e2e/test_terminal_window_execution_host_e2e.py +194 -0
  47. agent_shell_py-0.4.0/tests/e2e/test_tmux_execution_host_e2e.py +238 -0
  48. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_execution_host.py +262 -5
  49. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_health_check_integration.py +18 -0
  50. agent_shell_py-0.4.0/tests/integration/test_herdr_execution_host.py +1022 -0
  51. agent_shell_py-0.4.0/tests/integration/test_interactive_agents.py +549 -0
  52. agent_shell_py-0.4.0/tests/integration/test_interactive_terminal.py +748 -0
  53. agent_shell_py-0.4.0/tests/integration/test_packages_unsupported.py +20 -0
  54. agent_shell_py-0.4.0/tests/integration/test_pi_packages.py +337 -0
  55. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_process_lifecycle.py +78 -8
  56. agent_shell_py-0.4.0/tests/integration/test_terminal_window_execution_host.py +877 -0
  57. agent_shell_py-0.4.0/tests/integration/test_tmux_execution_host.py +734 -0
  58. agent_shell_py-0.4.0/tests/unit/test_package_spec.py +10 -0
  59. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_process_cleanup.py +1 -1
  60. agent_shell_py-0.4.0/tests/unit/test_public_exports.py +16 -0
  61. agent_shell_py-0.4.0/tests/unit/test_terminal_window_execution_host.py +83 -0
  62. agent_shell_py-0.3.1/PKG-INFO +0 -422
  63. agent_shell_py-0.3.1/README.md +0 -413
  64. agent_shell_py-0.3.1/docs/assets/skill_banner.png +0 -0
  65. agent_shell_py-0.3.1/tests/e2e/test_execution_host_e2e.py +0 -46
  66. agent_shell_py-0.3.1/tests/unit/__init__.py +0 -0
  67. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/.github/workflows/build.yml +0 -0
  68. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/.github/workflows/ci.yml +0 -0
  69. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/.github/workflows/publish.yml +0 -0
  70. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/.gitignore +0 -0
  71. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/.python-version +0 -0
  72. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/LICENSE +0 -0
  73. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/docs/development/agent_parameter_comparison.md +0 -0
  74. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/docs/development/disabled_tools.md +0 -0
  75. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/docs/development/info.md +0 -0
  76. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/docs/development/total_token_count.md +0 -0
  77. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/pyproject.toml +0 -0
  78. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/skills/delegating-code-review/SKILL.md +0 -0
  79. {agent_shell_py-0.3.1/src/agent_shell → agent_shell_py-0.4.0/src/agent_shell/adapters}/__init__.py +0 -0
  80. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/model_discovery.py +0 -0
  81. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/outcome.py +0 -0
  82. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/process_failure.py +0 -0
  83. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/response.py +0 -0
  84. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/stderr_format.py +0 -0
  85. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/src/agent_shell/adapters/tool_denial.py +0 -0
  86. {agent_shell_py-0.3.1/src/agent_shell/adapters → agent_shell_py-0.4.0/src/agent_shell/models}/__init__.py +0 -0
  87. {agent_shell_py-0.3.1/src/agent_shell/models → agent_shell_py-0.4.0/tests}/__init__.py +0 -0
  88. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/conftest.py +0 -0
  89. {agent_shell_py-0.3.1/tests → agent_shell_py-0.4.0/tests/e2e}/__init__.py +0 -0
  90. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_claude_code_e2e.py +0 -0
  91. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_copilot_cli_e2e.py +0 -0
  92. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_cursor_e2e.py +0 -0
  93. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_grok_e2e.py +0 -0
  94. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_model_discovery_e2e.py +0 -0
  95. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_opencode_e2e.py +0 -0
  96. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/e2e/test_pi_e2e.py +0 -0
  97. {agent_shell_py-0.3.1/tests/e2e → agent_shell_py-0.4.0/tests/integration}/__init__.py +0 -0
  98. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_claude_code_integration.py +0 -0
  99. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_claude_code_mcp_integration.py +0 -0
  100. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_codex_integration.py +0 -0
  101. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_codex_mcp_integration.py +0 -0
  102. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_copilot_cli_integration.py +0 -0
  103. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_copilot_cli_mcp_integration.py +0 -0
  104. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_cursor_integration.py +0 -0
  105. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_cursor_mcp_integration.py +0 -0
  106. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_grok_integration.py +0 -0
  107. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_grok_mcp_integration.py +0 -0
  108. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_model_discovery_integration.py +0 -0
  109. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_opencode_integration.py +0 -0
  110. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_opencode_mcp_integration.py +0 -0
  111. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_pi_integration.py +0 -0
  112. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/integration/test_pi_mcp_integration.py +0 -0
  113. {agent_shell_py-0.3.1/tests/integration → agent_shell_py-0.4.0/tests/unit}/__init__.py +0 -0
  114. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/adapter_matrix.py +0 -0
  115. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/codex_fixtures.py +0 -0
  116. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/copilot_fixtures.py +0 -0
  117. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/cursor_fixtures.py +0 -0
  118. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/fixtures.py +0 -0
  119. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/grok_fixtures.py +0 -0
  120. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/opencode_fixtures.py +0 -0
  121. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/pi_fixtures.py +0 -0
  122. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_adapter_transport.py +0 -0
  123. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_cancel.py +0 -0
  124. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_codex_cancel.py +0 -0
  125. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_codex_execute.py +0 -0
  126. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_codex_parse_event.py +0 -0
  127. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_codex_warnings.py +0 -0
  128. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_copilot_cli_cancel.py +0 -0
  129. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_copilot_cli_execute.py +0 -0
  130. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_copilot_cli_parse_event.py +0 -0
  131. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_copilot_cli_stream.py +0 -0
  132. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_cursor_cancel.py +0 -0
  133. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_cursor_execute.py +0 -0
  134. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_cursor_parse_event.py +0 -0
  135. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_cursor_warnings.py +0 -0
  136. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_execute.py +0 -0
  137. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_execute_outcome.py +0 -0
  138. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_grok_cancel.py +0 -0
  139. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_grok_execute.py +0 -0
  140. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_grok_parse_event.py +0 -0
  141. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_grok_warnings.py +0 -0
  142. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_health_probe.py +0 -0
  143. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_mcp_server_spec.py +0 -0
  144. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_model_discovery.py +0 -0
  145. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_models.py +0 -0
  146. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_opencode_cancel.py +0 -0
  147. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_opencode_execute.py +0 -0
  148. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_opencode_parse_event.py +0 -0
  149. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_opencode_spawn.py +0 -0
  150. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_opencode_stream.py +0 -0
  151. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_parse_event.py +0 -0
  152. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_pi_cancel.py +0 -0
  153. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_pi_execute.py +0 -0
  154. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_pi_parse_event.py +0 -0
  155. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_pi_warnings.py +0 -0
  156. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_process_group_registration.py +0 -0
  157. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_response_aggregation.py +0 -0
  158. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_shell.py +0 -0
  159. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_shell_cancellation.py +0 -0
  160. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_shell_mcp.py +0 -0
  161. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_stderr_format.py +0 -0
  162. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_stream.py +0 -0
  163. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/tests/unit/test_tool_denial.py +0 -0
  164. {agent_shell_py-0.3.1 → agent_shell_py-0.4.0}/uv.lock +0 -0
@@ -17,6 +17,9 @@ classDiagram
17
17
  +add_mcp_server(spec) None
18
18
  +remove_mcp_server(name) None
19
19
  +list_mcp_servers() list~MCPServerSpec~
20
+ +add_package(spec, timeout) None
21
+ +list_packages() list~PackageSpec~
22
+ +remove_package(source, timeout) None
20
23
  }
21
24
 
22
25
  class AgentAdapter {
@@ -29,6 +32,9 @@ classDiagram
29
32
  +add_mcp_server(spec) None
30
33
  +remove_mcp_server(name) None
31
34
  +list_mcp_servers() list~MCPServerSpec~
35
+ +add_package(spec, timeout) None
36
+ +list_packages() list~PackageSpec~
37
+ +remove_package(source, timeout) None
32
38
  }
33
39
 
34
40
  class ClaudeCodeAdapter {
@@ -105,6 +111,21 @@ classDiagram
105
111
  +launch(command, cwd, env, stdin, isolation_policy) NativeRunHandle
106
112
  }
107
113
 
114
+ class HerdrExecutionHost {
115
+ <<experimental>>
116
+ +launch(command, cwd, env, stdin, isolation_policy) RunHandle
117
+ }
118
+
119
+ class TmuxExecutionHost {
120
+ <<experimental>>
121
+ +launch(command, cwd, env, stdin, isolation_policy) RunHandle
122
+ }
123
+
124
+ class TerminalWindowExecutionHost {
125
+ <<experimental>>
126
+ +launch(command, cwd, env, stdin, isolation_policy) RunHandle
127
+ }
128
+
108
129
  class IsolationPolicy {
109
130
  <<Protocol>>
110
131
  +prepare(command, env) PreparedLaunch
@@ -140,6 +161,9 @@ classDiagram
140
161
  AgentShell --> ExecutionHost : selects
141
162
  AgentShell --> IsolationPolicy : selects
142
163
  NativeExecutionHost ..|> ExecutionHost : satisfies
164
+ HerdrExecutionHost ..|> ExecutionHost : satisfies
165
+ TmuxExecutionHost ..|> ExecutionHost : satisfies
166
+ TerminalWindowExecutionHost ..|> ExecutionHost : satisfies
143
167
  NativeExecutionHost --> NativeRunHandle : creates
144
168
  NativeRunHandle ..|> RunHandle : satisfies
145
169
  NoIsolation ..|> IsolationPolicy : satisfies
@@ -157,15 +181,25 @@ classDiagram
157
181
 
158
182
  The adapter pattern uses Python's `Protocol` (structural typing) rather than ABC, so adapters satisfy the contract implicitly without inheritance. Each adapter translates agent-specific CLI flags and NDJSON output into the shared `StreamEvent`/`AgentResponse` models, while the selected `ExecutionHost` owns process creation and returns a per-run `RunHandle`.
159
183
 
184
+ `HerdrExecutionHost`, `TmuxExecutionHost`, and `TerminalWindowExecutionHost` are experimental,
185
+ opt-in APIs. Their constructors, placement options, supported platforms, and lifecycle behaviour
186
+ may change in a later minor release. `NativeExecutionHost` remains the backwards-compatible
187
+ default, and an unavailable experimental host never silently falls back to it.
188
+
160
189
  Execution location and protection are separate axes. Existing callers default to
161
190
  `NativeExecutionHost()` plus `NoIsolation()` when `AGENTSHELL_ISOLATION_POLICY` is unset. The
162
191
  environment accepts `none` or `linux-pid-namespace` as a process-wide construction default;
163
192
  explicit `isolation_policy=` takes precedence, and invalid or empty values raise `ValueError`.
164
193
  `LinuxPidNamespaceIsolation` is a direct signal boundary: a tiny init/reaper is PID 1 and the CLI
165
- is PID 2 or later, so child-namespace processes cannot see or signal AgentShell's ancestors. It
166
- requires Linux, `unshare`, and enabled unprivileged user/PID namespaces; an unavailable request
167
- raises `IsolationUnavailableError` and never falls back. This is not a general sandbox and does
168
- not restrict filesystem, credentials, network, tools, or resources. The host/policy applies to
194
+ is PID 2 or later, so child-namespace processes cannot directly signal AgentShell's ancestors.
195
+ The default `mount_proc=True` also hides those ancestors through a private `/proc` mount.
196
+ Explicit `mount_proc=False` retains the PID boundary and descendant cleanup while inheriting the
197
+ outer `/proc` view, exposing process metadata and potentially confusing tools that use its PIDs.
198
+ It does not create a private mount namespace. The environment value `linux-pid-namespace` remains
199
+ strict; each policy probes its own requested mode. It requires Linux, `unshare`, and enabled
200
+ unprivileged user/PID namespaces; an unavailable request raises `IsolationUnavailableError` and
201
+ never falls back. This is not a general sandbox and does not restrict filesystem, credentials,
202
+ network, tools, or resources. The host/policy applies to
169
203
  `execute()`, `stream()`, and `health_check()`; model discovery and MCP configuration remain local.
170
204
 
171
205
  `output_tokens` is a cost measure — the billed output-token count, which **includes reasoning tokens** (billed at the output rate). Each adapter normalises this so the value is consistent across agents (e.g. OpenCode reports reasoning in a sibling field, so its adapter adds it back).
@@ -236,8 +270,12 @@ entries from `~/.claude.json` directly, avoiding the health checks and human-rea
236
270
  `claude mcp list`. Cursor manages user-scope MCP entries directly in `~/.cursor/mcp.json` because
237
271
  its `mcp` subcommands have no add/remove commands. Grok listing reads user-scope `mcp_servers`
238
272
  entries from `~/.grok/config.toml` directly for the same reason. Pi's MCP add/remove/list methods
239
- raise `NotImplementedError`. Pi manages capability via `pi install` extensions, which needs
240
- investigation before wiring up.
273
+ raise `NotImplementedError`.
274
+
275
+ ## Package Management
276
+
277
+ See [package management](docs/development/package_management.md) for the API, Pi behaviour,
278
+ scope, and validation details.
241
279
 
242
280
  ## Test Philosophy
243
281
 
@@ -0,0 +1,120 @@
1
+ Metadata-Version: 2.5
2
+ Name: agent-shell-py
3
+ Version: 0.4.0
4
+ Summary: A lightweight abstraction for executing CLI coding agents headlessly
5
+ License-Expression: MIT
6
+ License-File: LICENSE
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+
10
+ ![AgentShell — run CLI coding agents from Python](docs/assets/agentshell-banner.png?v=rounded)
11
+
12
+ <h1 align="center">Agent Shell</h1>
13
+ Agent Shell is a light weight abstraction for executing a cli coding agent headlessly
14
+ and returning the output that can be used programatically as a unified contract
15
+
16
+ ## Features
17
+
18
+ - **One unified contract** — the same `execute`, `stream`, `health_check`, and
19
+ `list_models` API across every agent; swap the backend without changing consuming code.
20
+ - **Seven CLI agents** — Claude Code, OpenCode, Copilot CLI, Codex, Pi, Cursor, and Grok
21
+ behind a common adapter protocol.
22
+ - **Execute or stream** — get one `AgentResponse` (raises `AgentExecutionError` on a failed run),
23
+ or async-iterate normalized `StreamEvent`s with optional thinking/reasoning.
24
+ - **Composable execution policy** — preserve native execution by default, or opt into Linux PID
25
+ namespace isolation without changing an agent adapter.
26
+ - **Session resumption** — continue any conversation by passing back its `session_id`.
27
+ - **Normalized cost & tokens** — consistent `cost` and `output_tokens` (reasoning included)
28
+ regardless of how each CLI reports them.
29
+ - **Model discovery** — retrieve the exact account/workspace-aware model strings accepted by
30
+ each CLI, without inference calls, SDK dependencies, or static catalogs.
31
+ - **Health checks** — confirm an agent + model combination actually works before you rely on
32
+ it, read from the event stream rather than unreliable exit codes.
33
+ - **Portable tool control** — one canonical allow/deny vocabulary
34
+ (`bash, edit, read, web_search, web_fetch`) translated to each CLI's own tool names.
35
+ - **Unified MCP management** — register, remove, and list MCP servers across agents through a
36
+ single API.
37
+ - **Package management** — install/register, list, and remove harness packages through a shared
38
+ API, with Pi as the first supported agent.
39
+ - **Async & dependency-free** — pure `asyncio`, zero runtime dependencies, Python 3.12+.
40
+
41
+ ## Installation
42
+
43
+ ```bash
44
+ uv add agent-shell-py
45
+ ```
46
+
47
+ or with pip:
48
+
49
+ ```bash
50
+ pip install agent-shell-py
51
+ ```
52
+
53
+ ## Agent skills
54
+
55
+ The repository includes reusable skills that teach coding agents how to use AgentShell:
56
+
57
+ - `invoking-cli-agents` — invoke, stream, resume, and restrict CLI agents.
58
+ - `delegating-code-review` — delegate an independent code review through AgentShell.
59
+
60
+ Install them interactively with the Vercel Skills CLI:
61
+
62
+ ```bash
63
+ npx skills add ScottRBK/agent-shell
64
+ ```
65
+
66
+ Or install both skills globally for every coding agent supported by AgentShell:
67
+
68
+ ```bash
69
+ npx skills add ScottRBK/agent-shell --global \
70
+ --skill '*' \
71
+ --agent claude-code opencode github-copilot codex pi cursor grok \
72
+ --yes
73
+ ```
74
+
75
+ Install only the core AgentShell skill with:
76
+
77
+ ```bash
78
+ npx skills add ScottRBK/agent-shell --skill invoking-cli-agents
79
+ ```
80
+
81
+ The skills provide agent instructions. Install `agent-shell-py` and the chosen coding-agent CLIs
82
+ separately.
83
+
84
+ ## Examples
85
+
86
+ ### Execute
87
+
88
+ ```python
89
+ from agent_shell.shell import AgentShell
90
+ from agent_shell.models.agent import AgentType
91
+
92
+ shell = AgentShell(agent_type=AgentType.CLAUDE_CODE)
93
+
94
+ response = await shell.execute(
95
+ cwd="/path/to/project",
96
+ prompt="Can you tell me about this project?",
97
+ allowed_tools=["Read", "Glob", "Grep"],
98
+ model="sonnet",
99
+ )
100
+
101
+ print(response.response)
102
+ print(f"Cost: ${response.cost:.4f}")
103
+ print(f"Output tokens: {response.output_tokens}") # billed output, reasoning included
104
+ print(f"Session: {response.session_id}")
105
+
106
+ # Resume the conversation using the session_id
107
+ follow_up = await shell.execute(
108
+ cwd="/path/to/project",
109
+ prompt="Now refactor the auth module based on your findings",
110
+ allowed_tools=["Read", "Edit", "Bash"],
111
+ model="sonnet",
112
+ session_id=response.session_id,
113
+ )
114
+ ```
115
+
116
+ > `output_tokens` is a cost measure: the billed output-token count, which **includes reasoning
117
+ > tokens** (they are billed at the output rate). It is reported consistently across all adapters.
118
+
119
+ See [more examples](docs/examples.md) for isolation and execution hosts, failure handling,
120
+ streaming, model discovery, health checks, tool restrictions, MCP servers, packages, and logging.
@@ -0,0 +1,111 @@
1
+ ![AgentShell — run CLI coding agents from Python](docs/assets/agentshell-banner.png?v=rounded)
2
+
3
+ <h1 align="center">Agent Shell</h1>
4
+ Agent Shell is a light weight abstraction for executing a cli coding agent headlessly
5
+ and returning the output that can be used programatically as a unified contract
6
+
7
+ ## Features
8
+
9
+ - **One unified contract** — the same `execute`, `stream`, `health_check`, and
10
+ `list_models` API across every agent; swap the backend without changing consuming code.
11
+ - **Seven CLI agents** — Claude Code, OpenCode, Copilot CLI, Codex, Pi, Cursor, and Grok
12
+ behind a common adapter protocol.
13
+ - **Execute or stream** — get one `AgentResponse` (raises `AgentExecutionError` on a failed run),
14
+ or async-iterate normalized `StreamEvent`s with optional thinking/reasoning.
15
+ - **Composable execution policy** — preserve native execution by default, or opt into Linux PID
16
+ namespace isolation without changing an agent adapter.
17
+ - **Session resumption** — continue any conversation by passing back its `session_id`.
18
+ - **Normalized cost & tokens** — consistent `cost` and `output_tokens` (reasoning included)
19
+ regardless of how each CLI reports them.
20
+ - **Model discovery** — retrieve the exact account/workspace-aware model strings accepted by
21
+ each CLI, without inference calls, SDK dependencies, or static catalogs.
22
+ - **Health checks** — confirm an agent + model combination actually works before you rely on
23
+ it, read from the event stream rather than unreliable exit codes.
24
+ - **Portable tool control** — one canonical allow/deny vocabulary
25
+ (`bash, edit, read, web_search, web_fetch`) translated to each CLI's own tool names.
26
+ - **Unified MCP management** — register, remove, and list MCP servers across agents through a
27
+ single API.
28
+ - **Package management** — install/register, list, and remove harness packages through a shared
29
+ API, with Pi as the first supported agent.
30
+ - **Async & dependency-free** — pure `asyncio`, zero runtime dependencies, Python 3.12+.
31
+
32
+ ## Installation
33
+
34
+ ```bash
35
+ uv add agent-shell-py
36
+ ```
37
+
38
+ or with pip:
39
+
40
+ ```bash
41
+ pip install agent-shell-py
42
+ ```
43
+
44
+ ## Agent skills
45
+
46
+ The repository includes reusable skills that teach coding agents how to use AgentShell:
47
+
48
+ - `invoking-cli-agents` — invoke, stream, resume, and restrict CLI agents.
49
+ - `delegating-code-review` — delegate an independent code review through AgentShell.
50
+
51
+ Install them interactively with the Vercel Skills CLI:
52
+
53
+ ```bash
54
+ npx skills add ScottRBK/agent-shell
55
+ ```
56
+
57
+ Or install both skills globally for every coding agent supported by AgentShell:
58
+
59
+ ```bash
60
+ npx skills add ScottRBK/agent-shell --global \
61
+ --skill '*' \
62
+ --agent claude-code opencode github-copilot codex pi cursor grok \
63
+ --yes
64
+ ```
65
+
66
+ Install only the core AgentShell skill with:
67
+
68
+ ```bash
69
+ npx skills add ScottRBK/agent-shell --skill invoking-cli-agents
70
+ ```
71
+
72
+ The skills provide agent instructions. Install `agent-shell-py` and the chosen coding-agent CLIs
73
+ separately.
74
+
75
+ ## Examples
76
+
77
+ ### Execute
78
+
79
+ ```python
80
+ from agent_shell.shell import AgentShell
81
+ from agent_shell.models.agent import AgentType
82
+
83
+ shell = AgentShell(agent_type=AgentType.CLAUDE_CODE)
84
+
85
+ response = await shell.execute(
86
+ cwd="/path/to/project",
87
+ prompt="Can you tell me about this project?",
88
+ allowed_tools=["Read", "Glob", "Grep"],
89
+ model="sonnet",
90
+ )
91
+
92
+ print(response.response)
93
+ print(f"Cost: ${response.cost:.4f}")
94
+ print(f"Output tokens: {response.output_tokens}") # billed output, reasoning included
95
+ print(f"Session: {response.session_id}")
96
+
97
+ # Resume the conversation using the session_id
98
+ follow_up = await shell.execute(
99
+ cwd="/path/to/project",
100
+ prompt="Now refactor the auth module based on your findings",
101
+ allowed_tools=["Read", "Edit", "Bash"],
102
+ model="sonnet",
103
+ session_id=response.session_id,
104
+ )
105
+ ```
106
+
107
+ > `output_tokens` is a cost measure: the billed output-token count, which **includes reasoning
108
+ > tokens** (they are billed at the output rate). It is reported consistently across all adapters.
109
+
110
+ See [more examples](docs/examples.md) for isolation and execution hosts, failure handling,
111
+ streaming, model discovery, health checks, tool restrictions, MCP servers, packages, and logging.