Skip to content

cli: improve macOS keychain write-failure messaging and first-run UX #235

Description

@gbrlcustodio

Problem

pipefy auth login from a fresh install on macOS surfaces this when the keychain write fails:

Login succeeded but the session could not be stored in your OS keychain (Keyring):
Can't store password on keychain: (-25244, 'Unknown Error').
On headless Linux, ensure a Secret Service daemon (gnome-keyring, kwallet) is running,
or use a static PIPEFY_TOKEN.

(packages/cli/src/pipefy_cli/commands/auth.py:205-213.)

Two issues:

  1. The hint is platform-wrong. The user is on macOS; the hint talks about headless Linux Secret Service daemons. Confusing.
  2. The actual cause isn't named. On macOS, -25244 (errSecParam) from SecItemAdd typically fires when Security.framework cannot surface the new-item ACL dialog to the user — e.g. when invoked from a non-TTY subprocess of an editor / IDE / agent host that doesn't share an interactive Aqua session. The failure is independent of how pipefy was installed. It hits both uvx --from <git+url> (ephemeral binary) and uv tool install-installed persistent binaries when the calling subprocess can't render the keychain prompt. The OAuth handshake itself succeeds; only the keychain persistence step rejects.

The fix users have to discover today: run pipefy auth login once from their own Terminal.app session, click Always Allow when macOS prompts to grant the Python binary access to the pipefy keychain item. From that point on, the keychain ACL remembers and the slash command (and refresh writes) work from subprocesses.

Surfaced during the workstream-C smoke test (#229): /pipefy:login via the Claude Code plugin completed OAuth but failed to persist, leaving users with a non-actionable error.

Proposal

Branch the error message on platform.system() in the KeyringError handler at packages/cli/src/pipefy_cli/commands/auth.py:205-213:

```python
except KeyringError as exc:
hint = _keychain_hint_for_platform()
typer.echo(
f"Login succeeded but the session could not be stored in your OS "
f"keychain ({keychain_backend_name()}): {exc}. {hint}",
err=True,
)
raise typer.Exit(1) from exc
```

_keychain_hint_for_platform() returns:

  • macOS: "This is usually macOS denying the calling subprocess access to the keychain ACL prompt (errSecParam, -25244). Run pipefy auth login once from a regular Terminal.app session and click Always Allow when macOS prompts; subsequent runs (including agent / IDE integrations) will write without prompting."
  • Linux: existing headless-Secret-Service hint.
  • Windows: a Credential Manager equivalent (or generic).
  • Unknown: generic fallback referencing pipefy auth status + docs.

Optionally also detect non-TTY callers up front (sys.stdin.isatty(), absence of TERM_PROGRAM, etc.) and warn before invoking store_session that first-time keychain access needs to be primed from a terminal.

Acceptance

  • Running pipefy auth login on macOS in a context where the keychain dialog can't surface emits a message that explicitly says "run once from Terminal.app and click Always Allow" — no mention of headless Linux on macOS.
  • Running on Linux still emits the Secret Service hint.
  • errSecParam (-25244) is named in the error so users can grep for it.
  • docs/cli/auth.md documents the macOS first-run keychain ACL step.

Why this is separate from #229 / #233 / #234

The plugin-installed CLI surface (#229), the PIPEFY_AUTH_URL default (#233), and the release-wheel migration (#234) don't touch this error path. It's a pipefy-cli UX concern that fires after OAuth succeeds — pure CLI message work. Lands cleanly on its own.

Refs #229.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions