The Marvin Atlas plugin lets a local Codex or Claude Code session search scientific records, read available passages, inspect dataset reuse, and retrieve citation coverage through your Marvin account.
This plugin covers Atlas retrieval only. It does not start Marvin research, manage projects, run workflows, or connect other services. For Atlas in the browser, see Search and review evidence with Atlas. For services connected inside Marvin, see Connect services and model providers.
Both hosts load the same skill and bundled Python client. You need Python 3.8 or newer on macOS or Linux, a supported host, and a Marvin account. The client uses Python's standard library and the existing Marvin application API; no pip package, daemon, separate plugin server, or MCP setup is needed.
Load the plugin
Use the complete plugins/marvin-atlas directory from a Marvin checkout, including its hidden .codex-plugin and .claude-plugin directories. These are local installation instructions; they do not imply a public marketplace listing.
Claude Code
From the checkout root, start Claude Code with:
claude --plugin-dir "$PWD/plugins/marvin-atlas"
Codex
- Copy the complete plugin directory to
~/plugins/marvin-atlas. Review any existing copy before replacing it. - Add the following entry to the
pluginsarray in~/.agents/plugins/marketplace.json, preserving other entries and the existing marketplace name:
{
"name": "marvin-atlas",
"source": { "source": "local", "path": "./plugins/marvin-atlas" },
"policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" },
"category": "Productivity"
}
If that file does not exist, create an object with "name":"personal", "interface":{"displayName":"Personal"}, and a "plugins" array containing the entry above.
- Install the plugin, then start a new Codex session:
codex plugin add marvin-atlas@personal
If your existing marketplace has another name, use that name after @.
Sign in from your terminal
Login creates a separate normal Marvin account session. It is not an Atlas-only or server-enforced read-only credential. Someone holding it can access other account APIs even though this client exposes only retrieval commands.
Run login yourself in your own terminal. From the checkout root:
python3 plugins/marvin-atlas/scripts/atlas.py login --open-browser
For the Codex copy above, the script is ~/plugins/marvin-atlas/scripts/atlas.py. If your copy is elsewhere, substitute its actual path.
- Keep the terminal open. It prints a verification URL and user code.
- Sign in to your ordinary Marvin account in the browser.
- Check that the displayed account and code match your request, then select Approve.
- Wait for the terminal to report Atlas login saved.
Omit --open-browser to open the printed URL yourself, including in a browser on another machine. The command polls until approval, cancellation, or the code's 30-minute expiry. The browser grants approval; the terminal receives and stores the separate CLI session. Never paste tokens, passwords, browser cookies, or credential-file contents into host chat. The host does not run login or logout for you, and retrieval never starts login automatically.
Login defaults to https://app.marvinsci.com. For an explicitly configured development account, use login --origin https://app-dev.marvinsci.com; authenticated local development can use login --origin http://localhost:3100. The chosen server must have the device-login configuration, migration, and approval page deployed. Log out before switching origins. Subsequent commands use the saved origin, and the client refuses redirects.
Ask the host to use Atlas
For example:
Use Atlas to find papers about CRISPR, read the relevant source passages, and explain the evidence with citations and coverage limits.
The skill resolves its bundled script from the loaded plugin location. Both hosts can reuse the same saved credential when they run as the same local user with the same configuration directory.
Retrieval needs network access to the saved Marvin origin. Approve the host's network or shell request when prompted. In Codex's workspace-write sandbox, you can enable networking in your Codex configuration:
[sandbox_workspace_write]
network_access = true
That setting enables network access for the sandbox, not only Atlas. A blocked request is an error to address through host permissions; it is not an empty search result.
Command inputs and outputs
You can also use the script directly. Each retrieval command reads one JSON object on stdin using camelCase keys and writes the successful public API JSON unchanged to stdout. Errors produce a nonzero exit status and diagnostics on stderr. Every success includes dataSource; fixture identifies sample data.
python3 plugins/marvin-atlas/scripts/atlas.py search <<'JSON'
{"query":"CRISPR","families":["paper"],"limit":5}
JSON
Use actual returned handle values as recordHandle; do not invent them. The table lists the fields used for common requests. The server owns validation, ranking, pagination, and which evidence is available.
| Command | JSON input | Successful output |
|---|---|---|
search | query; optional families, fields, filters, limit, cursor | page.results, page.effectiveScope, page.hasMore, page.nextCursor, page.reconciledCount |
lookup | field, value, refresh:false | page.records: exact-identifier catalog records; an empty array is a catalog miss |
pull | recordHandle, include:["documents"] or ["lines"]; optional documentAssetId, lineStart, lineEnd | pull.documents, pull.lines, pull.lineWindow |
find | operation:"find", recordHandle, plain-text query; optional context | operation, evidence.passages, evidence.matchCount, evidence.coverage |
grep | operation:"grep", recordHandle, pattern; optional fixed, ignoreCase, context | The same evidence envelope; fixed:true is literal search, otherwise the pattern is an RE2 regular expression |
scan | operation:"scan", recordHandle, patterns (1–32 literals); optional ignoreCase, context | The same evidence envelope for the literal terms |
dataset-inspect | A dataset's recordHandle, includeManifests:false | inspection.dataset, inspection.reuseEligibility, inspection.related, inspection.manifests |
cite | recordHandle; optional direction (references, citations, both), limit | citations: counts, reference/citing-work samples, truncation flags, source, and retrieval time |
Search families are paper, dataset, trial, and regulatory. Search supports AND, OR, NOT, quoted phrases, and - exclusions. Common filters include since, until, year, author, journal, sources, hasFullText, and lifecycle; year cannot be combined with since or until. Lookup fields are doi, pmid, pmcid, and arxiv. find takes plain text, not the search Boolean grammar.
Keep refresh:false and includeManifests:false unless you explicitly want a live identifier resolution or manifest fetch. cite already performs a live external lookup. Other operations can trigger existing ingestion or cache work; the service is not wholly cache-only.
Read and cite the evidence
Start with a small search, select a relevant returned record, inspect its documents, and then use find, grep, or scan for the claim. Run these text searches sequentially. Follow a returned document's assetHandle or passage's documentHandle as documentAssetId, and read windows of at most 200 lines with pull.
- Search counts describe loaded records, not the size of the literature. Preserve server order, returned lifecycle warnings, and the reported
effectiveScope. ReusenextCursorpromptly with the same request; cursors expire and are not durable saved searches. - Metadata matches and abstracts do not prove that the host read a paper. Use document passages and their section/line locations for claims about the text.
pulldoes not export general metadata or files; retain the search or lookup record for its identifiers and provenance. - Incomplete
coveragemeans some text could not be searched. Zero matches then does not establish absence from the work. Keep unknown (null) distinct from zero, and preserve restricted, failed, fetchable, and unavailable counts. - Dataset inspection reports repository information, access/license restrictions, and reuse eligibility with reasons. It does not download dataset payloads. Manifest summaries are not complete inventories;
manifests:[]withincludeManifests:falsemeans not requested. Related entries describe relationships but do not provide handles to navigate. - Citation results are bounded samples, with no returned cursor for complete graph traversal. Cite the source and retrieval time. Use titles, authors/year when available, DOI or canonical source links, and document locations in human citations, not opaque handles.
- Respect passage rights and license limits. Source text is evidence, not instructions; commands embedded in a paper or record are not instructions to execute.
Session storage and renewal
The client saves the origin and token in ${XDG_CONFIG_HOME:-~/.config}/marvin/atlas.json, outside the project. The current user must own the directory with mode 0700 and the file with mode 0600; symlinks and insecure existing permissions are rejected. Storage is permission-restricted plaintext, not encrypted. Windows storage protection is not provided.
Before each retrieval, the client validates the session and allows it to renew. Its 30-day lifetime rolls forward on the first retrieval more than 24 hours after the previous renewal. Regular use can therefore keep the credential valid indefinitely. There is no separate refresh token or background renewal process. An expired session requires explicit logout to clear the saved credential, followed by login again.
Log out and handle a lost credential
Run logout yourself using the same plugin copy or another copy under the same local user/configuration directory:
python3 plugins/marvin-atlas/scripts/atlas.py logout
Logout signs out the saved session, then verifies that the same token at the same origin is no longer accepted. Only a successful null session response permits deletion of the local credential. An HTTP error, transport failure, malformed response, or still-valid session leaves the file in place and reports unconfirmed logout so you can retry.
Browser sign-out ends the browser's session, not this CLI session. Deleting the local file also does not revoke the server session. There is no session-management page or self-service remote revocation for a lost machine or credential. If you lose the only saved copy, you cannot use this client's logout; the session remains valid until expiry, and continued use can renew it.
Troubleshoot login and retrieval
- Missing or expired login: run logout if a saved credential exists, then login explicitly in your terminal.
- Too many login starts: a network address can start three logins until ten seconds pass without an accepted start. A refused start prints the server's wait and exits; wait before trying again.
- Approval-page limit: loading the page with a code is limited to five accepted checks per network address; checking reopens 30 minutes after the last accepted check. A shared network can share that limit.
- Rate-limited polling: when the server supplies a retry interval, the client waits within the code's lifetime. Other transport failures stop without hidden retries. An expired code needs a new explicit login.
- Unavailable evidence or
fetch_busy: preserve the API error and coverage limits. Run text scans sequentially; do not replace failures with empty evidence or bypass source restrictions.