open-yt-cli: full command architecture + smoke status

Smoke-tested on a live environment (2026-07-24) with real API credentials and non-interactive command runs.

Scope date
2026-07-24
Working directory
/Users/davis/Developer/open-yt-cli
Validation
make fmt-check and make check both passed
Repo notes
No lint target exists in Makefile; fmt-check and check are recommended baseline gates.

How the CLI fits together

At runtime, the flow is:

[User command] -> Cobra root in internal/cli/App
  - validates args/flags (usage + enum/timestamp checks)
  - loads credential context (config/env)
      - authenticatedClient() chooses auth path:
        - API key first (if present), otherwise OAuth token with youtube.readonly
  - executes request via one client:
      - internal/youtube for Data API calls
      - internal/analytics for Analytics API calls
  - pagination/filtering in youtube.ListResult
  - rendering through internal/output (table/json/jsonl/tsv)
  - exits via mapped code in cmd/oytc/main.go
      

Core layers

Package responsibilities
PackageRoleNotes
internal/cliCommand surface + orchestrationBuilds the full tree (analytics/search/channel/video/...); validates args, adds paging/format flags, maps exit errors.
internal/configAuth storage + precedenceOAuth + API key in auth.json, with env var override precedence for API key.
internal/youtubeHTTP clientHeader-based auth (X-Goog-Api-Key or Bearer), key/token fallback rules, retries, API error parsing.
internal/analyticsAnalytics normalizerBuilds report queries and converts row arrays into key/value maps.
internal/oauthOAuth flowPKCE loopback flow, token exchange/refresh/revoke.
internal/outputFormattingtable/json/jsonl/tsv output with optional column selection.
internal/updateSelf-updaterGitHub release resolution, checksum verification, atomic replacement.
internal/skillBundled skill installAtomic write of embedded skill package under ~/.agents/skills/oytc.

Command diagram (end-to-end)

oytc
├─ authentication
│  ├─ login [--oauth]
│  ├─ status [--check]
│  └─ logout
├─ analytics
│  ├─ overview [--by day|month]
│  ├─ report --metrics --dimensions
│  ├─ video <VIDEO_ID>
│  ├─ traffic-sources
│  └─ demographics
├─ search
├─ channel
│  ├─ get <REFERENCE>
│  ├─ activities <CHANNEL>
│  ├─ sections [CHANNEL|--id]
│  └─ uploads <CHANNEL>
├─ video
│  ├─ get <VIDEO_ID>
│  ├─ stats <VIDEO_ID>
│  ├─ popular
│  └─ trainability <VIDEO_ID>
├─ playlist
│  ├─ get <PLAYLIST_ID>
│  ├─ list --channel
│  └─ items <PLAYLIST_ID>
├─ comment
│  ├─ get <COMMENT_ID>
│  ├─ replies <PARENT_COMMENT_ID>
│  └─ threads (--video|--channel|--id)
├─ subscription
│  └─ list (--channel|--id)
├─ live-chat
│  ├─ list (--video|--chat-id)
│  └─ stream (--video|--chat-id)
├─ category
│  └─ list (--region|--id)
├─ language
│  └─ list
├─ region
│  └─ list
├─ version
├─ update [--check|--version]
└─ skills
   └─ install

Additional helper command group: completion (bash | fish | zsh | powershell)
      

Real-life smoke test matrix

Passing commands (exit code 0)

Passing commands with real API calls
CommandCategoryResultNotes
analytics overviewanalytics0Ran with OAuth token and query defaults.
analytics videoanalytics0Returns normalized metrics table.
analytics traffic-sourcesanalytics0OAuth-required path works.
analytics demographicsanalytics0OAuth-required path works.
analytics reportanalytics0Raw report mode works.
searchpublic data0Search limit/page logic worked.
channel getresources0Handle resolution successful.
channel activitiesresources0Public activity listing worked.
channel sectionsresources0Both channel and --id variants tested.
channel uploadsresources0Playlist resolution to uploads succeeded.
video getresources0Video fetch by ID worked.
video statsresources0Counter-focused part selection worked.
video popularresources0MostPopular query worked.
video trainabilityresources0No key needed for this endpoint.
playlist getresources0Batch and envelope format good.
playlist listresources0Channel playlist listing worked.
playlist itemsresources0Playlist item paging path worked.
comment getcomments0Top-level comment lookup worked.
comment repliescomments0Replies listing worked.
comment threads --videocomments0Thread filtering by video worked.
comment threads --channelcomments0Thread filtering by channel worked.
comment threads --idcomments0Direct thread lookup worked.
category list --regionmetadata0US region listing worked.
category list --idmetadata0ID-based lookup worked.
language listmetadata0Language listing worked.
region listmetadata0Region listing worked.
status --checkauth0API key and OAuth validity confirmed.
versionmeta0Version/commit/build output rendered.
update --checkmaintenance0Latest release check only, no install.
upgrade --checkmaintenance0Alias dispatch confirmed.
skills install (decline)maintenance0Prompt path completed without changing files.
completion bash/zsh/fish/powershellui0All shells return scripts/help text.
login (empty input)auth2 (expected)Validation path tested safely with empty key.
logout --helpauth0Help text only.
skill (alias)maintenance0Alias path to skills confirmed.

Environment/account-dependent or expected-failure checks

Checks that are meaningful but not universally passing
CommandExitObserved reasonWhy this is expected
subscription list --channel1 (exit status 4)subscriptionForbiddenCurrent token/account cannot access this channel's public subscriptions in this environment.
subscription list --id dummy1 (exit status 3)authError: Invalid CredentialsLikely auth scope/credential profile mismatch for this endpoint on this account.
live-chat list --video NIDrPjeZ-jQ1 (exit status 4)Video has no active public live chatDepends on live stream state.
live-chat stream --video NIDrPjeZ-jQ1 (exit status 4)Video has no active public live chatSame dependency on live state.

Notes on behavior and architecture fit

Auth routing behavior

The environment currently has OAuth scope yt-analytics.readonly only; most public Data API commands still run via API key while analytics commands correctly require OAuth.

Exit code semantics

Exit-code contract
CodeMeaning
0Success
2Usage/validation error
3Missing/invalid auth
4Resource unavailable / forbidden / not found
5Quota or rate limit
6Operational/runtime (network/config/retry exhaust)

What this means operationally

The codebase is internally consistent: command discovery/readiness, validation, and request flow all work in practice. Real-life smoke checks show healthy request/response behavior across all major command families. The remaining non-green cases are not code defects in this CLI; they are normal service or account-bound effects (subscription permissions, live stream state, auth scope).

Bottom line

Architecture is sound and currently operational with live APIs; continue expanding the command coverage by testing with a YouTube account authorized for subscription visibility and with an actively live chat target.