Uh oh!
There was an error while loading. Please reload this page.
feat(cli): add openkb feedback to file a prefilled GitHub issue - #53
Conversation
Submitting feedback from a CLI tool with no backend is awkward — auto-creating issues requires a maintainer-owned token (security nightmare to ship in source), running an OpenKB-owned API server is overkill for an OSS CLI, and asking users to authenticate with their own gh CLI excludes anyone who hasn't installed it. Workaround: build a GitHub issue URL with title / body / labels prefilled in query params, and open the user's browser. The user goes through GitHub's normal flow with their own account — no backend, no secrets, no auth dance. Usage: openkb feedback # interactive (stdin) openkb feedback "openkb add hangs" # one-liner openkb feedback --type bug "..." # tags 'bug' label openkb feedback --print-url "..." # SSH / no-browser env openkb feedback --no-diagnostics "..." # skip env info The auto-collected diagnostics are deliberately minimal — openkb version, Python version, OS, whether a KB is initialised in cwd. No paths, no env vars, no API keys. Users can disable with --no-diagnostics if even that's too much. Implementation is ~90 lines in cli.py plus 17 regression tests covering URL shape, type→label mapping, title truncation, the --no-diagnostics body shape, and the webbrowser-not-called contract for --print-url.
| from unittest.mock import patch | ||
| from urllib.parse import parse_qs, urlparse | ||
| import pytest |
KylinMountain
commented
May 17, 2026
Code reviewFound 3 issues.
Generated with Claude Code. |
1. **webbrowser.open return value silently dropped on headless boxes** The command printed "Opening GitHub in your browser..." and exited 0 even when webbrowser.open returned False (no GUI, no $BROWSER, CI runner, container without DISPLAY). Now we capture the return value, surface "no browser available — copy the URL above" to stderr, and only print "Opened GitHub in your browser." after a confirmed True return. 2. **_openkb_version was the third copy of the same logic** openkb/__init__.py exports __version__ via importlib.metadata with fallback "0.0.0+unknown"; openkb/agent/chat.py wraps it as _openkb_version(); cli.py was re-implementing it with fallback "unknown" — already drifted. Replaced with the same one-liner used in chat.py: `from openkb import __version__; return __version__`. Now all three call sites agree. 3. **type prompt hung in non-TTY contexts (regression of PR #48)** PR #48 introduced _stdin_is_tty() specifically because adding a prompt without a TTY check broke automation pipelines. PR #53's second prompt (asking for feedback type) repeated the same pattern. Now it skips the prompt when stdin isn't a TTY and falls through to `--type other`. Pipes / CI work without flags now: echo "..." | openkb feedback "msg" # works, type=other, no label 4 new regression tests: - test_feedback_skips_type_prompt_when_stdin_is_not_a_tty - test_feedback_warns_when_webbrowser_open_returns_false - test_feedback_confirms_when_webbrowser_open_succeeds - test_openkb_version_helper_matches_package_version 331 tests pass (327 prior + 4 new).
The two flags added complexity without changing the day-one user experience: - --print-url: URL is already printed before webbrowser.open is attempted (the "Copy this URL..." line), so SSH/sandbox users can copy it from the terminal regardless of whether the auto-open succeeds. The flag was redundant. - --no-diagnostics: the diagnostics block is intentionally tiny (openkb version, Python, OS, kb_initialised yes/no) — no paths, usernames, env vars, or keys. Maintainers benefit from having it on every issue without exception, and the privacy cost is negligible. Surface shrinks to one flag (--type) plus the positional message. Help text and README updated. 19 feedback tests still pass (329 total).
Uh oh!
There was an error while loading. Please reload this page.
Summary
Adds
openkb feedback— opens a prefilled GitHub issue in the user's browser. No backend, no maintainer-owned token, noghCLI dependency, one flag.The auto-attached Diagnostics block is intentionally tiny —
openkbversion, Python version, OS, and whether a KB is initialised in cwd. No paths, env vars, or keys.Why this shape
ghCLI authgh auth login; also skips the natural "review before Submit" step that a browser flow givesPrefilled URL → browser is the standard pattern for "file a bug" CLI commands (rustup, cargo, etc.). GitHub renders the issue form with our title / body / label, the user reviews and clicks Submit with their own account.
Behaviour details
--typeif not given on the command line, then opens browser. URL is also printed for copy-fallback if the browser can't auto-open (headless box, no$BROWSER).other. Browser open may fail silently — the printed URL is the fallback.webbrowser.openreturns False: surfaced via stderr (no browser available — copy the URL above), exits 0. Tested via mock.Files
openkb/cli.py—feedbackcommand + 3 helpers (_openkb_version,_collect_feedback_diagnostics,_build_feedback_url)tests/test_feedback.py— 19 regression tests: URL shape, type → label mapping, title truncation/prefix rules, empty-dict diagnostics shape, thewebbrowser.open=Falseheadless path, the non-TTY--typeskip path, version-helper consistency across cli/chat/__init__README.md— one row in the Commands tableSelf-review fixes applied during PR
After the initial commit I ran the code-review skill against my own PR and addressed 3 findings:
webbrowser.openreturn value was discarded — silent success on headless boxes. Now captured and reported._openkb_versionduplicated logic in 3 places with drifted fallback strings — collapsed to onefrom openkb import __version__; return __version__that matchesopenkb/agent/chat.py._stdin_is_tty()helper to default tootherin pipes / CI.Then per discussion the original
--print-urland--no-diagnosticsflags were removed:--print-urlwas redundant — the URL is always printed for copy-fallback beforewebbrowser.openis attempted.--no-diagnosticswas an over-correction — the diagnostics block is small enough and useful enough for maintainers that there's no real privacy reason to opt out.Final surface: one flag (
--type) plus the positional message argument.Test plan
openkb feedback --type bug "msg"opens browser with title/body/label correct (verified by mock + manual run)echo "" | openkb feedback "X"doesn't hang on the type prompt; URL is correct (manual run)cli._openkb_version(),chat._openkb_version(), and__init__.__version__all return the same string (asserted intest_openkb_version_helper_matches_package_version)