agentsecure 0.1.4__tar.gz → 0.1.6__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 (115) hide show
  1. {agentsecure-0.1.4/agentsecure.egg-info → agentsecure-0.1.6}/PKG-INFO +27 -6
  2. {agentsecure-0.1.4 → agentsecure-0.1.6}/README.md +26 -5
  3. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/__init__.py +1 -1
  4. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/main.py +40 -6
  5. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/agentsecure_md.py +1 -1
  6. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/gateway/proxy.py +7 -0
  7. {agentsecure-0.1.4 → agentsecure-0.1.6/agentsecure.egg-info}/PKG-INFO +27 -6
  8. {agentsecure-0.1.4 → agentsecure-0.1.6}/setup.cfg +1 -1
  9. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli.py +14 -0
  10. {agentsecure-0.1.4 → agentsecure-0.1.6}/LICENSE +0 -0
  11. {agentsecure-0.1.4 → agentsecure-0.1.6}/NOTICE +0 -0
  12. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/__main__.py +0 -0
  13. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/api/__init__.py +0 -0
  14. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/api/server.py +0 -0
  15. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/api/services.py +0 -0
  16. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/__init__.py +0 -0
  17. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/common.py +0 -0
  18. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/demo.py +0 -0
  19. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/policy.py +0 -0
  20. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/project.py +0 -0
  21. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/proxy.py +0 -0
  22. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/receipts.py +0 -0
  23. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/secrets.py +0 -0
  24. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/settings.py +0 -0
  25. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/client/__init__.py +0 -0
  26. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/client/wrappers.py +0 -0
  27. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cloud.py +0 -0
  28. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/config/__init__.py +0 -0
  29. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/config/default_agentsecure.json +0 -0
  30. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/__init__.py +0 -0
  31. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/capabilities.py +0 -0
  32. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/command_metadata.py +0 -0
  33. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/config.py +0 -0
  34. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/config_profiles.py +0 -0
  35. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/container.py +0 -0
  36. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/key_service.py +0 -0
  37. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/models.py +0 -0
  38. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_mutation.py +0 -0
  39. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_ports.py +0 -0
  40. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_response.py +0 -0
  41. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_validation.py +0 -0
  42. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/product.py +0 -0
  43. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/provider_proxy.py +0 -0
  44. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/time.py +0 -0
  45. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/crypto/__init__.py +0 -0
  46. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/crypto/cipher.py +0 -0
  47. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/crypto/key_provider.py +0 -0
  48. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/__init__.py +0 -0
  49. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/commands.py +0 -0
  50. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/policies.py +0 -0
  51. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/sessions.py +0 -0
  52. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/supervisor.py +0 -0
  53. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/__init__.py +0 -0
  54. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/dotenv_scanner.py +0 -0
  55. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/env_scanner.py +0 -0
  56. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/patterns.py +0 -0
  57. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/scanner.py +0 -0
  58. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/suggestions.py +0 -0
  59. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/gateway/__init__.py +0 -0
  60. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/__init__.py +0 -0
  61. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/command.py +0 -0
  62. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/network.py +0 -0
  63. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/sanitizer.py +0 -0
  64. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/wrappers.py +0 -0
  65. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/__init__.py +0 -0
  66. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/audit.py +0 -0
  67. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/encrypted_secret_store.py +0 -0
  68. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/grant_store.py +0 -0
  69. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/local_secret_store.py +0 -0
  70. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/policy.py +0 -0
  71. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/secret_store_factory.py +0 -0
  72. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/secrets.py +0 -0
  73. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/__init__.py +0 -0
  74. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/audit.py +0 -0
  75. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/grants.py +0 -0
  76. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/key_store.py +0 -0
  77. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/policy.py +0 -0
  78. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/secrets.py +0 -0
  79. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/__init__.py +0 -0
  80. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/apply.py +0 -0
  81. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/diff.py +0 -0
  82. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/materializer.py +0 -0
  83. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/rewriter.py +0 -0
  84. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/strategies.py +0 -0
  85. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/SOURCES.txt +0 -0
  86. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/dependency_links.txt +0 -0
  87. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/entry_points.txt +0 -0
  88. {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/top_level.txt +0 -0
  89. {agentsecure-0.1.4 → agentsecure-0.1.6}/pyproject.toml +0 -0
  90. {agentsecure-0.1.4 → agentsecure-0.1.6}/setup.py +0 -0
  91. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_agentsecure_md.py +0 -0
  92. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_audit.py +0 -0
  93. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli_demo.py +0 -0
  94. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli_policy.py +0 -0
  95. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli_proxy.py +0 -0
  96. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_config_validation.py +0 -0
  97. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_diff.py +0 -0
  98. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_discovery.py +0 -0
  99. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_encrypted_secret_store.py +0 -0
  100. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_env_policy.py +0 -0
  101. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_env_policy_contract.py +0 -0
  102. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_gateway_credentials.py +0 -0
  103. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_guard.py +0 -0
  104. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_guard_network.py +0 -0
  105. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_key_service.py +0 -0
  106. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_policy.py +0 -0
  107. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_policy_mutation.py +0 -0
  108. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_product.py +0 -0
  109. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_provider_proxy.py +0 -0
  110. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_secret_scan.py +0 -0
  111. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_secrets.py +0 -0
  112. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_version.py +0 -0
  113. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_workspace.py +0 -0
  114. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_workspace_apply.py +0 -0
  115. {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_wrappers.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentsecure
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Local-first security runtime for AI coding agents
5
5
  Home-page: https://github.com/ShellFrameAI/agentsecure-community
6
6
  Author: ShellFrame AI
@@ -41,11 +41,22 @@ The community release is intentionally scoped to local CLI, local command guard,
41
41
  ## Install
42
42
 
43
43
  ```bash
44
- python3 -m pip install agentsecure
44
+ python3 -m pip install --upgrade agentsecure
45
+ python3 -m agentsecure demo
46
+ ```
47
+
48
+ `python3 -m agentsecure` works even when `pip` installs the `agentsecure`
49
+ executable into a user script directory that is not on your `PATH`. If you want
50
+ the shorter `agentsecure` command, add Python's user script directory to your
51
+ shell path:
52
+
53
+ ```bash
54
+ export PATH="$(python3 -m site --user-base)/bin:$PATH"
45
55
  agentsecure demo
46
56
  ```
47
57
 
48
- Use a virtual environment if you want to keep it isolated:
58
+ You do not need a virtual environment to run AgentSecure. Use one only if you
59
+ want the install isolated to this project:
49
60
 
50
61
  ```bash
51
62
  python3 -m venv .venv
@@ -55,6 +66,12 @@ python -m pip install agentsecure
55
66
  agentsecure demo
56
67
  ```
57
68
 
69
+ Then run your agent:
70
+
71
+ ```bash
72
+ python3 -m agentsecure run claude
73
+ ```
74
+
58
75
  ## What The Demo Shows
59
76
 
60
77
  The built-in demo creates a temporary local project with fake secrets, applies a small sample policy, simulates a command reading `.env`, and prints what the agent would see:
@@ -217,11 +234,15 @@ agentsecure receipts --proxy
217
234
  Run an agent or command through local command guard:
218
235
 
219
236
  ```bash
220
- agentsecure run --protect-all -- codex
221
- agentsecure run --protect-all -- claude
222
- agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
237
+ python3 -m agentsecure run --protect-all -- codex
238
+ python3 -m agentsecure run --protect-all -- claude
239
+ python3 -m agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
223
240
  ```
224
241
 
242
+ Bare interactive agent launches keep the terminal attached so tools such as
243
+ Claude Code can open normally. Non-interactive commands are still output
244
+ sanitized by AgentSecure.
245
+
225
246
  Use workspace copy mode when you want review-before-apply:
226
247
 
227
248
  ```bash
@@ -15,11 +15,22 @@ The community release is intentionally scoped to local CLI, local command guard,
15
15
  ## Install
16
16
 
17
17
  ```bash
18
- python3 -m pip install agentsecure
18
+ python3 -m pip install --upgrade agentsecure
19
+ python3 -m agentsecure demo
20
+ ```
21
+
22
+ `python3 -m agentsecure` works even when `pip` installs the `agentsecure`
23
+ executable into a user script directory that is not on your `PATH`. If you want
24
+ the shorter `agentsecure` command, add Python's user script directory to your
25
+ shell path:
26
+
27
+ ```bash
28
+ export PATH="$(python3 -m site --user-base)/bin:$PATH"
19
29
  agentsecure demo
20
30
  ```
21
31
 
22
- Use a virtual environment if you want to keep it isolated:
32
+ You do not need a virtual environment to run AgentSecure. Use one only if you
33
+ want the install isolated to this project:
23
34
 
24
35
  ```bash
25
36
  python3 -m venv .venv
@@ -29,6 +40,12 @@ python -m pip install agentsecure
29
40
  agentsecure demo
30
41
  ```
31
42
 
43
+ Then run your agent:
44
+
45
+ ```bash
46
+ python3 -m agentsecure run claude
47
+ ```
48
+
32
49
  ## What The Demo Shows
33
50
 
34
51
  The built-in demo creates a temporary local project with fake secrets, applies a small sample policy, simulates a command reading `.env`, and prints what the agent would see:
@@ -191,11 +208,15 @@ agentsecure receipts --proxy
191
208
  Run an agent or command through local command guard:
192
209
 
193
210
  ```bash
194
- agentsecure run --protect-all -- codex
195
- agentsecure run --protect-all -- claude
196
- agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
211
+ python3 -m agentsecure run --protect-all -- codex
212
+ python3 -m agentsecure run --protect-all -- claude
213
+ python3 -m agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
197
214
  ```
198
215
 
216
+ Bare interactive agent launches keep the terminal attached so tools such as
217
+ Claude Code can open normally. Non-interactive commands are still output
218
+ sanitized by AgentSecure.
219
+
199
220
  Use workspace copy mode when you want review-before-apply:
200
221
 
201
222
  ```bash
@@ -1,3 +1,3 @@
1
1
  """AgentSecure local-first security runtime."""
2
2
 
3
- __version__ = "0.1.4"
3
+ __version__ = "0.1.6"
@@ -85,6 +85,19 @@ from agentsecure.workspace.diff import WorkspaceDiff
85
85
  from agentsecure.workspace.materializer import WorkspaceMaterializer, make_tree_writable
86
86
 
87
87
 
88
+ INTERACTIVE_AGENT_COMMANDS = set(SUPPORTED_AGENTS)
89
+
90
+
91
+ class LocalGatewayHandle:
92
+ def __init__(self, gateway: LocalGateway, thread: threading.Thread) -> None:
93
+ self.gateway = gateway
94
+ self.thread = thread
95
+
96
+ def shutdown(self) -> None:
97
+ self.gateway.shutdown()
98
+ self.thread.join(timeout=2)
99
+
100
+
88
101
  def main(argv: Optional[List[str]] = None) -> int:
89
102
  parser = build_parser()
90
103
  args = parser.parse_args(argv)
@@ -338,7 +351,7 @@ def run_agent(args: argparse.Namespace) -> int:
338
351
 
339
352
  daemon = _running_daemon()
340
353
  daemon_session = None
341
- gateway_thread = None
354
+ gateway_handle = None
342
355
  if daemon:
343
356
  daemon_session = _daemon_create_session(
344
357
  daemon,
@@ -357,9 +370,9 @@ def run_agent(args: argparse.Namespace) -> int:
357
370
  else:
358
371
  gateway_host = container.config.gateway.host
359
372
  gateway_port = _available_gateway_port(gateway_host, container.config.gateway.port)
360
- gateway_thread = _start_local_gateway_thread(container, gateway_host, gateway_port)
361
- if isinstance(gateway_thread, int):
362
- return gateway_thread
373
+ gateway_handle = _start_local_gateway_thread(container, gateway_host, gateway_port)
374
+ if isinstance(gateway_handle, int):
375
+ return gateway_handle
363
376
 
364
377
  env = os.environ.copy()
365
378
  for env_name in container.config.env_policy.rules:
@@ -411,7 +424,13 @@ def run_agent(args: argparse.Namespace) -> int:
411
424
  session_finished = False
412
425
  try:
413
426
  output_sanitizer = SecretOutputSanitizer.from_config_path(args.config)
414
- process = _start_agent_process(argv, env, run_cwd, sanitize_output=True)
427
+ preserve_tty = _should_preserve_interactive_tty(argv)
428
+ if preserve_tty:
429
+ print(
430
+ "AgentSecure interactive terminal mode: command output is not post-processed.",
431
+ flush=True,
432
+ )
433
+ process = _start_agent_process(argv, env, run_cwd, sanitize_output=not preserve_tty)
415
434
  process_group_id = _process_group_id(process)
416
435
  if cloud_session and cloud and cloud.status().get("enrolled"):
417
436
  command_executor = _run_command_executor(
@@ -465,6 +484,8 @@ def run_agent(args: argparse.Namespace) -> int:
465
484
  cloud_stop.set()
466
485
  if cloud_thread:
467
486
  cloud_thread.join(timeout=2)
487
+ if gateway_handle:
488
+ gateway_handle.shutdown()
468
489
  if workspace_session and not args.workspace_keep:
469
490
  materializer.make_writable(workspace_session.workspace_root)
470
491
  shutil.rmtree(workspace_session.workspace_root, ignore_errors=True)
@@ -489,6 +510,19 @@ def _start_agent_process(argv: List[str], env, cwd: str, sanitize_output: bool =
489
510
  return subprocess.Popen(argv, env=env, cwd=cwd, stdout=stdout, stderr=stderr)
490
511
 
491
512
 
513
+ def _should_preserve_interactive_tty(argv: List[str]) -> bool:
514
+ if not argv or not _stdio_is_tty():
515
+ return False
516
+ command = os.path.basename(argv[0])
517
+ if command not in INTERACTIVE_AGENT_COMMANDS:
518
+ return False
519
+ return len(argv) == 1
520
+
521
+
522
+ def _stdio_is_tty() -> bool:
523
+ return sys.stdin.isatty() and sys.stdout.isatty() and sys.stderr.isatty()
524
+
525
+
492
526
  def _wait_for_agent_process(process, sanitizer: SecretOutputSanitizer) -> int:
493
527
  if process.stdout is None and process.stderr is None:
494
528
  return process.wait()
@@ -665,7 +699,7 @@ def _start_local_gateway_thread(container: Container, host: str, port: int):
665
699
  if isinstance(gateway_status, Exception):
666
700
  sys.stderr.write("agentsecure: gateway failed to start: %s\n" % gateway_status)
667
701
  return 1
668
- return gateway_thread
702
+ return LocalGatewayHandle(gateway, gateway_thread)
669
703
 
670
704
 
671
705
  def _proxy_url(host: str, port: int, session_id: str = "") -> str:
@@ -4,7 +4,7 @@ from typing import Any, Dict, List
4
4
 
5
5
 
6
6
  AGENTSECURE_MD = "AGENTSECURE.md"
7
- AGENTSECURE_MD_TEMPLATE_VERSION = "0.1.4"
7
+ AGENTSECURE_MD_TEMPLATE_VERSION = "0.1.6"
8
8
 
9
9
  AGENTSECURE_MD_TEMPLATE = """# AGENTSECURE.md
10
10
 
@@ -568,6 +568,10 @@ class LocalGateway:
568
568
  ready_callback()
569
569
  server.serve_forever()
570
570
 
571
+ def shutdown(self) -> None:
572
+ if self._server is not None:
573
+ self._server.shutdown()
574
+
571
575
  def _handler_class(self):
572
576
  class BoundGatewayRequestHandler(GatewayRequestHandler):
573
577
  pass
@@ -585,3 +589,6 @@ class LocalGateway:
585
589
  class ReusableThreadingTCPServer(socketserver.ThreadingTCPServer):
586
590
  allow_reuse_address = True
587
591
  daemon_threads = True
592
+
593
+ def handle_error(self, request, client_address) -> None:
594
+ return
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentsecure
3
- Version: 0.1.4
3
+ Version: 0.1.6
4
4
  Summary: Local-first security runtime for AI coding agents
5
5
  Home-page: https://github.com/ShellFrameAI/agentsecure-community
6
6
  Author: ShellFrame AI
@@ -41,11 +41,22 @@ The community release is intentionally scoped to local CLI, local command guard,
41
41
  ## Install
42
42
 
43
43
  ```bash
44
- python3 -m pip install agentsecure
44
+ python3 -m pip install --upgrade agentsecure
45
+ python3 -m agentsecure demo
46
+ ```
47
+
48
+ `python3 -m agentsecure` works even when `pip` installs the `agentsecure`
49
+ executable into a user script directory that is not on your `PATH`. If you want
50
+ the shorter `agentsecure` command, add Python's user script directory to your
51
+ shell path:
52
+
53
+ ```bash
54
+ export PATH="$(python3 -m site --user-base)/bin:$PATH"
45
55
  agentsecure demo
46
56
  ```
47
57
 
48
- Use a virtual environment if you want to keep it isolated:
58
+ You do not need a virtual environment to run AgentSecure. Use one only if you
59
+ want the install isolated to this project:
49
60
 
50
61
  ```bash
51
62
  python3 -m venv .venv
@@ -55,6 +66,12 @@ python -m pip install agentsecure
55
66
  agentsecure demo
56
67
  ```
57
68
 
69
+ Then run your agent:
70
+
71
+ ```bash
72
+ python3 -m agentsecure run claude
73
+ ```
74
+
58
75
  ## What The Demo Shows
59
76
 
60
77
  The built-in demo creates a temporary local project with fake secrets, applies a small sample policy, simulates a command reading `.env`, and prints what the agent would see:
@@ -217,11 +234,15 @@ agentsecure receipts --proxy
217
234
  Run an agent or command through local command guard:
218
235
 
219
236
  ```bash
220
- agentsecure run --protect-all -- codex
221
- agentsecure run --protect-all -- claude
222
- agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
237
+ python3 -m agentsecure run --protect-all -- codex
238
+ python3 -m agentsecure run --protect-all -- claude
239
+ python3 -m agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
223
240
  ```
224
241
 
242
+ Bare interactive agent launches keep the terminal attached so tools such as
243
+ Claude Code can open normally. Non-interactive commands are still output
244
+ sanitized by AgentSecure.
245
+
225
246
  Use workspace copy mode when you want review-before-apply:
226
247
 
227
248
  ```bash
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = agentsecure
3
- version = 0.1.4
3
+ version = 0.1.6
4
4
  description = Local-first security runtime for AI coding agents
5
5
  long_description = file: README.md
6
6
  long_description_content_type = text/markdown
@@ -2,6 +2,7 @@ import unittest
2
2
  import socket
3
3
  from io import StringIO
4
4
  from contextlib import redirect_stdout
5
+ from unittest.mock import patch
5
6
 
6
7
  from agentsecure.cli.main import (
7
8
  _apply_proxy_environment,
@@ -11,6 +12,7 @@ from agentsecure.cli.main import (
11
12
  build_parser,
12
13
  _merge_no_proxy,
13
14
  _proxy_url,
15
+ _should_preserve_interactive_tty,
14
16
  )
15
17
  from agentsecure.core.models import AgentSecureConfig, SecretBinding
16
18
 
@@ -117,6 +119,18 @@ class CliTest(unittest.TestCase):
117
119
  finally:
118
120
  sock.close()
119
121
 
122
+ def test_preserves_tty_for_bare_interactive_agent(self):
123
+ with patch("agentsecure.cli.main._stdio_is_tty", return_value=True):
124
+ self.assertTrue(_should_preserve_interactive_tty(["claude"]))
125
+
126
+ def test_does_not_preserve_tty_for_regular_commands(self):
127
+ with patch("agentsecure.cli.main._stdio_is_tty", return_value=True):
128
+ self.assertFalse(_should_preserve_interactive_tty(["cat", ".env"]))
129
+
130
+ def test_does_not_preserve_tty_when_agent_has_arguments(self):
131
+ with patch("agentsecure.cli.main._stdio_is_tty", return_value=True):
132
+ self.assertFalse(_should_preserve_interactive_tty(["claude", "--print", "hello"]))
133
+
120
134
 
121
135
  if __name__ == "__main__":
122
136
  unittest.main()
File without changes
File without changes
File without changes
File without changes