External Paperclip adapter for running Oh My Pi (OMP) CLI in headless mode with native model discovery, custom providers, resumable local sessions, skills synchronization, multi-workspace support, and structured transcripts.
This adapter integrates OMP into Paperclip as an external adapter module (omp_local). It communicates with the host Paperclip instance via the @paperclipai/adapter-utils contract and parses OMP's non-interactive JSONL event stream into Paperclip transcript entries.
| Feature | Paperclip Integration | OMP CLI Mapping |
|---|---|---|
| Model Discovery | Dynamic model list and badge updates | omp models --json and omp models refresh --json |
| Execution Mode | Headless execution per heartbeat run | omp --mode json -p |
| Session Resume | Resumes conversation across runs | --session-dir <dir> --resume <id> |
| Multi-Workspace | Local roots; only realized/staged roots on remote targets | --add-dir <path> (repeatable) |
| Thinking / Reasoning | Live transcript streaming plus durable omp.thinking run events |
--thinking <level>, --print-thoughts |
| Tool Events | Real-time tool calls, progress updates, durable omp.tool run events |
Maps tool_execution_* to Paperclip entries |
| Skills Integration | Paperclip workspace skills synchronization | Links skills into ~/.omp/agent/skills |
| Cancellation | Host-driven run abortion | Listens to ctx.signal and signals process group |
| Targets | Local and remote execution | Direct spawn, SSH, or managed sandboxes |
- Node.js >= 24.11.0
- Paperclip 2026.1012.0 (adapter helper and shared contracts pinned to this release)
- Oh My Pi (OMP) installed in the selected execution environment (
ompexecutable available inPATHor explicitly configured viacommand); remote-only deployments do not need OMP on the Paperclip hub
Install OMP globally:
npm install -g @oh-my-pi/pi-coding-agent@18.11.0Deadline classification requires an OMP runtime that emits the explicit terminal
agent_end.termination: { "reason": "deadline", "deadlineAt": <epoch milliseconds> }
contract; the unpatched 18.11.0 runtime does not supply it. The adapter reports
errorCode: "omp_deadline_exceeded", a nonzero effective exit code, an error
message, and resultJson.ompTermination even if the CLI exits zero. timedOut
still means the outer process watchdog fired, not the OMP agent-loop deadline.
Partial usage, tool results and artifact receipts remain available, but an
aborted run does not reuse an earlier success-like summary. Only the final
applicable terminal event determines this cause: yielded flags, tool failures,
timeout-like text and recovered model failures are not deadline evidence.
The adapter does not replay tools or promise preserved remote sessions.
Version 0.11.4 bounds adapter-owned resultJson to 48 KiB of UTF-8
JSON.stringify output. This leaves 16 KiB below the native 64 KiB retrieval
cutoff for native-added receipts; it is not a bound on metadata subsequently
added by Paperclip. Small ordinary results keep their existing fields and
values. Usage, cost, session metadata, cancellation acknowledgement, and the
explicit OMP termination cause are not inferred from truncated output.
Only persisted presentation metadata is reduced. Each non-tool section has a
3 KiB serialized budget; tool calls share 24 KiB, with a 6 KiB presentation
budget per call and up to 2 KiB of exact structured identifiers when reduced.
Recent calls take priority, retained calls remain chronological, and
toolCallsTotal/toolCallsOmitted report incomplete inventories. Nested samples
are limited to 12 levels and 128 entries per container. MCP image data,
resource blob, and recognized base64 data URLs are replaced by explicit
omission text. Long strings include a truncation marker, not a complete receipt.
Reduced results carry truncated, truncationReason, truncatedFields, and a
nativeRunLog containing the run ID and authenticated
/api/heartbeat-runs/<runId>/log path. Reduced calls carry their own truncation
marker and an identifiers index of exact operation/request/tool/resource/
artifact/session IDs found in structured payloads and small JSON text receipts.
identifiersComplete: false means the bounded index could not inspect or retain
all structured IDs (for example, JSON text over 64 KiB); it never asserts that
unstructured prose has been exhaustively indexed.
The native onLog stream remains byte-for-byte unchanged, including full JSONL,
image/resource payloads, and operation receipts. Failure/deadline classification
still uses the original parsed evidence. Recover complete operation evidence
from the native run log and actual operation ledger; a reduced tool result is
not authority to replay an uncertain mutation or proof that it succeeded.
The log locator assumes native log retention and access authorization; it is
not a new attachment API or a guarantee that a failed log sink retained bytes.
Historical oversized database rows are unchanged and still require safe native
read projection.
After publishing this fork's package, install it in a running Paperclip instance with:
paperclipai adapter install --payload-json '{"packageName":"@genrobo/paperclip-omp-adapter","version":"0.11.4"}' --jsonTo upgrade an existing installation:
paperclipai adapter reinstall omp_local --jsonCheck that the adapter is registered and loaded:
paperclipai adapter get omp_local --jsonVerify model discovery for a company:
paperclipai adapter models omp_local --company-id <company-id> --jsonSet these variables on the Paperclip server process/container, not in an agent's adapter configuration:
PAPERCLIP_OMP_REQUIRE_REMOTE=true
PAPERCLIP_ADAPTER_MODELS='{"omp_local":[{"id":"provider/model","label":"Display name"}]}'The policy is enabled by true (case-insensitive, surrounding whitespace ignored). When unset or another value, normal local-library behavior is preserved. Adapter type remains omp_local; this is an operator deployment policy, not a new adapter or agent-editable setting.
executeandtestEnvironmentrequire a host-suppliedexecutionTargetwithkind: "remote", a nonemptyremoteCwd, and eithertransport: "ssh"with a valid Paperclip SSHspec, ortransport: "sandbox"with a live hostrunner.executefunction. Execution also retains the existing host legacy SSHexecutionTransport.remoteExecutioncontract.- Missing/local/malformed targets fail before workspace creation, command resolution, installation, probes, or local OMP spawn.
executereturnsexitCode: 1,errorFamily: "configuration",errorCode: "omp_remote_target_required"; environment testing returnsstatus: "fail"with the same check code. - Agent
config,config.env, and serialized target-like configuration cannot disable the host policy or supply the host runner. Remote connectivity/setup failures propagate; there is no local fallback. Operators remain responsible for placing the supplied SSH/sandbox target on the separate runner, not on the hub. - Model listing/refresh and adapter registration never invoke local OMP under this policy. They reuse Paperclip's existing
PAPERCLIP_ADAPTER_MODELSJSON object, specifically itsomp_localarray of{id,label?}entries. Missing labels default to the id; an empty array is an explicit empty catalog. This is a picker catalog, not provider credentials or proof of model availability. - Without an
omp_localcatalog, listing/refresh reject with errorcode: "omp_explicit_model_required"and instructions to set agentconfig.modelto a provider/model selector. The configuration schema remains usable as a free-text model combobox; automatic model detection returnsnull. Invalid catalog JSON/OMP entries reject withcode: "omp_model_catalog_invalid". - Host quota discovery returns
ok: falseand no windows without invokingomp usage. Environment tests with a valid remote target still perform their OMP model/auth probes remotely.
Configure the Paperclip host to permit this external adapter on the selected remote environment and supply a real provider runner/SSH connection. This package does not provision an environment or make an otherwise ineligible host dispatch remote.
Remote command arguments and prompt workspace context use the SDK's realized workspace view, not the original host paths. Unstaged workspace hints retain metadata but lose their inaccessible directory. Configured addDirs, like extensions/config files, must be within the selected synchronized workspace and are remapped into the runner; an outside path is rejected rather than advertised as accessible. This does not stage arbitrary additional project trees.
Native runtimeTools and runtimeMcp are materialized into a private per-run
mcp.json using OMP's mcpServers convention. Native connection identities,
not display names, identify servers; unsafe MCP key characters are mapped to
stable hashed names without losing the host-side connection identity.
Remote HTTP MCP connections use the authenticated execution-target bridge.
The host retains each exact upstream endpoint and bearer token; the runner
receives only its granted /api/runtime-mcp/<bridge-id> routes and per-run
bridge credential. Generated JSON uses environment references for URLs and
authorization. Unknown grants, query overrides and endpoint aliases fail
closed; forwarding rejects redirects.
This remote feature requires the infrastructure repository's
runtime-mcp-bridge.patch
and PAPERCLIP_RUNTIME_MCP_BRIDGE_VERSION=1 exported by the host's
@paperclipai/adapter-utils. The adapter must resolve that patched SDK, not a
second unpatched nested copy. A stock helper package fails explicitly rather
than sending host-local URLs or native connection tokens into the runner.
Local execution continues to use its native environment-bound credentials.
For issue-scoped workload tools, set this only on the trusted Paperclip server
process, never in an agent's adapter config.env:
PAPERCLIP_WORKLOAD_MCP_COMMAND=/opt/gr-workload-mcp-client/bin/gr-workload-mcp-client
# Optional: explicit operator-owned native MCP configuration on the Paperclip host
PAPERCLIP_OMP_MCP_CONFIG=/etc/paperclip/omp/mcp.jsonThe command is an absolute executable path inside the execution target.
Install services/workload-mcp-client from the infrastructure repository at
/opt/gr-workload-mcp-client, with a trusted Node >=24.11.0 on PATH (the
entrypoint uses #!/usr/bin/env node). The package pins MCP SDK 1.29.0 and
provides bin/gr-workload-mcp-client; image preparation uses:
npm ci --ignore-scripts
npm run build
npm prune --omit=dev --ignore-scripts
chmod 0555 bin/gr-workload-mcp-clientMake the installation and Node binary operator-owned and read-only to the
sandbox user. No runtime package download, agent-supplied command, broker
secret, or new worker listener is used. The client inherits native
PAPERCLIP_API_URL, PAPERCLIP_API_KEY, PAPERCLIP_RUN_ID, and
PAPERCLIP_TASK_ID; remote issue runs require a working native Paperclip bridge.
The native server must permit only the gr.workloads issue routes through both
bridge transports and have the workloads plugin installed. Missing authority
fails explicitly. The API URL is an HTTP(S) origin, not an /api URL.
An optional operator MCP file is merged without modifying its source, preserving
servers and enable/disable lists. Reserved server-name collisions, aliases of
native endpoints/executables, malformed files, and unselected inherited
mcp.json/.mcp.json fail closed. Select intentional existing agent-directory
MCP configuration explicitly with PAPERCLIP_OMP_MCP_CONFIG; it is never
implicitly promoted from an agent-selected directory. Operator MCP entries and
their referenced executables must themselves be safe for the execution target.
Agent-supplied authority variables, config.env.PI_CONFIG_FILES, and raw
profile/config override arguments are rejected while native MCP is active;
use the normal configFiles field for ordinary overlays. Settings that disable
the native discovery provider or a required runtime MCP server fail clearly
rather than quietly removing tools.
A final trusted --config overlay disables only MCP project discovery
before OMP deduplication, so project mcp.json cannot shadow runtime tools.
It waits for MCP startup discovery to settle (individual server deadlines remain
bounded). It does not disable discovery providers, skills, rules, or unrelated
OMP features. Configured ordinary overlays still apply before this policy.
Temporary configuration is removed by the existing per-run cleanup.
The base workload tools are gr_request_resource, gr_list_resources,
gr_resource_status, gr_application_tools, gr_call_application,
gr_operation_status, and gr_release_resource. Mutations require a
caller-retained request/operation UUID: transport reconnection must reuse that
ID with the same payload. HTTP calls have a 20-second deadline and no automatic
retry; uncertain mutations are not represented as failures safe to repeat.
Completed operation results preserve actual MCP image/resource blocks and
structured output, including failed application results with partial-mutation
warnings and isError: true. Do not re-execute indeterminate edits; save desired
state before explicit release.
The workload server deadline is 900,000 ms so committed engineering source can
transfer in bounded resumable batches. Native HTTP MCP servers retain their
30-second deadline. OMP 18.11.0's OMP_MCP_TIMEOUT_MS overrides per-server values:
leave it unset for this deployment. An override below 900,000 ms can interrupt
source transfer before its progress receipt; do not treat that timeout as proof
that nothing was accepted. Discover the deployed client's actual tool inventory;
engineering-capable clients also provide gr_freeze_source.
Development checks include npm test here and, in the client package,
npm run typecheck && npm test. Deployment qualification must additionally
exercise real OMP tool discovery, native bridge authentication, and completed
image delivery to the model; source/config preparation tests are not that proof.
The adapter exposes the following configuration schema fields under an agent's adapter configuration:
command(string): Path to the OMP executable. Default:omp.model(string): Default model selector (e.g.,anthropic/claude-3-7-sonnet,openai/gpt-4o).thinking(string): Reasoning level (off,minimal,low,medium,high,xhigh,max,auto).printThoughts(boolean): Stream thinking blocks into the Paperclip transcript (--print-thoughts). Default:true;falsepasses--hide-thinking. Thinking only appears when the selected model actually emits reasoning deltas.profile(string): Named OMP profile to activate (OMP_PROFILE).
cwd(string): Working directory override. Defaults to the Paperclip issue workspace.addDirs(textarea): Additional directory paths passed via repeatable--add-dirflags.sessionDir(string): Directory for storing OMP session state.noSession(boolean): Set true to disable session resumption (ephemeral execution).allowHome(boolean): Pass--allow-homeif working directly in the user home directory.
tools(string): Comma-separated list of enabled tool names.noTools(boolean): Disable default OMP tools.skills(string): Comma-separated list of explicit skill names to enable.noSkills(boolean): Disable built-in skills discovery.noRules(boolean): Skip loadingRULES.md.approvalMode(select): Tool execution approval policy (yolo,write,always-ask). Default:yolo, always passed as--approval-modeso the run never depends ontools.approvalModein the OMP config.
timeoutSec(number): Maximum wall-clock execution time in seconds before SIGINT. Default:43200(12 hours).graceSec(number): Grace period before SIGKILL after SIGINT. Default:20.configFiles(textarea): Customconfig.ymloverlay paths.extensions(textarea): Paths to custom OMP extensions.pluginDirs(textarea): Paths to plugin directories.hooks(textarea): Paths to hook files.extraArgs(textarea): Raw additional flags passed to the OMP CLI.
This optional mode does not require Paperclip Cloud and does not manufacture
a managed OAuth grant. It requires a Linux controller, an isolated remote native
issue run with a GitHub policy capability, and git, gh and Node installed in
the runner (/usr/bin/git, /usr/bin/gh, and trusted Node on PATH).
Repository credential admission additionally requires trusted native workspace
metadata identifying isolated_workspace, git_worktree and a canonical
execution-workspace UUID. A remote container alone is insufficient: a disabled
instance enableIsolatedWorkspaces flag can otherwise silently leave the
durable checkout shared despite an isolated project policy. Enable that flag,
keep enableIsolatedWorkspacesByDefault:false when non-repository projects
should retain their existing behavior, and configure the engineering project's
enabled policy with defaultMode:"isolated_workspace" and
workspaceStrategy:{type:"git_worktree",baseRef:"origin/main"}. Shared,
missing or inconsistent workspace metadata fails before GitHub credential use;
there is no shared-checkout fallback.
Store the PAT once as an organization secret named PAPERCLIP_GITHUB_TOKEN.
In the authorized project's Configuration → Env, add GR_GITHUB_TOKEN,
choose Organization secret, then Create new secret…. Enter the shared
secret name and PAT, choose Create & bind, then Save changes. Other
approved projects can select that existing secret instead of copying its value.
The stored secret is organization-level; its environment binding is per-project.
Never paste a PAT into a plain project variable, agent configuration, repository
URL, this policy, or an operator's inherited environment.
The native secret name also supports Paperclip's host-side private checkout when no managed GitHub identity is configured. That company-level facility is separate from exporting the token to a runner.
Set the host environment
PAPERCLIP_OMP_GITHUB_PAT_POLICY=/etc/gr/github/policy.json and mount a regular,
operator-owned policy read-only, without group/other write permission:
{
"schemaVersion": 2,
"companies": {
"11111111-1111-4111-8111-111111111111": {
"projects": {
"33333333-3333-4333-8333-333333333333": {
"repository": "example-org/project",
"secretId": "44444444-4444-4444-8444-444444444444",
"agents": ["22222222-2222-4222-8222-222222222222"]
}
}
}
}
}The native workspace must identify the exact authorized project and HTTPS
github.com repository. The resolved GR_GITHUB_TOKEN must carry one successful
native binding for the policy's secret UUID. Missing, substituted or ambiguous
provenance fails closed before contacting GitHub. Before export, the adapter
also checks native run policy: only an eligible run with absent managed
identity can use this mode. Unavailable, revoked, low-trust or already-configured
managed identity is not a fallback opportunity. Schema 1 policies are rejected;
operators must migrate all grants before deploying this release.
GitHub /user and repository responses establish the real token owner's
identity and repository visibility; actual push/PR operations still enforce
GitHub permissions. Token-free run-local launchers clear ambient credentials,
use a URL-scoped HTTPS Git helper, and set the verified owner's noreply Git
identity. Local credential-free Git archive operations remain usable.
Host prerequisite: secret provenance must describe the effective environment,
not every earlier layer. Paperclip 2026.1012.0 concatenates manifests even when a
later plain value overrides a secret reference. The GR deployment applies its
native secret-provenance.patch: environment < agent < project < routine <
trusted projection; an override invalidates the earlier binding, even with equal
bytes. Do not deploy this mode on an unqualified host with stale manifests.
The same host patch makes strict secret mode recognize the GitHub token variable
names without treating MAX_TOKENS or TOKEN_BUDGET as credentials.
Grant only selected repositories and necessary Contents/PR permissions, with expiry. A shared fine-grained PAT can cover multiple selected repositories under one resource owner. Every credential-bearing runner can technically access that entire selected set; project admission does not narrow GitHub's token scope. GitHub permissions and branch protection are the authority ceiling: this is not an egress sandbox, does not create a bot identity, and does not prohibit direct branch writes by itself. Bind it only to approved engineering projects. Public-repository readability is not proof of a selected write grant. Do not run untrusted repository scripts in this credential-bearing runner; send committed source to the credential-free Slurm test environment. Stop affected runs before rotating/rebinding/revoking access, then revoke the old PAT at GitHub. The policy pins a secret UUID, not a binding UUID or binding scope: the same approved secret bound at another native layer can still satisfy admission. Removing only the project reference is therefore not a complete revocation procedure; remove the operator grant to deny future launches. Admission is checked at run start, not a replacement for provider revocation.
The POSIX test suite exercises actual Git commits, credential-helper host scoping, login-shell startup and anonymous source export, plus denied actor, repository and native-policy cases. Real native GitHub push/PR qualification requires an owner-provided selected-repository PAT; fixture tests do not prove that external authorization.
git clone https://github.com/GenRobo/paperclip-omp-adapter.git
cd paperclip-omp-adapter
npm ci
npm run typecheck
npm testPack the local repository and install the tarball directly into your Paperclip instance:
TARBALL=$(npm pack)
paperclipai adapter install --payload-json "{\"packageName\":\"$PWD/$TARBALL\",\"version\":\"0.11.4\"}" --jsonUse Node 24 (at least 24.11.0; deployment toolchain 24.21.0). Keep @paperclipai/adapter-utils and @paperclipai/shared pinned together to the deployed Paperclip contract. After changing package identity/version/dependencies, regenerate and commit the lockfile with the supported toolchain before npm ci or publication:
npm install --package-lock-only --ignore-scripts
npm ci --ignore-scripts
npm run typecheck
npm test
npm run pack:checkThe smoke suite exercises the public server adapter's denied local/missing/malformed targets, immutable host policy, explicit model catalog, and remote runner failure propagation without local fallback. Existing policy-off execution tests cover the normal library behavior. Remote deployment acceptance additionally needs a real SSH/sandbox integration run; the smoke runner failure fixture does not claim a successful remote execution.
- Bound adapter-owned persisted result metadata to 48 KiB UTF-8 without changing canonical streamed logs, usage/session accounting, deadline classification, or retry policy.
- Replace embedded image/resource bytes with explicit omissions; retain useful operation/tool identifiers, incomplete-inventory markers, and the native run-log locator instead of manufacturing complete receipts.
- Add large image-bearing execution, retained control evidence, multibyte/escaped JSON bound, and ordinary small-result regressions.
- Honor explicit terminal OMP deadline causes independently of the last assistant stop reason; report a real unsuccessful adapter result without confusing the inner deadline with the outer watchdog or a provider failure.
- Preserve partial usage and tool/artifact evidence, suppress stale final summaries, and render the deadline as a transcript error.
- Add regressions for deadlines during tools, zero-exit deadline events, later real success, ordinary yields, tool-local timeouts, and misleading timeout text.
- Reuse native remote workspace shaping for OMP directory arguments and runtime prompt context. Reproduced the previous failure in a real runner: an unstaged host project path was passed through
--add-dir, and the agent's Bash tool rejected that working directory. - Resolve remote directory arguments with POSIX semantics and constrain explicit
addDirsto the synchronized workspace. - Added path projection/escape regression coverage and removed an incidental flag-presence test. POSIX smoke, all 17 GitHub/MCP tests, typecheck and package validation passed; deployment-specific inference remains a separate acceptance check.
- Reject repository PAT admission unless native per-issue Git-worktree identity is present; a remote sandbox no longer masks a shared durable checkout.
- Add a regression for shared/inconsistent/missing workspace authority, reproduced against 0.11.0 before the fix.
- Replaced agent-wide PAT grants with schema-2 project/repository/secret/agent admission.
- Required native secret-binding provenance before PAT export; rejected missing, substituted and ambiguous bindings.
- Documented shared organization-secret setup and the selected-repository authority ceiling.
- Qualified POSIX adapter smoke, native-policy denial, and real Git identity/credential-helper/source-export behavior; external push/PR proof remains deployment-specific.
- Added opt-in host-owned company/agent/repository PAT grants, native trust-policy preflight and verified GitHub-owner identity without Paperclip Cloud.
- Added isolated token-free Git/gh launchers; no ambient credential fallback or PAT-bearing installation/version probes.
- Increased the persistent workload MCP deadline to support bounded engineering source transfers.
- Materialized native runtime/project MCP and issue-scoped workload tools in isolated OMP configuration.
- Preserved native identity, deduplicated matching dual delivery, and rejected conflicting authority, inherited untrusted MCP configuration and project overrides.
- Routed remote native MCP through exact host-owned grants with rebased bridge credentials; required the qualified patched host SDK.
- Exercised a real Paperclip artist on the remote OMP runner, including live Slurm Blender edits, image delivery, saved artifacts and native task review.
- Adopted
@genrobo/paperclip-omp-adapterand the GenRobo fork metadata; retained the original MIT license and attribution. - Pinned Paperclip helper/shared contracts to 2026.1012.0.
- Added operator-owned remote-only execution/environment enforcement and non-spawning model/config/quota discovery on the hub.
- Reused the host's explicit model catalog contract; retained
omp_localand existing policy-off behavior.
MIT