Files
PaperClipAI/packages/adapter-utils
nickyleachandPaperclip a2d014d2ef fix(server): stage a token-free API helper and drop curl from the access note
The generated Paperclip API access note taught agents to put the run
bearer on a curl command line, which any process running as the same
user can read. Every run now gets a paperclip-api helper staged onto
PATH; the helper reads the token from its own environment and sets
the Authorization header itself, so the token never becomes a
command-line argument. The helper rejects an absolute URL, a
scheme-relative path, and a path containing a backslash, and it
verifies the built request resolves to the configured API origin
before sending it.

Staging now runs for every run, not only a managed-GitHub run, so a
host-GitHub run still gets the helper. The note renders only when the
helper was actually staged, checked through the one env field the
staging step itself sets, so the note and the staging step cannot
drift apart.

Co-authored-by: Paperclip <noreply@paperclip.ing>
2026-09-16 09:09:36 +00:00
..

@paperclipai/adapter-utils

Shared utilities for Paperclip adapters: process spawning, environment injection, sandbox/SSH transport, workspace sync, and the round-trip helpers that move code between the local execution-workspace cwd and wherever the agent actually runs.

For the adapter-author guide see docs/adapters/creating-an-adapter.md and the in-repo notes at packages/adapters/AUTHORING.md.

No-remote-git contract

The local execution-workspace cwd is the only persistence boundary across runs. No adapter may depend on a git remote for cross-run state.

Adapters that run the agent on a different host should use the SSH round-trip helpers in src/ssh.ts:

  • prepareWorkspaceForSshExecution({ spec, localDir, remoteDir }) — bundles the local cwd (tracked files, dirty edits, untracked additions, and the git history needed to reconstruct it) to remoteDir before the run starts. Runs with no git remote configured.
  • restoreWorkspaceFromSshExecution({ spec, localDir, remoteDir, ... }) — syncs the remote cwd back into localDir after the run, including any new commits the agent created. Also runs with no git remote configured.

prepareRemoteManagedRuntime in src/remote-managed-runtime.ts wraps both calls for adapters that want a per-run remote workspace and an automatic restoreWorkspace() finally hook.

The invariant is pinned by the no-remote-git contract case in src/ssh-fixture.test.ts, which asserts that a remote-only commit propagates to the local worktree through the prepare → restore round-trip with no git remote configured at any point. Do not regress that test.