Skip to content

Native --help for X commands; /health reports per-account cooldown state - #47

Merged
guzus merged 1 commit into
mainfrom
feat/native-help-health
Sep 6, 2026
Merged

guzus merged 1 commit into
mainfrom
feat/native-help-health

Conversation

@guzus

@guzus guzus commented Sep 6, 2026

Copy link
Copy Markdown
Owner

What

  1. Native --help for the X commands. birdy <cmd> --help, birdy <cmd> -h and birdy help <cmd> now print birdy-authored help — one-liner, usage with positionals, the flags the native engine accepts for that command, birdy's global flags, and 1–2 birdy examples. Help is answered in-process before any account is picked or process spawned, so it works on a runner with no accounts and no bird. --help is never forwarded on any path (registered command, unknown command, tweet-id shorthand); a literal --help after -- still passes through.
  2. GET /health reports rate-limit state. Appended to the existing (byte-compatible) six fields: accounts_cooling, accounts_ready, cooldown_seconds (= rotation.QuotaCooldown), degraded (no account ready), and accounts_detail: [{name, cooling, cooldown_remaining_seconds, last_rate_limited_at, disabled?}]. ok stays a liveness bit. Names and timestamps only — a test asserts no credential material leaks.
  3. Docs. README/COMPATIBILITY now state what actually happens with a non-native flag; README gains a birdy daemon section documenting /health.

How the flag list stays DRY

cmd/native_help.go has one ordered flagDocs table. nativeHelpFlags(cmd) filters it through nativeAcceptsFlags — the exact predicate runPassthrough uses to decide whether the native engine serves an invocation. TestNativeHelpMatchesParserFlagSet compares, for every command in nativeCommands, the set of flags shown in help against the set the parser accepts (drawn from nativeSupportedFlags + commandExtraFlags), in both directions. So a flag added to native.go without a doc entry fails CI, and help can never advertise a flag the engine rejects (e.g. whoami --json). cmd/native.go is untouched. A --json-full doc entry is present but inert until the parser accepts it (another branch).

Before / after — birdy search --help

Before (main, from a cwd without the bird checkout, or on the CI runner):

Error: bird CLI not found, and --bird requires it.

Before, with a stray birdy-bird Node shim on PATH: bird's Commander banner (bird unknown — fast X CLI for tweeting, replying, and reading, -V, --json-full, bird tweet examples). With node hidden: env: node: No such file or directory, exit 127.

After (PATH=/usr/bin:/bin ./birdy search --help, exit 0):

Search for tweets

Usage:
  birdy search <query> [flags]

The query is X advanced-search syntax (from:, since:, min_faves:, ...).

Flags:
  -n, --count, --limit N   number of items to return (default 10)
      --json               emit JSON instead of the human-readable view
      --plain              plain output: no emoji, no color, stable for scripts
      --no-emoji           human-readable output without emoji
      --no-color           accepted for compatibility; native output is never colorized
  -h, --help               show this help

Global Flags (before the command name):
  -a, --account ACCOUNT         use a specific account by name (skip rotation)
  -s, --strategy STRATEGY       rotation strategy: round-robin, least-recently-used, least-used, random
  -v, --verbose                 show which account is being used
      --vpn                     route bird through the configured SOCKS5 VPN (see: birdy vpn)
      --vpn-server VPN-SERVER   pin to a specific SOCKS5 server hostname (implies --vpn)
      --bird                    force the bird CLI (Node) instead of birdy's native Go implementation

Examples:
  birdy search "golang" -n 20 --plain
  birdy search "from:OpenAI since:2026-09-01" --json

birdy trending --help (registered but not native) says so and points at --bird + a separate bird install instead of forwarding. Root birdy --help retitles the group X Commands (native Go engine; \birdy --help` lists its flags):and flagstrending` as bird-only.

Premise corrections

  • The brief said --max-pages / --cursor "run natively now". They do not: neither is in nativeSupportedFlags, and --max-pages only exists on following-overlap. Verified live from a clean cwd: birdy search golang --max-pages 2 → Error: bird CLI not found, and --bird requires it. The docs were wrong in a different way — "falls back to bird" no longer works out of the box — and now say exactly that. --json-full doc mention left as-is per the brief.
  • findBird() does not re-exec birdy; with no shim it returns the bird CLI not found error above (runner is out of scope here, untouched).
  • README had no daemon section; one was added.

Verification

  • gofmt -l . → only the pre-existing internal/vpn/bootstrap_test.go (untouched, out of scope)
  • go vet ./... clean; go test ./... -count=1 all packages ok (cmd, internal/daemon incl. 3 new httptest health tests with one cooling + one ready account, all-cooling → degraded, and nil Accounts compatibility)
  • Manual: PATH=/usr/bin:/bin ./birdy search --help (above), whoami -h (no --json listed), help news (all six tab flags), --help root listing
  • go mod tidy promoted spf13/pflag from indirect to direct (already imported directly by cmd/root.go on main)

🤖 Generated with Claude Code

https://claude.ai/code/session_01L2FYb2zupuW9VBdnTFjz3Y

`birdy <cmd> --help` / `-h` / `birdy help <cmd>` used to travel into the
bird subprocess (bird's Commander banner, or `env: node: No such file`,
or `bird CLI not found` on a runner without bird). The X subcommands run
with DisableFlagParsing, so cobra never saw the flag. Answer it in-process
before any account is picked or process spawned, on every dispatch path.

The flag list is not hand-written per command: cmd/native_help.go keeps
one ordered flagDocs table and filters it through nativeAcceptsFlags, the
predicate runPassthrough already uses to choose the engine. A test compares
help against the parser's accepted set in both directions for every native
command, so a flag added to native.go without a doc entry fails CI and help
can never advertise a flag the engine rejects. native.go is untouched.

GET /health now appends accounts_cooling, accounts_ready, cooldown_seconds
(rotation.QuotaCooldown), degraded (no account ready) and accounts_detail
(name, cooling, cooldown_remaining_seconds, last_rate_limited_at; never
credentials). ok stays a liveness bit. The daemon Config gains an optional
Accounts callback; nil keeps the old shape working.

Docs: README/COMPATIBILITY said unsupported flags (--max-pages, --cursor)
"fall back to bird"; verified live that without bird installed they fail
with `bird CLI not found`, and say so now. README gains a daemon section.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01L2FYb2zupuW9VBdnTFjz3Y
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 6, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-06T07:33:46.396711Z e77df2e PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e77df2ea86

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread cmd/native_help.go
Comment on lines +43 to +44
{names: []string{"-n", "--count", "--limit"}, arg: "N",
doc: "number of items to return"},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don't advertise counts for commands that ignore them

For read, thread, and replies, this shared entry causes help to advertise -n/--count/--limit as controlling the number of returned items because nativeAcceptsFlags accepts the common flag set. However, nativeRead, nativeThread, and nativeReplies never read args.count, so invocations such as birdy replies <id> -n 1 are served natively while silently ignoring the documented limit. Restrict this help entry to handlers that consume the count, or narrow the native acceptance tables so unsupported counts fall back instead.

Useful? React with 👍 / 👎.

@guzus
guzus merged commit c5c605c into main Sep 6, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant