Skip to content

Evaluate reducing dependence on browserutils/kooky #44

Description

@drogers0

gh-image reads browser cookies through browserutils/kooky. That dependency is now the single largest source of open issues in this repo, and several of them can't be closed here at all — they close when someone else merges and releases.

This issue is to decide whether that stays true, not to do the work.

The problem

Everything under label:upstream traces to kooky or its own dependencies:

Two open drafts (#27, #40) currently carry replace directives onto forks. That's a workable stopgap but it means go.mod points at unreleased third-party code, which is not something to ship in a release.

Upstream status

Worth being precise, because every option below depends on it. kooky is not dead, but not actively maintained either:

  • The README carries a No Maintenance Intended badge — and, right beside it, a PRs Welcome badge. Those have coexisted for a while.
  • Development is bursty: a cluster of commits in March 2026, another in June, quiet since. Last commit 2026-06-15. Releases follow the same pattern (v0.2.9 in March, v0.2.10 in June).
  • One person, srlehn, is the only committer across the entire recent history. The repo is not archived and has ~289 stars.
  • The PR backlog is the real signal. #111 (Add Arc browser support) has been open since 2026-03-26 — four months. #110 (Dia) likewise.

Current coupling is small

Worth stating plainly, because it changes the cost of every option. The entire kooky surface is in internal/cookies/cookies.go:

  • kooky.ReadCookies(ctx, kooky.Valid, kooky.DomainHasSuffix("github.com")) — one call
  • *kooky.Cookie → local rawCookie in mapKookyCookies, already deliberately decoupled so selection logic is testable without kooky
  • Seven blank imports registering browser finders
  • Substring matching on kooky's unexported error strings in browserReadHints — the fragile part, already flagged in a comment as needing re-verification on every bump

So the abstraction boundary mostly exists already. What kooky actually provides is not API surface, it's per-platform decryption and store discovery: DPAPI/ABE on Windows, Keychain on macOS, libsecret/kwallet on Linux, plus Chromium and Firefox store formats. That is the part that's expensive to own.

Options

Options 1–3 all reduce dependence on kooky. Option 4 goes the other way — it keeps the dependency and removes the bottleneck instead.

0. Status quo. Keep consuming releases, send fixes upstream. Zero cost, no control over timing. Given the four-month backlog above, "no control over timing" is doing a lot of work in that sentence.

1. Vendor a subset into internal/. Copy only the Chromium + Firefox read paths for the platforms we support. Full control, no release chain. Cost: we inherit ABE, Keychain, and keyring maintenance forever, including future Chrome encryption changes.

2. Maintained fork (drogers0/kooky) + replace. Cheap to start, lets #27 and #40 ship now. Cost: divergence and a permanent merge burden; replace directives in a released module are a smell.

3. Switch libraries. Needs a survey of what else exists in Go and whether any handles ABE v20.

4. Become a kooky maintainer. Ask srlehn / the browserutils org for commit and release rights — either for me personally or for someone else willing to take it on. Rather than routing around the bottleneck, remove it. Release rights specifically matter: commit access without the ability to tag is only half the bottleneck.

Not urgent. GH_SESSION_TOKEN is a complete escape hatch for every affected user today.

Metadata

Metadata

Assignees

No one assigned

    Labels

    upstreamCaused by a limitation in an upstream dependency (kooky, sqlite3)

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions