{
  "markdown": "# HarnessBox\n\n[![PyPI](https://img.shields.io/pypi/v/harnessbox)](https://pypi.org/project/harnessbox/)\n[![CI](https://github.com/Nikhil-Kadapala/HarnessBox/actions/workflows/ci.yml/badge.svg)](https://github.com/Nikhil-Kadapala/HarnessBox/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-blue.svg)](https://www.python.org/downloads/)\n\nRun AI coding agents in secure sandbox environments with workspace orchestration, auto-pause, and multi-session support.\n\n```python\nimport os\nfrom harnessbox import HarnessBox\n\nasync with HarnessBox(\n    provider=\"e2b\",\n    harness=\"claude-code\",\n    secrets={\n        \"provider_api_key\": os.getenv(\"E2B_API_KEY\"),\n        \"harness_secrets\": {\"ANTHROPIC_API_KEY\": os.getenv(\"ANTHROPIC_API_KEY\")},\n    },\n) as hb:\n    async for event in hb.send_message(\"Fix the failing test\"):\n        print(event.delta or \"\", end=\"\")\n```\n\n`HarnessBox` is the sole public API — provision sandboxes, manage workspaces, run agent sessions. Provider SDKs are optional extras.\n\n## Install\n\n```bash\n# SDK + interactive CLI (hbox) + local server deps\npip install harnessbox\n\n# + E2B sandbox provider\npip install \"harnessbox[e2b]\"\n```\n\nThen run `hbox` for the interactive shell, or `harnessbox serve` for a standalone API server.\n\n## Quickstart\n\n```python\nimport os\nfrom harnessbox import HarnessBox, WorkspaceConfig\nfrom harnessbox.workspace import GitRepoConfig\n\nhb = HarnessBox(\n    provider=\"e2b\",\n    harness=\"claude-code\",\n    workspace_config=WorkspaceConfig(\n        git_repo_config=GitRepoConfig(\n            remote=\"https://github.com/user/repo.git\",\n            branch=\"main\",\n        ),\n    ),\n    secrets={\n        \"provider_api_key\": os.getenv(\"E2B_API_KEY\"),\n        \"harness_secrets\": {\"ANTHROPIC_API_KEY\": os.getenv(\"ANTHROPIC_API_KEY\")},\n    },\n)\n\nsession = await hb.create_session()\nasync for event in session.send_message(\"Fix the tests\"):\n    print(event.delta or \"\", end=\"\")\nawait hb.kill()\n```\n\n## Multi-Session Mode\n\nRun multiple agents on different branches simultaneously:\n\n```python\nimport os\nfrom harnessbox import HarnessBox, WorkspaceConfig, WorkspaceMode\nfrom harnessbox.workspace import GitRepoConfig\n\nhb = HarnessBox(\n    provider=\"e2b\",\n    harness=\"claude-code\",\n    workspace_config=WorkspaceConfig(\n        workspace_mode=WorkspaceMode.NEW,\n        git_repo_config=GitRepoConfig(\n            remote=\"https://github.com/user/repo.git\",\n            branch=\"main\",\n        ),\n    ),\n    secrets={\n        \"provider_api_key\": os.getenv(\"E2B_API_KEY\"),\n        \"harness_secrets\": {\"ANTHROPIC_API_KEY\": os.getenv(\"ANTHROPIC_API_KEY\")},\n    },\n)\n\n# Each session gets its own sandbox\nauth_session = await hb.create_session(branch=\"feat/auth\")\nui_session = await hb.create_session(branch=\"feat/ui\")\n\n# Interact with sessions directly\nasync for event in auth_session.send_message(\"Fix the auth bug\"):\n    print(event.delta or \"\", end=\"\")\n\n# Non-streaming\nresult = await ui_session.send_message(\"Add dark mode\", stream=False)\nprint(result.text)\n\n# Clean up\nawait auth_session.kill()\nawait ui_session.kill()\n```\n\nSee [`examples/multi_session.py`](packages/sdk/examples/multi_session.py) for a complete runnable example.\n\n## How It Works\n\nHarnessBox is a Python library. You import it, provision a sandbox, and stream agent output. That's the whole product.\n\n```python\nfrom harnessbox import HarnessBox, WorkspaceConfig\nfrom harnessbox.workspace import GitRepoConfig\n\nhb = HarnessBox(\n    provider=\"e2b\",\n    harness=\"claude-code\",\n    workspace_config=WorkspaceConfig(\n        git_repo_config=GitRepoConfig(\n            remote=\"https://github.com/user/repo.git\",\n        )\n    ),\n    secrets={...}\n)\nsession = await hb.create_session()\n\nasync for event in session.send_message(\"Fix the failing test\"):\n    print(event.delta or \"\", end=\"\")\n\nawait hb.kill()\n```\n\nEverything else is a deployment choice:\n\n```\n┌────────────────────────────────────────────────────────────┐\n│              HarnessBox (Python SDK)                         │\n│                                                             │\n│  • Create workspaces and sessions                          │\n│  • Stream agent output as async events                     │\n│  • Auto-pause idle sandboxes, resume on next message       │\n│  • Persist state across restarts (SQLite)                  │\n│  • Security policies, credential guards                    │\n└─────────────────────┬───────────────────┬──────────────────┘\n                      │                   │\n        \"I'm a script │                   │ \"I need a web UI\n        or service\"   │                   │  or team access\"\n                      ▼                   ▼\n           ┌─────────────────┐  ┌────────────────────────────┐\n           │  Use the SDK    │  │  Run `harnessbox serve`    │\n           │  directly       │  │  (same SDK + HTTP/SSE)     │\n           │                 │  │                            │\n           │  No server.     │  │  Adds: multi-client,      │\n           │  No infra.      │  │  web dashboard, shared    │\n           │  Just Python.   │  │  state across consumers.  │\n           └─────────────────┘  └────────────────────────────┘\n```\n\nThink of it like SQLite vs Postgres. SQLite is embedded — no server, works great for one process. Postgres adds a server for shared access. Same SQL, same data model, different deployment. HarnessBox works the same way.\n\n**When you don't need the server:**\n- Scripts and CI pipelines\n- Single-developer tools\n- Programmatic agents (backend services)\n- Anything where one Python process is enough\n\n**When you add the server:**\n- You're building a web UI for your team\n- Multiple clients (web + CLI + SDK) need to see the same workspaces\n- You want an always-on orchestrator that survives process restarts\n- You're running our hosted platform (`base_url=\"https://api.harnessbox.dev\"`)\n\n## Server\n\nThe server is the SDK running as a long-lived process that accepts HTTP connections. Same features, accessible over the network.\n\n```bash\n# Self-hosted (server deps are in the base install)\npip install harnessbox\n# For sandboxes:\npip install \"harnessbox[e2b]\"\nharnessbox serve --port 8080\n\n# Or with Docker\ndocker run -p 8080:8080 harnessbox/server\n```\n\nPoint the SDK at your server (planned):\n\n```python\n# SDK becomes a thin client — all orchestration happens server-side\nhb = HarnessBox(base_url=\"http://localhost:8080\", secrets={...})\n# Same API, same streaming, same everything\n```\n\nServer endpoints:\n- `POST /v1/workspaces` — create workspace\n- `GET /v1/workspaces` — list workspaces\n- `DELETE /v1/workspaces/{id}` — destroy workspace\n- `POST /v1/workspaces/{id}/prompt` — send prompt (SSE stream)\n- `GET /v1/workspaces/{id}/events` — subscribe to live events (SSE)\n\n## Security\n\nHarnessBox generates agent-specific deny rules and PreToolUse hook guards that protect credentials inside sandboxes:\n\n| Threat | Defense |\n|--------|---------|\n| `printenv` / `env` / `os.environ` | Bash deny rules + hook guard |\n| Read `.env`, `.aws/credentials` | Read deny rules |\n| `WebFetch` exfiltration | Tool deny rules |\n| Agent spawning sub-agents | `Agent` deny rules |\n| `/proc/self/environ` | Bash deny rules + hook guard |\n| IMDS credential theft (169.254.169.254) | Hook guard regex |\n| Git credential helper leak | `git config credential.*` deny |\n\n```python\nfrom harnessbox import SecurityPolicy\n\npolicy = SecurityPolicy(\n    denied_tools=[\"WebFetch\", \"WebSearch\", \"Agent\"],\n    denied_bash_patterns=[\"rm -rf /\"],\n    deny_network=True,\n    include_credential_guards=True,  # on by default\n)\n```\n\n## Built-in Harness Types\n\n| Harness | Config Dir | System Prompt | CLI |\n|---------|-----------|---------------|-----|\n| `claude-code` | `.claude` | `CLAUDE.md` | `claude --dangerously-skip-permissions ...` |\n| `codex` | `.codex` | `AGENTS.md` | `codex --model o4-mini -q {prompt}` |\n| `opencode` | `.opencode` | `AGENTS.md` | `opencode -p {prompt}` |\n\n## Key Features\n\n| Feature | Description |\n|---------|-------------|\n| **Auto-pause/resume** | Idle workspaces pause → $0/hr. Resume transparently on next message. |\n| **Multi-session** | Multiple concurrent agent sessions per workspace. |\n| **Branch-based pooling** | Same (remote, branch) reuses existing workspace. |\n| **Security policies** | Credential guards, tool deny lists, network blocking. |\n| **Git workflows** | Clone, commit, push on exit. Branch creation from base. |\n| **Provider extras** | E2B (and future backends) via `harnessbox[e2b]`. Base install includes CLI + server deps. |\n| **Any provider** | E2B, Docker, Daytona, EC2. Protocol-based extensibility. |\n\n## API Reference\n\n### HarnessBox\n\n```python\nfrom harnessbox import HarnessBox, HarnessBoxSecrets, WorkspaceConfig, WorkspaceMode\nfrom harnessbox.workspace import GitRepoConfig\n\nhb = HarnessBox(\n    provider=\"e2b\",                    # Provider name or instance\n    harness=\"claude-code\",             # Agent harness type\n    api_key=\"hb_live_...\",             # Platform key (None = self-hosted)\n    secrets=HarnessBoxSecrets(         # Or pass as dict\n        provider_api_key=\"e2b_...\",\n        harness_secrets={\"ANTHROPIC_API_KEY\": \"sk-ant-...\"},\n    ),\n    model=\"claude-sonnet-4-6-20250514\",\n    system_prompt=Path(\"CLAUDE.md\"),    # Path to load from file, or str for inline content\n    workspace_config=WorkspaceConfig(\n        workspace_mode=WorkspaceMode.NEW,\n        git_repo_config=GitRepoConfig(\n            remote=\"https://github.com/org/repo.git\",\n            branch=\"feat/auth\",\n            base_branch=\"main\",\n        ),\n    ),\n    security_policy=SecurityPolicy(...),\n    setup_script=\"npm install\",\n    timeout=300,\n)\n\n# Lifecycle\nsession = await hb.create_session()\nasync for event in session.send_message(\"Fix tests\"):\n    print(event.delta)\n\n# Non-streaming\nresponse = await session.send_message(\"Fix tests\", stream=False)\n\n# Run a raw shell command in the session\nresult = await session.run_command(\"pytest\")\n\n# Clean up all sessions\nawait hb.kill()\n\n# Context manager (auto create + kill)\nasync with HarnessBox(provider=\"e2b\", workspace_config=WorkspaceConfig()) as hb:\n    session = await hb.create_session()\n    async for event in session.send_message(\"Hello\"):\n        print(event.delta)\n```\n\n### WorkspaceConfig\n\n```python\nWorkspaceConfig(\n    workspace_mode: WorkspaceMode = WorkspaceMode.NEW, # NEW or SHARED\n    git_repo_config: GitRepoConfig | None = None,      # Git repo setup\n    file_system_config: FileSystemConfig | None = None,# Local directory mapping\n)\n```\n\n### GitRepoConfig\n\n```python\nGitRepoConfig(\n    remote: str,                          # Git remote HTTPS or SSH URL\n    *,\n    branch: str = \"main\",                 # Checkout branch\n    base_branch: str | None = None,       # Base branch to fork from\n    clone_depth: int | None = None,       # Git shallow clone depth\n    auth_token: str | None = None,        # Git access token for auth\n    clone_dir_name: str | None = None,    # Custom name for directory\n)\n```\n\n### SecurityPolicy\n\n```python\nSecurityPolicy(\n    denied_tools: list[str] = [],\n    denied_bash_patterns: list[str] = [],\n    deny_network: bool = False,\n    include_credential_guards: bool = True,\n)\n```\n\n## Project Structure\n\n```\npackages/sdk/src/harnessbox/\n  __init__.py                   # public API\n  harnessbox.py                 # HarnessBox — public entry point\n  sandbox.py                    # internal sandbox orchestration\n  workspace.py                  # Workspace protocol, GitRepoConfig\n  providers.py                  # SandboxProvider protocol\n  lifecycle.py                  # RuntimeState transition map\n  streaming.py                  # UniversalEvent, StreamParser\n  events.py                     # EventBuffer (SSE replay)\n  server.py                     # HTTP/SSE transport\n  config/\n    harness.py                  # HarnessTypeConfig registry\n    manifest.py                 # SandboxManifest builder\n  security/\n    policy.py                   # SecurityPolicy, deny rules\n    hooks.py                    # PreToolUse hook guard\n    events.py                   # SandboxEvent, EventHandler\n  _providers/\n    e2b.py                      # E2B provider\n  _server/\n    workspace_manager.py        # internal workspace orchestration\n    registry.py                 # workspace registry\n    _storage/\n      sqlite.py                 # SQLite backend\n      memory.py                 # In-memory backend\npackages/sdk/tests/             # Unit & integration tests\napps/web/                       # Web application front-end (Vite/React)\napps/api/                       # Cloud API for paid tier (planned)\n```\n\n## License\n\nMIT\n",
  "bytes": 12713,
  "sha": "bbf39d236a3f74f87101c1ad3cc2550478e27cef85c2f343e1092e315e7ffa90",
  "repo_slug": "nikhil-kadapala/harnessbox",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/okf_nikhil_kadapala_harnessbox_docs_index_md_c651721d/readme"
}