After the mocked RPC spawn fails, getQuotaWindows() still calls
readCodexToken(). Use an empty mkdtemp directory for CODEX_HOME for the
duration of the test so we never read ~/.codex/auth.json or call WHAM.
Add a Vitest case that mocks `node:child_process.spawn` so the child
emits `error` (ENOENT) after the constructor attaches listeners.
`getQuotaWindows()` must resolve with `ok: false` instead of leaving an
unhandled `error` event on the process.
Register `packages/adapters/codex-local` in the root Vitest workspace.
Document in DEVELOPING.md that a missing `codex` binary should not take
down the API server during quota polling.
When the `codex` binary is absent from PATH, Node.js emits an `error`
event on the ChildProcess. Because `CodexRpcClient` only subscribed to
`exit` and `data` events, the `error` event was unhandled — causing
Node to throw it as an uncaught exception and crash the server.
Add an `error` handler in the constructor that rejects all pending RPC
requests and clears the queue. This makes a missing `codex` binary a
recoverable condition: `fetchCodexRpcQuota()` rejects, `getQuotaWindows()`
catches the error and returns `{ ok: false }`, and the server stays up.
The fix mirrors the existing pattern in `runChildProcess`
(packages/adapter-utils/src/server-utils.ts) which already handles
`ENOENT` the same way for the main task execution path.
The previous documentation parenthetical "(defaulting to ~/.codex/skills/)"
was misleading because Paperclip almost always sets CODEX_HOME to a
per-company managed home. Update index.ts docs, skills.ts detail string,
and execute.ts inline comment to make the runtime path unambiguous.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The default fallback in ensureCodexSkillsInjected still referenced the
old function name. Updated to use resolveCodexSkillsDir with shared
home as fallback.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The previous commit incorrectly used resolveSharedCodexHomeDir() (~/.codex)
but Codex runs with CODEX_HOME set to a per-company managed home under
~/.paperclip/instances/. Skills injected into ~/.codex/skills/ would not
be discoverable by Codex. Now uses effectiveCodexHome directly.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The Codex adapter was the only one injecting skills into
<cwd>/.agents/skills/, polluting the project's git repo. All other
adapters (Gemini, Cursor, etc.) use a home-based directory. This
changes the Codex adapter to inject into ~/.codex/skills/ (resolved
via resolveSharedCodexHomeDir) to match the established pattern.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Use path.join instead of string concatenation for the auth.json
fallback path in the detail message, ensuring correct path
separators on Windows.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When adapter config has no CODEX_HOME but process.env.CODEX_HOME is
set, readCodexAuthInfo reads from the process env path. The detail
message now uses codexHomeDir() instead of hardcoded "~/.codex" so
the displayed path always matches where credentials were read from.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Show the configured CODEX_HOME path instead of hardcoded ~/.codex
when the email fallback message is displayed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add tests for codex_native_auth_present and codex_openai_api_key_missing
code paths. Also pass adapter-configured CODEX_HOME through to
readCodexAuthInfo so the probe respects per-adapter home directories.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Loading an instructions file is normal, expected behavior — not worth
logging to stdout/stderr on every run. Warning logs for failed reads
are preserved.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The environment test warned about OPENAI_API_KEY being unset even
when Codex was authenticated via `codex auth`. Now checks
~/.codex/auth.json before emitting the warning.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
mkdir -p the CODEX_HOME directory in codex-local adapter and the
agentHome directory in the heartbeat service before passing them to
adapters. This prevents CLI tools from erroring when their home
directory hasn't been created yet. Covers all local adapters that
set AGENT_HOME.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Persist child-process metadata for local adapter runs, keep detached runs alive when their pid still exists, queue a single automatic retry when the pid is confirmed dead, and clear detached warnings when the original run reports activity again.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
Expose adapter-discovered user-installed skills with provenance metadata, share persistent skill snapshot classification across local adapters, and render unmanaged skills as a read-only section in the agent skills UI.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
- Extract all Anthropic credential/API logic into claude-local/src/server/quota.ts
- Extract all OpenAI/WHAM credential/API logic into codex-local/src/server/quota.ts
- Add optional getQuotaWindows() to ServerAdapterModule in adapter-utils
- Rewrite quota-windows.ts as a 29-line thin aggregator with zero provider knowledge
- Wire getQuotaWindows into adapter registry for claude-local and codex-local
- Add 47 unit tests covering toPercent, secondsToWindowLabel, WHAM normalization,
readClaudeToken, readCodexToken, fetchClaudeQuota, fetchCodexQuota, fetchWithTimeout
- Add 8 unit tests covering parseDateRange validation and byProvider pro-rata math
Adding a third provider now requires only touching that provider's adapter.
The $AGENT_HOME environment variable was referenced by skills (e.g.
para-memory-files) but never actually set, causing runtime errors like
"/HEARTBEAT.md: No such file or directory" when agents tried to resolve
paths relative to their home directory.
Add agentHome to the paperclipWorkspace context in the heartbeat service
and propagate it as the AGENT_HOME env var in all local adapters.
Co-Authored-By: Paperclip <noreply@paperclip.ing>
The claude-local, codex-local adapters and the server all resolve a
skills/ directory using __dirname-relative paths that only work inside
the monorepo. When installed from npm the paths point outside the
package and cause ENOENT on readdir/readFile.
- Update both adapter execute.ts files to try a published-path
candidate (../../skills from dist/) before falling back to the
monorepo dev path (../../../../../skills from src/).
- Update server readSkillMarkdown() to try the published path first.
- Add "skills" to the files array in server, claude-local, and
codex-local package.json so npm includes them.
- Update release.sh to copy the repo-root skills/ into each package
before publish, and clean up after.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Rename all workspace packages from @paperclip/* to @paperclipai/* and
the CLI binary from `paperclip` to `paperclipai` in preparation for
npm publishing. Bump CLI version to 0.1.0 and add package metadata
(description, keywords, license, repository, files). Update all
imports, documentation, user-facing messages, and tests accordingly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add instructionsFilePath config to Claude and Codex adapters, allowing
agents to load external instruction files appended to the system prompt.
Claude uses --append-system-prompt-file; Codex prepends file contents
to the prompt. Add docs:dev script for local Mintlify preview.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add AdapterBillingType (api/subscription/unknown) to adapter execution results
so the system can distinguish API-billed vs subscription-billed runs. Enhance
cost service to aggregate subscription vs API run counts and token breakdowns.
Add limit param to heartbeat runs list API and client.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Heartbeat service resolves cwd from task session, project primary
workspace, or agent home directory (~/.paperclip/instances/.../workspaces/).
Adapters receive workspace context and forward it as env vars and
session params. cwd is now optional in adapter config.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>