Skip to content

docs: fix three onboarding friction points for Linux/headless installs - #88

Merged
suisuss merged 2 commits into
KeeperHub:mainfrom
Makabeez:docs/onboarding-friction
Aug 9, 2026
Merged

docs: fix three onboarding friction points for Linux/headless installs#88
suisuss merged 2 commits into
KeeperHub:mainfrom
Makabeez:docs/onboarding-friction

Conversation

@Makabeez

@Makabeez Makabeez commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

What and why

Three documentation gaps hit during a fresh Linux/WSL2 onboarding run on v0.13.1 (2026-08-06). Each change is self-contained and fixable in docs without a code change.

1. Linux binary install — quickstart.md

The install section leads with Homebrew and lists "Binary download: see GitHub Releases" as a one-liner with no command. Users on headless Linux boxes (remote servers, WSL, CI) without Homebrew have no actionable path. Added a curl one-liner that fetches the latest release automatically and extracts to ~/.local/bin.

2. Auth flow description — quickstart.md

"This opens a browser window to authenticate."

This is wrong for any headless or remote environment — and it's wrong about the mechanism. kh auth login uses the device code flow: it prints a URL and a code; the user visits the URL on any machine. On a remote box, the browser never opens. Codes expire in roughly two minutes, and there's no retry hint.

Changed to accurately describe the flow and tell headless users what to do when the URL doesn't open automatically.

3. Node.js/npx prerequisite — kh_wallet_info.md

kh wallet info (and other kh wallet subcommands) shells out to npx @keeperhub/wallet. This dependency is unmentioned, so users without Node.js see:

could not determine executable to run

with no actionable guidance. Added a Prerequisite callout pointing to nodejs.org.

Related

Companion PR for SSH prerequisite in claude-plugins: KeeperHub/claude-plugins#

Full onboarding teardown (to be published with the carrydesk repo): covers these three items plus the kh w balance chainId type mismatch fixed in #87.

@Makabeez

Makabeez commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

SSH prerequisite companion PR: KeeperHub/claude-plugins#5

@Makabeez

Makabeez commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

@suisuss Both blockers were fair. null becoming "null" was a regression I introduced, and the else branch was wider than the bug.

Fixed: null returns early as a no-op per the Unmarshaler contract; acceptance narrowed to numbers via json.Number, which restores *json.UnmarshalTypeError for objects, arrays and bools. Also corrected the wrong "panics" comment, moved the test to package wallet_test to match its neighbours, and extended the table with null, object, bool and array cases across both ChainBalance and Token — you were right that those would have caught both blockers. Left the strings import in place; it's still used elsewhere in the file.

On the marshal question: I'd lean toward (a) — emit a bare number when the value is numeric. It restores parity with kh chain list --json for the case that actually occurs and closes the jq footgun without a breaking change to that command. The cost you name is real, output shape following input shape, but for chainId the input is numeric in every response I've seen, so the string branch is a compatibility path rather than a live one. Happy to add it here or keep this PR scoped to the decode fix — your call.

@Makabeez
Makabeez force-pushed the docs/onboarding-friction branch from 34eee3f to ea3910b Compare August 6, 2026 11:58
@Makabeez

Makabeez commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Verified the Linux install snippet on Ubuntu/WSL2 (x86_64, GNU tar 1.34) — amended to add mkdir -p before the tar call (silent failure if ~/.local/bin doesn't exist) and made stdin explicit with -f -. Both failure modes tested: missing directory exits 2, original one-liner ran fine on this system but -f - is the portable form.

- quickstart: add Linux binary install one-liner for no-Homebrew/headless
  environments; the existing section was macOS-first with no path for
  remote servers or WSL boxes without Homebrew installed
- quickstart: correct auth description from "opens a browser window" to
  device-code flow; headless users need to know codes expire (~2 min)
  and the URL can be opened on any machine
- kh_wallet_info: add Node.js/npx prerequisite; the command shells out
  to npx @keeperhub/wallet but this dependency was undocumented, causing
  "could not determine executable to run" with no actionable guidance

Found during a fresh Linux/WSL2 onboarding run on v0.13.1 (2026-08-06).
@Makabeez
Makabeez force-pushed the docs/onboarding-friction branch from ea3910b to b98abd7 Compare August 6, 2026 15:06
@Makabeez

Makabeez commented Aug 6, 2026

Copy link
Copy Markdown
Contributor Author

Amended — the original note in docs/kh_wallet_info.md mapped "could not determine executable to run" to a missing Node.js install. That diagnosis was wrong: I hit that error with Node v24 installed. Root cause is npx binary-name inference: @keeperhub/wallet publishes three bins (keeperhub-wallet, keeperhub-wallet-hook, keeperhub-wallet-mcp) and none of them is named wallet, so npx @keeperhub/wallet <subcmd> can't pick one and exits with that error regardless of whether Node is present.

The fix is in #89 (npx -p @keeperhub/wallet keeperhub-wallet <subcmd>). Keeping the Node prerequisite here since it's still a real requirement; dropped the incorrect error mapping.

Related: #89 (root cause fix)

@joelorzet joelorzet left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Two of the three changes hold up. One will fail CI as written, and one states a number that is off by an order of magnitude.

docs/kh_wallet_info.md is generated, so this edit gets dropped

docs/generate.go runs doc.GenMarkdownTree over the cobra tree, and the docs-check job runs go generate ./docs/ followed by git diff --exit-code docs/. Running that against this branch deletes your line:

$ go generate ./docs/ && git diff --stat docs/
 docs/kh_wallet_info.md | 2 --

Checks have not run on this PR yet because a first time contributor PR needs workflow approval, which is why this has not surfaced on its own.

The place for the note is the Long string on the cobra command, followed by go generate ./docs/ in the same commit. That also puts it in kh wallet info --help, which is where someone who just hit the error is actually looking. Worth attaching to the parent kh wallet command rather than info alone, since fund, add, link and feedback shell out the same way.

Note that #89 changes the picture here: the "could not determine executable to run" error was binary name inference, not a missing Node. Node remains a real prerequisite worth documenting, so keep the note, just as a prerequisite rather than as the explanation for that error.

The two minute expiry is not right

The server configures the device authorization flow with expiresIn: "15m", so a code is good for fifteen minutes. Please drop the two minute figure or replace it with fifteen.

The rest of that paragraph is correct and worth having. I read internal/auth/device.go and there is no browser opening code anywhere in the path: it requests a device code, prints the URL and the user code, then polls. The sentence you are replacing was simply wrong.

While you are there, kh auth login's own Long says "Opens a browser to confirm a one-time code", and cmd/auth/auth.go carries an example commented "Log in via browser". Both repeat the error this PR is correcting, and both feed docs/kh_auth_login.md. Fixing quickstart alone leaves the wrong description in the command help, which is the copy most people meet first.

The install one-liner works

Ran it verbatim against the current release. It resolves the asset, extracts, and produces a valid statically linked linux amd64 ELF binary. Asset naming and archive layout both check out, and kh sits at the archive root, so the single member extract is correct.

One thing worth adding: the release publishes checksums.txt, and this snippet pipes an unverified binary straight into tar. Since this would become the install path we recommend to people on exactly the machines that cannot use Homebrew, it is worth verifying the download, or at minimum pointing at the checksums file.

Minor and separate: the unauthenticated GitHub API is rate limited to 60 requests an hour per IP, which tends to bite on shared CI addresses and fails in a way that looks nothing like rate limiting.

Requesting changes for the generated file and the expiry figure. The quickstart install section and the flow correction are both things this repo needs.

@joelorzet joelorzet added the changes-requested Triage: reviewed, changes needed from the contributor label Aug 7, 2026
- Move Node.js prerequisite from kh_wallet_info.md (generated, wrong place)
  to cmd/wallet/wallet.go Long so it covers all agentic subcommands at once
  and regenerates cleanly into kh_wallet.md
- Fix two browser-error sources: auth.go Example comment ("via browser" →
  device code description) and login.go Long (clarify browser does not open
  automatically; code TTL is 15 minutes, not "roughly two minutes")
- Replace unverified install pipe with checksum-verified snippet:
  downloads checksums.txt alongside the tarball, runs sha256sum --ignore-
  missing, then extracts; add GitHub API rate-limit note (60 req/hr/IP)
- Regenerate docs/kh_auth*.md, docs/kh_wallet*.md, docs/quickstart.md

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Makabeez

Makabeez commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Revised — four changes in this push:

  1. Prerequisite note moved out of kh_wallet_info.md (a generated file, wrong place to hand-write into) and into cmd/wallet/wallet.go's Long, so it regenerates into kh_wallet.md and covers all agentic subcommands at once.

  2. Browser copy fixed in two places: cmd/auth/auth.go Example comment (was "Log in via browser") and cmd/auth/login.go Long (was "open the URL in a browser to confirm it" with no indication the browser doesn't auto-open). Both now describe the device code flow accurately.

  3. Code TTL corrected: I wrote "roughly two minutes" from experience — codes were dying during the session, but that was the background shell timing out, not the codes expiring. The server sends expiresIn: "15m". Fixed to "15 minutes".

  4. Install snippet now verifies checksums: previous snippet piped an unverified binary straight into tar. New snippet downloads checksums.txt alongside the tarball, runs sha256sum --ignore-missing -c checksums.txt, then extracts. Tested end to end. Added a note about the 60 req/hr/IP GitHub API rate limit.

@Makabeez

Makabeez commented Aug 7, 2026

Copy link
Copy Markdown
Contributor Author

Heads up on merge order: #88 and #89 both touch the Long on cmd/wallet/wallet.go (Node prerequisite here, invocation string there) and both regenerate docs/kh_wallet.md, so whichever lands second will conflict. Happy to rebase the loser onto main and re-push as soon as the first one merges — just say which order you'd prefer.

@suisuss

suisuss commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

What changed since the last review

  • docs/kh_wallet_info.md generated-file edit - addressed. The Node/npx prerequisite moved to cmd/wallet/wallet.go's Long (parent kh wallet command, not info alone, per the ask), kh_wallet_info.md reverted, kh_wallet.md regenerated with the line. Diffed both files against the cobra source strings at head - they match verbatim.
  • Two-minute expiry - addressed. cmd/auth/login.go:57, docs/kh_auth_login.md, and docs/quickstart.md:36 all now read 15 minutes, matching internal/auth/device.go's 15*time.Minute context timeout.
  • Browser-copy fix scoped to quickstart only - addressed for both spots the prior review named. cmd/auth/auth.go Example ("Log in via browser" -> device-code description) and cmd/auth/login.go Long (browser does not auto-open) are both corrected and regenerated into docs/kh_auth.md / docs/kh_auth_login.md.
  • Unverified install pipe - addressed. docs/quickstart.md:12-18 now downloads checksums.txt alongside the tarball and runs sha256sum --ignore-missing -c before extracting; rate-limit note added. Ran the snippet verbatim against the current release (kh_0.14.0_linux_amd64.tar.gz) - checksum reports OK, extraction produces a valid ELF binary.

Two of the six PR comments (2026-08-06 08:31 and 08:38, re: null decoding to string and ChainBalance/Token json.Unmarshaler) describe code that is not in this PR - the two commits on this PR (b98abd79, ff409821) only touch cmd/auth/*, cmd/wallet/wallet.go, and docs/*. Nothing to fact-check there; noting it since those comments read as answers to blockers this PR's diff does not contain.

Blocking

None.

Mechanical - actionable as-is

None.

Needs a decision

None.

Verdict

Approve - all four items from the prior review are fixed and verified against source/base, the install snippet runs clean end to end, and the increment touches only help-text strings and docs, no auth logic.

@suisuss suisuss added approve Triage: reviewed and good - not a GitHub approval and removed changes-requested Triage: reviewed, changes needed from the contributor labels Aug 9, 2026
@suisuss
suisuss merged commit 8bedef7 into KeeperHub:main Aug 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approve Triage: reviewed and good - not a GitHub approval

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants