Rebuild twitch-cli on the kit framework - #1
Merged
Merged
Conversation
Replace the first-pass scaffold with a GraphQL client against Twitch's public endpoint and a kit domain that declares every read once. Each operation maps a typed input to a record stream, so the same declaration drives the CLI, the HTTP server, and the MCP tool. The client paces, retries, and caches requests by query hash, and walks Relay cursor connections to honor --limit. Records carry only fields a logged-out reader can fill: streams, channels, videos, clips, the category directory, schedules, and search over channels and categories. The domain also classifies and locates twitch:// references offline.
NewApp now builds the kit App from the twitch domain and folds the domain-global flags (--client-id, --user-agent, --cache-ttl, --refresh) into the config the client reads. The thin main hands NewApp to kit.Run so the exit code carries the operation result. Remove the hand-rolled streams command, the output helper, and the pkg renderer; the kit output layer covers all of them.
Rewrite the README and docs site for the rebuilt surface: streams, the category directory, a channel with its videos, clips, and schedule, a single video or clip, search, and the offline ref tools. The honesty note states the boundary plainly: Twitch's public GraphQL answers a logged-out reader from any network, so the edge is the account line, not an IP wall, and exit 3 means a resource is genuinely empty. Add guides for collecting data, resource URIs, and adding a command.
Twitch sometimes answers a logged-out request with a "failed integrity check" GraphQL error. It is a transient throttle, not a missing entity, so map it to the rate-limited sentinel: the existing retry loop reattempts it, and if it persists the exit code points the operator at pacing rather than failing with an opaque message.
Model the README on the fleet's house style: lead with a command and the table it actually prints, then cover why, install, quick start, how it works, the access boundary with its exit-code table, the command list, output formats, recipes, serve, and the resource-URI driver. Note that output is colorized on a terminal and drops to plain text in a pipe, with --color to force either way. Give the docs site a real description.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This rebuilds the twitch CLI from the first-pass cobra/fang scaffold onto the any-cli/kit framework, so every read command is declared once and drives the CLI subcommand, the HTTP route, and the MCP tool from a single source.
What it does
A single pure-Go binary that reads public Twitch the way a logged-out browser does, talking to Twitch's public GraphQL endpoint with the web client's public id. No API key, no login, nothing to run alongside it.
Command surface:
Access boundary
Twitch's public GraphQL answers a logged-out reader from any network, home or datacenter, so there is no IP soft-wall. The edge is the account line: anonymous access cannot reach following, chat, subscriptions, watch history, or per-viewer state. Records carry only fields that access can fill, so there are no always-empty columns. Exit 3 means a resource is genuinely empty, not that the network withheld it.
Layout
twitch/the library: GraphQL client, queries, records, anddomain.go(the kit driver)cli/assembles the kit App from the twitch domaincmd/twitch/thin main: handscli.NewApptokit.Rundocs/the tago documentation siteVerification
gofmt,go vet, andgo test ./...are clean;make buildproducesbin/twitch. The httptest-backed tests cover pagination, limit capping, the not-found/rate-limit/blocked paths, and reference classification. Every command was run live against Twitch and returns data anonymously from this network.