Imported from dorkitude/skimmer (
AGENTS.md). Install upstream withnpx skills add dorkitude/skimmer. Copyright stays with the author.
AGENTS.md
Guidance for coding agents (Claude Code, Codex, ...) working on skimmer.
CLAUDE.md is a symlink to this file.
Project overview
skimmer is a Go CLI (Cobra + Viper) that saves tokens: it splits pages, files, or lists into chunks/items, asks Jev one yes/no question per chunk ("does this help with the goal?"), and prints only what passes. The chunk filter and Jev client started in webctl; keep the two consistent where it makes sense.
Build & test
go build -o skimmer .
go vet ./... && go test ./...
gofmt -l . # must print nothing (CI enforces it)
Tests never call the real Jev API: internal/jev/judge_test.go uses an
httptest fake. For a manual end-to-end check, run ./skimmer auth status
and then a real skimmer skim ... -g ....
Layout
main.go: entry pointcmd/: Cobra commands (skim,filter,auth,prompts) and the version stringinternal/jev/: System One client;judge.goholds the batching (token budget, parallel batches, split-on-too-large, unjudged items kept)internal/chunk/: line-aware chunker with overlapinternal/fetch/: page fetching and HTML/PDF to text (from webctl)internal/skim/: the skim pipeline (load, chunk, judge, select)internal/items/: parsing and re-encoding lists (JSON, JSONL, lines)internal/config/: precedence of flags, env,.env, and~/.config/skimmer/config.yamlinternal/prompts/+prompts/<kind>/*.md: embedded prompt templates
Rules
- Never print or log the API key.
auth statusshows onlyconfig.Mask. Never commit keys or.envfiles. - When a chunk or item gets no verdict, keep it. A Jev failure must never silently drop content.
- Keep
--jsonoutput stable; agents parse it. - A new flag or behavior updates the README's Usage section and
CHANGELOG.md. - Commits carry no AI attribution (no
Co-Authored-Bytrailers or "Generated with" lines).
Release strategy
Versions
- Semver with large patch numbers, as in cfctl:
0.1.100,0.1.101, ... Bump the patch for each release and the minor for big shifts. Never zero-pad (0.1.001is not valid semver: Go and GoReleaser reject it). - The tag is the version with a
v:0.1.100→v0.1.100. - The binary learns its version from the tag. GoReleaser sets
-X github.com/dorkitude/skimmer/cmd.Version=X.Y.Z(every channel butgo installships its binaries), andgo install ...@vX.Y.Zbuilds read it from the module info. There is no version constant to bump.
Channels
| Channel | Source of truth | Updated by |
|---|---|---|
| GitHub release (macOS/Linux tarballs, Windows zips, .deb, .rpm, checksums) | .goreleaser.yaml |
release workflow, on tag push |
apt (dorkitude.github.io/skimmer-apt, signed) |
scripts/publish-apt.sh |
release workflow, on tag push |
Homebrew (dorkitude/homebrew-tap, Casks/skimmer.rb: the universal macOS binary, or the Linux one per arch; no build, so no Xcode Command Line Tools needed) |
scripts/publish-packages.sh |
maintainer, after the release exists |
Scoop (dorkitude/scoop-bucket, skimmer.json) |
scripts/publish-packages.sh |
maintainer, after the release exists |
go install github.com/dorkitude/skimmer@latest |
the tag | automatic |
The tap and bucket are shared with other dorkitude tools, so they are updated
from the maintainer's machine with their own gh login, not from CI.
Secrets (on dorkitude/skimmer)
APT_GPG_PRIVATE_KEY: the apt repo signing key (RSA 4096, fingerprint241D677482BEC395E187B4693D1A4098CB4041F2). This secret is its only copy. If it's lost, generate a new key, set the secret, and tell users to re-importkey.gpg.APT_DEPLOY_KEY: SSH key for a write deploy key ondorkitude/skimmer-aptonly.MACOS_SIGN_P12,MACOS_SIGN_PASSWORD: the Developer ID Application certificate (base64 .p12, that identity only) and its password.MACOS_NOTARY_KEY,MACOS_NOTARY_KEY_ID,MACOS_NOTARY_ISSUER_ID: an App Store Connect API key ("goreleaser notarization", Developer role; base64 .p8). GoReleaser signs and notarizes every macOS binary with these; without them it skips signing. The same five secrets are set on cfctl, dhctl, tsctl, deadlore and EnronQA-cli.
Cutting a release
Agents create or push tags only when the maintainer explicitly asks for a release.
- On
main, with CI green: move theCHANGELOG.mdentries from[Unreleased]into## [X.Y.Z] - YYYY-MM-DD, then commit and push. - Tag and push:
git tag -a vX.Y.Z -m "vX.Y.Z: short summary" git push origin vX.Y.Z - Watch it:
gh run watch -R dorkitude/skimmer. The workflow runs vet and tests, then GoReleaser, then the apt publish. - Add the notes:
gh release edit vX.Y.Z -R dorkitude/skimmer --notes "<from CHANGELOG>". - Publish Homebrew and Scoop:
scripts/publish-packages.sh vX.Y.Z(DRY_RUN=1to preview). It's idempotent. Don't skip this. The tag push updates only GitHub and apt. Without this step,brewandscoopusers stay on the previous version and nothing fails to warn you. - Verify each channel reports
X.Y.Z:go install github.com/dorkitude/skimmer@vX.Y.Z && skimmer --version brew update && brew install dorkitude/tap/skimmer && skimmer --version # or brew upgrade sudo apt update && sudo apt install skimmer && skimmer --version scoop update && scoop install dorkitude/skimmer # on Windows
If the workflow fails after GoReleaser has published, fix the problem, delete
the release and tag (gh release delete vX.Y.Z --cleanup-tag), and tag again.
Don't reuse a version once any channel has published it; bump the patch
instead.
