bkt on macOS prompts the keychain even after the user clicks "Always Allow". Subsequent invocations either re-prompt or fail with:
Error: keyring operation timed out; keyring prompt may need more time. Increase timeout via BKT_KEYRING_TIMEOUT (e.g. 60s or 2m)
This is the follow-on to #45. The 60s default timeout is long enough to enter a password once, but the real problem is that "Always Allow" is not sticking — we keep hitting the prompt on every invocation.
Repro
- macOS 26.3.1, bkt 0.26.1 (homebrew), auth source
keyring, basic auth, DC host.
- Run any command that reads the token (
bkt pr list, bkt api ...).
- Keychain prompt appears. Click Always Allow.
- Run the same command again within seconds.
- Expected: no prompt, token read silently.
Actual: either another prompt, or a keyring operation timed out error.
Workaround
BKT_KEYRING_TIMEOUT=120s bkt ... mostly works, but:
- the prompt still appears sometimes
- 120s is absurd for a token read — if we need 2 minutes, the design is wrong
- shouldn't be required at all after "Always Allow"
Likely root cause
99designs/keyring on macOS calls /usr/bin/security under the hood, and the ACL stored on the item probably doesn't include the current bkt binary path. Each brew upgrade rewrites the binary, which invalidates the ACL and re-triggers the prompt. The Label: fmt.Sprintf("bkt %s", key) in internal/secret/store.go:250 doesn't pin an ACL entry.
Relevant: 99designs/keyring exposes KeychainTrustApplication / KeychainAccessibleWhenUnlocked options on Config that we're not setting today.
Proposed fix
- Set
KeychainTrustApplication: true in the keyring.Config when runtime.GOOS == "darwin" so the ACL trusts the calling binary without re-prompt.
- Optionally add
KeychainAccessibleWhenUnlocked: true so the item survives reboots without re-prompt.
- Add a
bkt auth doctor subcommand (or extend auth status) that inspects the Keychain item ACL and warns when the current binary isn't on the trusted list — which is the state after every brew upgrade bkt.
Environment
- macOS 26.3.1 (Darwin 25.3.0)
- bkt 0.26.1
- Install:
avivsinai/tap/bitbucket-cli via Homebrew
- Backend: macOS Keychain (default on darwin)
- Host: Bitbucket Data Center, basic auth, token source
keyring
Not blocked
Workaround is known. This is a paper cut that hits every time the binary changes. Low priority, but it keeps coming back.
bkton macOS prompts the keychain even after the user clicks "Always Allow". Subsequent invocations either re-prompt or fail with:This is the follow-on to #45. The 60s default timeout is long enough to enter a password once, but the real problem is that "Always Allow" is not sticking — we keep hitting the prompt on every invocation.
Repro
keyring, basic auth, DC host.bkt pr list,bkt api ...).Actual: either another prompt, or a
keyring operation timed outerror.Workaround
BKT_KEYRING_TIMEOUT=120s bkt ...mostly works, but:Likely root cause
99designs/keyringon macOS calls/usr/bin/securityunder the hood, and the ACL stored on the item probably doesn't include the currentbktbinary path. Each brew upgrade rewrites the binary, which invalidates the ACL and re-triggers the prompt. TheLabel: fmt.Sprintf("bkt %s", key)ininternal/secret/store.go:250doesn't pin an ACL entry.Relevant:
99designs/keyringexposesKeychainTrustApplication/KeychainAccessibleWhenUnlockedoptions onConfigthat we're not setting today.Proposed fix
KeychainTrustApplication: truein thekeyring.Configwhenruntime.GOOS == "darwin"so the ACL trusts the calling binary without re-prompt.KeychainAccessibleWhenUnlocked: trueso the item survives reboots without re-prompt.bkt auth doctorsubcommand (or extendauth status) that inspects the Keychain item ACL and warns when the current binary isn't on the trusted list — which is the state after everybrew upgrade bkt.Environment
avivsinai/tap/bitbucket-clivia HomebrewkeyringNot blocked
Workaround is known. This is a paper cut that hits every time the binary changes. Low priority, but it keeps coming back.