skills/paperclip/references/installation.md
Paperclip is distributed by GXL (https://paperclip.gxl.ai). There are two ways to reach it: a local
CLI, or a hosted MCP server. The CLI is the richer surface — the virtual filesystem, grep, scan,
sql, repos, and the clipboard all live there — so prefer it unless you are on Windows or cannot
install software.
Commands here were exercised against paperclip 0.7.14 and 0.7.15 on macOS (darwin 25.5.0). Per-client MCP
configuration is transcribed from https://paperclip.gxl.ai/install and is not verified here.
curl -fsSL https://paperclip.gxl.ai/install.sh | bash
This is the vendor's supported install path, and it executes a remotely-fetched script with the user's privileges — there is no published checksum or signature to verify it against. Get the user's go-ahead before running it, and read it first if they want that:
curl -fsSL https://paperclip.gxl.ai/install.sh | less
The same applies after install: the CLI self-updates opportunistically, so the code that runs can
change between invocations. paperclip --version tells you what actually ran.
This drops a self-contained CLI in ~/.paperclip/ and a launcher on your PATH (on macOS,
~/.local/bin/paperclip). It bundles its own interpreter and dependencies under ~/.paperclip/lib/,
so it will not disturb any project virtualenv.
If paperclip is not found afterwards, ~/.local/bin is not on your PATH:
export PATH="$HOME/.local/bin:$PATH" # add to ~/.zshrc or ~/.bashrc to persist
Use this when you want the package inside an environment you control — for example to import the Python SDK alongside your own code.
pip install https://paperclip.gxl.ai/paperclip.whl
paperclip setup # = paperclip login + paperclip install
Two caveats. The wheel URL is unversioned, so it resolves to whatever is current — there is no pinned,
hash-verified release to install instead, and gxl-paperclip is not published on PyPI. And the
unrelated paperclip package is on PyPI: pip install paperclip installs the wrong software.
Always install from the full URL.
The native installer does not support Windows. Use Claude Desktop, claude.ai, or another MCP client pointed at the hosted server (below).
Use an API key from the environment. Treat browser OAuth as the fallback. A key is non-interactive, works headless and in CI, is independently revocable, and never blocks on a browser.
Verified against cli/app.py and client/client.py in 0.7.14:
| Priority | Source | Notes |
|---|---|---|
| 1 | --api-key flag | Works, but exposed in ps and shell history — avoid |
| 2 | PAPERCLIP_API_KEY env var | Preferred. Click reads it via the flag's envvar binding |
| 3 | ~/.paperclip/credentials.json | Written by paperclip login |
A key in the environment short-circuits OAuth completely: _ensure_auth() returns immediately, so
no browser opens and a stored login is not consulted even when one exists. That also means an exported
key silently overrides the account you logged in as — paperclip config will show
Auth: ✓ API key (env) instead of your email.
The Python SDK's from_env() uses a similar order with one extra step in front:
PAPERCLIP_BEARER_TOKEN → PAPERCLIP_API_KEY → ~/.paperclip/credentials.json.
.env — the default pathCreate a key at https://paperclip.gxl.ai/keys (they look like gxl_...) and put it in the project's
.env:
# .env — add to .gitignore
PAPERCLIP_API_KEY=gxl_...
Paperclip has no dotenv support. There is no python-dotenv dependency anywhere in the package;
config.py reads os.getenv("PAPERCLIP_API_KEY", "") and nothing more. A .env sitting next to the
command is invisible to it, so the file has to be exported into the environment first.
Use this exact form, in the directory holding .env:
[ -f .env ] && { set -a; . ./.env; set +a; }; paperclip config
set -a marks subsequent assignments for export, . sources the file, set +a restores normal
behavior.
Two things about this form are not stylistic:
The [ -f .env ] guard is mandatory. A bare . ./.env against a missing file is a fatal error
in a POSIX shell — it terminates the shell, so everything after the ; is silently discarded:
# WRONG — unguarded, run in a directory with no .env
sh -c 'set -a; . ./.env 2>/dev/null; set +a; echo survived; paperclip config'
# (no output at all — "survived" never prints, paperclip never runs)
Guarded, it is safe in all four states, each verified: .env present, .env absent, key already
ambient in the environment, and under both sh and bash.
Every invocation needs it. Environment variables do not persist between separate shell
invocations, which is exactly how an agent runs commands — one call per tool use. Export in one call
and run paperclip in the next and the key is gone, and Paperclip does not complain: it silently
falls back to stored OAuth, a different identity:
# WRONG — split across two tool calls
# call 1
set -a; . ./.env; set +a
# call 2
paperclip config # → Auth: ✓ [email protected] ← the key never loaded
# RIGHT — one self-contained call
[ -f .env ] && { set -a; . ./.env; set +a; }; paperclip config # → Auth: ✓ API key (env)
If the key is already exported — CI secrets, a shell profile, direnv — the guard is a harmless
no-op and no prefix is needed.
export PAPERCLIP_API_KEY='gxl_...' # ad hoc, current shell only
Values containing spaces must be quoted inside .env or the shell will try to run them; gxl_ keys
never contain spaces, so this only matters for other variables sharing the file.
Over HTTP the key travels as an X-API-Key header. Never echo it, never commit .env, and never
include it in a file you paperclip upload.
--api-key flagpaperclip --api-key "$PAPERCLIP_API_KEY" search -s pmc "query" -n 5
Same mechanism, worse hygiene: the argument shows up in ps output and shell history. Use it only to
run two identities in one shell where exporting would collide.
paperclip login opens a browser and waits. An agent cannot complete it; ask the user to run it and
report back. With no TTY it exits cleanly rather than hanging:
[error] Not authenticated. Run: paperclip login
Or use --api-key flag or PAPERCLIP_API_KEY env var
For interactive use on a machine with a browser and no key available:
paperclip login # opens a browser
paperclip logout # sign out, remove stored credentials
Credentials land in ~/.paperclip/credentials.json. Sign-in is also triggered automatically on first
use — which is exactly the blocking behavior an API key avoids, so set the key before the first call
in any non-interactive context.
paperclip config
With a key exported, a healthy install prints:
Paperclip
Server: https://paperclip.gxl.ai
(default)
Auth: ✓ API key (env)
Config: /Users/you/.paperclip
Health: ✓ server reachable
Sources: PubMed Central, bioRxiv, medRxiv, arXiv
Under OAuth the Auth line shows your email address instead.
Auth: ✓ means a key is present, not that it is valid. A junk key produces the identical line,
and Health: ✓ server reachable is an unauthenticated probe. Only a real query proves the credential:
paperclip search -s pmc "CRISPR base editing" -n 3
You should get numbered results ending in a [s_xxxxxxxx] result id. An invalid key instead prints
[error] Authentication failed (API key invalid). and exits 1, which is what to check in a script.
paperclip install writes Paperclip's own skill files into a project so an agent picks them up
without being told.
It is interactive — two prompts, agent and path. Run bare from a tool call it either hangs on a TTY or aborts without writing anything:
Select (e.g. 1,2 or all) [1]: Aborted!
Answer both prompts on stdin. 1 = Claude Code, 2 = Cursor, 3 = Codex; the empty second line
accepts the --dir default:
printf '1\n\n' | paperclip install --dir /path/to/project
# → writes /path/to/project/.claude/skills/paperclip/SKILL.md
Interactively:
paperclip install # prompts for client: Claude Code or Codex
paperclip install --dir ~/work/my-project
Installed skills are tracked in ~/.paperclip/installed_skills.json. This is independent of the
CLI itself — the CLI works fine without it.
Universal endpoint:
https://paperclip.gxl.ai/mcp
claude mcp add --transport http paperclip https://paperclip.gxl.ai/mcp
codex mcp add paperclip --url https://paperclip.gxl.ai/mcp
codex mcp login paperclip
Codex Desktop: Settings → MCP servers → Custom MCP, with an X-API-Key header holding your key.
~/.cursor/mcp.json{
"mcpServers": {
"paperclip": {
"url": "https://paperclip.gxl.ai/mcp",
"type": "http"
}
}
}
Reload the window afterwards.
Customize → Connectors → add a custom connector named "Paperclip" with the MCP URL above. Requires a Pro, Max, Team, or Enterprise plan.
Same URL, configured as a custom MCP server or connector; the first two need the X-API-Key header
added by hand in their config file.
MCP caveat: the MCP surface is a single paperclip tool, not the full CLI. Its own instructions
tell you to run paperclip skill first to load the command reference.
paperclip update # upgrade the CLI and refresh installed agent skills
paperclip uninstall # remove Paperclip from this machine
The CLI also self-updates opportunistically. A command may print
[paperclip] Updated 0.7.14 → v0.7.15 before its output — harmless, but it means a long-running
script can change versions mid-run. Pin behavior by running paperclip update up front if that
matters.
paperclip config # diagnostics (default)
paperclip config --show # current configuration
paperclip config --url http://localhost:8002 # point at a different server
paperclip config --sources pmc --sources fda # persistent default source filter
paperclip config --sources-list
paperclip config --sources-clear
A persistent source filter narrows every subsequent command. If searches come back suspiciously
empty, check paperclip config --sources-list before debugging anything else.
Config lives in ~/.paperclip/:
~/.paperclip/
├── credentials.json OAuth tokens
├── feature_flags.json
├── installed_skills.json
├── repos/ local repo state
├── cache/
└── lib/ bundled interpreter + gxl_paperclip package
| Symptom | Cause and fix |
|---|---|
command not found: paperclip | ~/.local/bin missing from PATH — export it, or re-source your shell rc |
Error: search requires a source flag (-s) | Expected. Every search names a source: -s pmc |
Auth: ✗ in paperclip config | Run paperclip login, or export PAPERCLIP_API_KEY |
| Searches return nothing across sources | A stale source filter — paperclip config --sources-clear |
Corpus grep finds nothing for a rare term | Default scan is time-bounded; retry with --exhaustive |
head on meta.json prints nothing | head/tail handle .lines files; use cat for JSON |
| Version changed mid-session | Opportunistic self-update; re-run paperclip --version |
| MCP client cannot authenticate | Add the X-API-Key header with a key from /keys |