Gobstopper plugins are explicitly trusted, versioned subprocess bundles. They are extension boundaries, not security sandboxes. The host keeps source ownership, policy, validation, snapshots, publication, and provider controls.
A manifest declares one or more closed capabilities:
strategy: receives an already normalized built-in transcript and proposesEdit[].provider_read: inspects a bounded source file and returns normalized items and usage, with no edit proposals. This is a protocol restriction on the response; a trusted subprocess can still have operating-system side effects.read_content: allows source lines or normalized summaries to be included for an operation that also declares it.
A provider plugin does not grant Gobstopper permission to rewrite that provider's files. External runtimes can request policy advice through policy-check/MCP and use provider_read for export inspection. The runtime must separately test and control any provider operation it executes. MCP does not execute plugins or external strategies.
The JSON manifest is limited to 64 KiB and rejects unknown fields. Example shape:
{
"protocol_version": 1,
"id": "example-atif-reader",
"version": "1.0.0",
"executable": "reader.py",
"files": {
"reader.py": "<sha256-of-reader.py>"
},
"args": [],
"capabilities": ["provider_read", "read_content"],
"provider_ids": ["example-atif"],
"timeout_ms": 5000,
"max_input_bytes": 2097152,
"max_output_bytes": 1048576,
"environment": []
}The executable and every runtime artifact must be a declared regular file below the manifest directory. Paths are relative and cannot traverse upward. Bundles are limited to 64 declared files, 256 directory entries, eight levels, and 16 MiB total. The child receives a cleared environment except for explicitly named variables.
Run admission without executing code:
gobstopper plugin check /absolute/path/gobstopper-plugin.jsonThe result prints manifest_sha256. Pin that exact value in configuration or pass it to plugin inspect. Any manifest or declared-file change requires review and a new trust hash. Gobstopper rechecks identity after execution.
The plugin reads one JSON object from stdin:
{
"protocol_version": 1,
"operation": "provider_read",
"provider_id": "example-atif",
"source_sha256": "<64 hex characters>",
"items": [],
"usage": {
"context_tokens": 0,
"lifetime_input_tokens": 0,
"lifetime_cached_tokens": 0,
"model_context_window": null
},
"policy": null,
"content": ["{", " ...", "}"]
}Input is capped by both the host maximum (2 MiB) and the manifest's lower limit. content appears only when read_content is declared. Treat its lines as a bounded representation of the source document, not as a guaranteed JSONL record mapping.
For strategy, items contains normalized TranscriptItem values and policy contains the resolved policy. Plugins should defer with an empty edits array.
Return exactly one JSON object on stdout:
{
"protocol_version": 1,
"source_sha256": "<same digest as request>",
"edits": [],
"inspection": {
"provider_id": "example-atif",
"session_id": "bounded-session-id",
"items": [],
"usage": {
"context_tokens": 0,
"lifetime_input_tokens": 0,
"lifetime_cached_tokens": 0,
"model_context_window": null
}
}
}Unknown fields fail admission. source_sha256 must exactly echo the request binding. A provider_read response requires one inspection and no edits; a strategy response may contain edits and no inspection.
Normalized inspection items must be strictly increasing and unique, with logical indexes below 100,000. Labels, summaries, UUID-like fields, tool-use IDs, payload hashes, usage, elidable byte counts, and part counts are independently bounded. Logical indexes support whole-document formats such as ATIF.
Strategy proposals may use elide and inject_digest. External plugins cannot dispatch provider_compact or Claude cache_edit controls. The host rejects:
- unknown, duplicate, out-of-range, or protected-tail indexes;
- non-elidable targets or mixed provider/file controls;
- oversized, empty-coverage, or malformed state cards;
- edits that do not reduce projected context by
min_savings_tokens; - candidates that add structural verification findings.
Applying a plugin's file plan works like any other file apply: Gobstopper retains the exact source and candidate bytes, then publishes a separate Claude Code or Codex fork without overwriting an existing file. Host validation does not sandbox the trusted plugin process itself.
Execution is bounded to 30 seconds, 2 MiB input, and 1 MiB each for stdout and stderr, with lower manifest limits encouraged. The process runs in its own process group; timeout, output overflow, non-zero exit, invalid JSON, identity drift, or malformed output kills/reaps the process and fails closed. No retry is automatic.
A new provider integration should include:
- a stable lowercase provider ID;
- fixtures for empty, malformed, maximum-size, forked/branched, and representative exports;
- explicit token-accounting semantics;
- deterministic logical item ordering and stable labels;
- timeout/output-bound tests and malformed-response tests;
- documentation of the provider-owned native compaction control;
- no direct mutation until a separate, reviewed write protocol exists.
Built-in adapter proposals must additionally preserve the supported structural invariants and pass the workspace regression/property suite. Provider resume acceptance requires separate testing. xcb is a library consumer: it pins gobstopper-core to an exact Git commit and applies a strategy only to the prompt it builds in memory, keeping the full local history. Its compatibility editor uses the preset command interface. Other adjacent runtimes have no implicit privileged access: use numeric policy/MCP or this plugin protocol unless a provider-owned contract is documented and tested.