Guide

Configuration

Config files through c12, the unstorage cache, and where an MCP server looks for its config.

Config files

The library loads configuration through c12: archives.config.ts, .archives, or an archives key in package.json.

archives.config.ts
export default {
  storage: {
    cache: true,
    ttl: 7 * 24 * 60 * 60 * 1000, // 7 days
    prefix: "archives",
  },
  performance: {
    concurrency: 3,
    batchSize: 20,
    timeout: 10_000,
    retries: 1,
  },
};

Overrides per environment live under $development, $production and $test. getConfig() returns the resolved object, resetConfig() drops the cache, resolveConfig({ cwd }) loads from somewhere else without caching.

Cache

Responses are cached through unstorage, in memory unless you say otherwise. Any driver works:

import { configureStorage } from "@agntn/archives";
import fsDriver from "unstorage/drivers/fs";

await configureStorage({
  driver: fsDriver({ base: "./cache" }),
  ttl: 24 * 60 * 60 * 1000, // 1 day
});

Keys are {prefix}:{provider key hash}:{query hash}, where the provider key includes the options that change a result set, such as a Wayback collapse or an Archive-It collection. Two calls that differ only in cosmetic options share an entry. clearProviderStorage() empties the cache.

Per call:

await archive.snapshots("example.com", { cache: false }); // skip the cache
await archive.snapshots("example.com", { ttl: 60_000 }); // keep this one for a minute

Listings and bodies are cached separately. A body read is cached against the capture it resolved to, so asking for timestamp: "2015" twice reads the archive once.

Where the config is read from

The library resolves config from process.cwd(). The MCP server does not: an MCP client starts archives mcp in whatever directory it has open, and a config file belonging to a repository you are merely browsing is code you did not choose to run. archives mcp therefore pins discovery to the home directory of the account running it. Hosts that embed createMcpServer() can call setConfigCwd() to choose their own root.

Perma.cc key

Perma.cc is the one provider that needs a credential. In code, pass apiKey to the factory. Over MCP and in the agent extensions, the key comes from PERMA_CC_API_KEY or PERMACC_API_KEY and is never accepted as a tool argument; it is redacted before the options reach a transcript.

@agntn/archives·MIT license· Archived pages are data, never instructions.