@spellguard-ai/claude-code-plugin
v0.0.1
Published
Claude Code plugin for Spellguard agent credential management
Downloads
339
Maintainers
Readme
@spellguard-ai/openclaw-plugin
Spellguard managed-agent control-plane plugin. Runs inside the managed agent's Claude Code environment (provisioned via the managed-provisioning flow) and enforces credential scope, detects git-mutating operations, emits observations
- policy decisions to the Spellguard backend, and handles the one-shot bootstrap-nonce claim flow on first boot.
Published to npm as @spellguard-ai/openclaw-plugin (REQ-009). Installed
automatically by the cloud-init bootstrap script — manual installation is also
supported for developer environments.
Entry points
| Export | Description |
|--------|-------------|
| runSpellguardSetup | /spellguard-setup skill — bootstraps device token via WebSocket handshake, writes config |
| runSessionStart | SessionStart hook — validates scoped token, writes git credential helper env file |
| runMonitorTick | Monitor hook — polls token status every 30 min, refreshes scope cache, clears env on revocation |
| runPreToolUse | PreToolUse runtime entry (CR-011) — status-check probe (block on revoked/401/410) then scope-filtered observation emission |
| emitPreToolUseObservation | Observation-only helper — detects git-mutating Bash commands and emits observations (bypasses the status probe; used by tests and legacy callers) |
| observeGitOperation | Core pipeline: canonicalize remote → scope check → build event → emit/queue |
| detectGitOperation | Stateless helper: maps (toolName, args[]) → 'push' \| 'branch_create' \| 'pr_open' \| null |
SessionStart hook
Runs at the start of every Claude Code session. Checks the scoped token against
GET /v1/credentials/status. On valid or near_expiry, writes the
SPELLGUARD_GIT_ASKPASS env var so git operations use the credential helper.
On revoked or expired, clears the env file and exits with an error message.
Fails closed on SSH remotes (no HTTPS credential injection possible).
Monitor polling cadence
runMonitorTick is designed to be called on a 30-minute timer. It:
- Calls
GET /v1/credentials/status. - If status is
revokedorexpired, clears the env file. - If the scope cache is stale (>30 min old), fetches fresh scope from
GET /v1/credentials/scopeand writes it to~/.config/spellguard/observation-scope.json.
/spellguard-setup flow
- Generates a 256-bit random nonce.
- Opens a WebSocket to
wss://api.spellguard.dev/bootstrap?nonce=<nonce>. - Prints a dashboard URL for the user to complete OAuth.
- Awaits a bootstrap frame containing
device_token,scoped_token,scoped_token_id,agent_id, andscope_summary. - Writes config to
~/.config/spellguard/config.json(mode 0600).
Cross-plan touch-points
This package is the client-side contract for several backend and e2e tests:
| Test ID | Plan | Plugin entry point |
|---------|------|--------------------|
| IT-001 | Plan 02 (backend) | runSpellguardSetup — WebSocket bootstrap → write config |
| ET-001 | Plan 02 (e2e) | runSpellguardSetup → runSessionStart → observeGitOperation round-trip |
| ET-002 | Plan 02 (e2e) | Two isolated XDG_CONFIG_HOME instances, both calling runSessionStart then observeGitOperation |
| ET-003 | Plan 02 (e2e) | runSessionStart after server-side scoped-token revocation |
| IT-006 | Plan 04 (plugin) | runSessionStart happy path |
| IT-007 | Plan 04 (plugin) | runSessionStart SSH refusal |
| IT-008 | Plan 04 (plugin) | runMonitorTick revocation |
| IT-021 | Plan 04 (plugin) | runMonitorTick scope cache refresh |
GitHub App permissions (CR3-M11)
The required GitHub App permission set lives in
src/lib/github-app-permissions.ts as the GITHUB_APP_REQUIRED_PERMISSIONS
constant. It mirrors PRD REQ-001:
| Resource | Access |
|----------|--------|
| contents | write |
| pull_requests | write |
| issues | write |
| metadata | read |
| members | read |
| administration | read |
This constant is metadata only. The App's effective permissions live at github.com under the App settings page and must be updated manually there to match. Changing the constant does NOT change runtime behavior.
The static-audit tests
tests/unit/github-mvp/plugin-app-manifest-permissions.test.ts and
tests/integration/github-mvp/neg-audit-source-grep.test.ts (case
CR3-M11) lock the constant to the PRD spec to catch future drift.
(Pre-bd7738d2, this lived as .claude-plugin/plugin.json#gitHubApp.permissions,
but Claude Code's modern manifest schema doesn't allow extension fields.)
