Shipseal

Configuration

.shipseal/config.json is written by init. Every field is optional.

{
  "version": 1,
  "outputDir": ".shipseal/output",
  "formats": ["og", "github-social", "x", "linkedin"],
  "release": {
    "templates": ["release-hero", "release-highlights", "code-card"],
    "maxHighlights": 4,
    "changelogPath": "CHANGELOG.md",
    "snippet": null
  },
  "milestones": {
    "stars": [100, 250, 500, 1000, 2500, 5000, 10000],
    "downloads": [1000, 10000, 100000, 1000000],
    "contributors": [10, 25, 50, 100]
  },
  "bench": { "file": ".shipseal/bench.json" },
  "copy": { "llm": false, "provider": null, "model": null, "maxRetries": 2 },
  "output": { "imageFormat": "png" },
  "attribution": true
}

Notable fields

  • release.snippet forces the code card to use a specific range, for example "src/index.ts#L10-L24". Otherwise the first fenced code block in your README is used.
  • release.changelogPath defaults to the repository root. In a monorepo, Shipseal also looks under packages/* and apps/*, which is where Changesets writes it.
  • copy.llm is false by default. Everything works without an API key.
  • output.imageFormat defaults to png. WebP is 58 percent smaller, but GitHub social previews accept PNG, JPG and GIF only.
  • attribution adds a small "made with shipseal.dev" mark. Set it to false and it disappears. It is never forced.

Environment variables

VariablePurpose
GITHUB_TOKENOptional. Raises API limits and enables release asset upload
SHIPSEAL_LLM_API_KEYOnly needed when copy.llm is true
Never put keys in config files. They are read from the environment only, and config files are committed.