Problem Summary
Every time the system restarts or a new shell session starts, the SSH key passphrase must be entered manually before 1Password is unlocked. Once 1Password is unlocked, the passphrase resolution works as expected, but the initial bootstrap sequence is broken.
Root Cause Analysis
1. setup_ssh_agent.sh does not verify op authentication before configuring SSH_ASKPASS
In src/setup_ssh_agent.sh:
if command -v op >/dev/null 2>&1 && [[ -f "$_askpass_helper" ]] && [[ -x "$_askpass_helper" ]]; then
if ! grep -q "REPLACE/WITH/YOUR" "$_askpass_helper" 2>/dev/null; then
export SSH_ASKPASS="$_askpass_helper"
export SSH_ASKPASS_REQUIRE="prefer"
_askpass_vars_set=true
fi
fi
The script verifies that:
op CLI is installed
- The askpass helper file exists and is executable
- The placeholder reference has been replaced
It does NOT verify that op is actually authenticated. On a fresh boot:
- The 1Password desktop app is locked
- There is no cached session token yet (or it has expired)
op vault list would fail with "not currently signed in"
- Yet
SSH_ASKPASS is still set to the 1Password helper
2. askpass-1password.sh fails silently when op is not authenticated
In src/askpass-1password.sh:
op read "$OP_SECRET_REFERENCE"
When op is not authenticated, op read fails and writes an error to stderr, but nothing (or an empty string) goes to stdout. ssh-add interprets this empty/failed output as the passphrase, which is incorrect. Because SSH_ASKPASS_REQUIRE=prefer (not force), ssh-add then falls back to a terminal prompt, forcing the user to type the passphrase manually.
3. op-session-manager.sh interactive signin may break in .zshrc
In src/op-session-manager.sh:
op signin > "$TOKEN_FILE"
This redirects stdout to the token file. If op signin outputs prompts to stdout (depending on auth method), the user may not see them in the .zshrc context, causing the signin to hang or fail silently.
4. SSH_ASKPASS and SSH_ASKPASS_REQUIRE are unset after keychain runs
if $_askpass_vars_set; then
unset SSH_ASKPASS
unset SSH_ASKPASS_REQUIRE
fi
This means even if a user later authenticates 1Password and wants to run ssh-add manually, the ASKPASS environment is gone and must be manually recreated.
Impact
- On every system restart / new login, the user sees a manual SSH passphrase prompt
- The whole value proposition of "1Password provides the passphrase automatically" is lost at the most critical moment
- The setup documentation explicitly states the session manager must come before SSH setup, but even with correct ordering, the SSH script does not gate on 1Password readiness
Reproduction Steps
- Reboot the system (or open a fresh terminal with no existing
ssh-agent)
- Ensure 1Password desktop app is locked (or no
OP_SERVICE_ACCOUNT_TOKEN is exported)
- Open a new shell where
.zshrc sources ~/.ssh/setup_ssh_agent.sh
- Observe that
keychain runs and ssh-add prompts for passphrase manually
- Only after unlocking 1Password separately does
op read work
Environment
- Linux/WSL/macOS with
keychain installed
- 1Password CLI (
op) installed
- SSH key with passphrase
- Desktop app integration or session token caching (not service account)
Suggested Fixes
Fix 1: Gate SSH_ASKPASS on 1Password authentication status
In setup_ssh_agent.sh, add an authentication check:
if command -v op >/dev/null 2>&1 && [[ -f "$_askpass_helper" ]] && [[ -x "$_askpass_helper" ]]; then
if ! grep -q "REPLACE/WITH/YOUR" "$_askpass_helper" 2>/dev/null; then
# NEW: Only use 1Password ASKPASS if op is actually authenticated
if op vault list >/dev/null 2>&1; then
export SSH_ASKPASS="$_askpass_helper"
export SSH_ASKPASS_REQUIRE="prefer"
_askpass_vars_set=true
else
if [[ -n "$OP_DEBUG" ]]; then
echo "[DEBUG] 1Password not authenticated. Skipping ASKPASS config." >&2
fi
fi
fi
fi
Fix 2: Add error handling to askpass-1password.sh
# Verify op is authenticated before trying to read
if ! op vault list >/dev/null 2>&1; then
# Exit non-zero so ssh-add can fall back to terminal prompt
echo "1Password not authenticated" >&2
exit 1
fi
op read "$OP_SECRET_REFERENCE"
Fix 3: Consider not unsetting SSH_ASKPASS after keychain
Leaving SSH_ASKPASS in the environment allows manual ssh-add operations to also benefit from 1Password after the user authenticates. Alternatively, export a helper function or alias.
Fix 4: For op-session-manager.sh, ensure interactive prompts are visible
Consider using /dev/tty for op signin output when in an interactive shell, or use op signin --raw with explicit prompting, to avoid stdout redirection swallowing prompts:
op signin > "$TOKEN_FILE" 2>/dev/tty
Files Affected
packages/1password-cli-tools/src/setup_ssh_agent.sh
packages/1password-cli-tools/src/askpass-1password.sh
packages/1password-cli-tools/src/op-session-manager.sh
packages/1password-cli-tools/lib/config.js (.zshrc block generation)
Related Documentation
- SKILL.md - SSH Agent (Troubleshooting section mentions this exact symptom but the docs only suggest checking env vars, not fixing the auth check)
- docs/SETUP.md (Order of sourcing is documented correctly, but the scripts don't enforce the dependency)
Problem Summary
Every time the system restarts or a new shell session starts, the SSH key passphrase must be entered manually before 1Password is unlocked. Once 1Password is unlocked, the passphrase resolution works as expected, but the initial bootstrap sequence is broken.
Root Cause Analysis
1.
setup_ssh_agent.shdoes not verifyopauthentication before configuringSSH_ASKPASSIn
src/setup_ssh_agent.sh:The script verifies that:
opCLI is installedIt does NOT verify that
opis actually authenticated. On a fresh boot:op vault listwould fail with "not currently signed in"SSH_ASKPASSis still set to the 1Password helper2.
askpass-1password.shfails silently whenopis not authenticatedIn
src/askpass-1password.sh:When
opis not authenticated,op readfails and writes an error to stderr, but nothing (or an empty string) goes to stdout.ssh-addinterprets this empty/failed output as the passphrase, which is incorrect. BecauseSSH_ASKPASS_REQUIRE=prefer(notforce),ssh-addthen falls back to a terminal prompt, forcing the user to type the passphrase manually.3.
op-session-manager.shinteractive signin may break in.zshrcIn
src/op-session-manager.sh:This redirects stdout to the token file. If
op signinoutputs prompts to stdout (depending on auth method), the user may not see them in the.zshrccontext, causing the signin to hang or fail silently.4.
SSH_ASKPASSandSSH_ASKPASS_REQUIREare unset afterkeychainrunsThis means even if a user later authenticates 1Password and wants to run
ssh-addmanually, the ASKPASS environment is gone and must be manually recreated.Impact
Reproduction Steps
ssh-agent)OP_SERVICE_ACCOUNT_TOKENis exported).zshrcsources~/.ssh/setup_ssh_agent.shkeychainruns andssh-addprompts for passphrase manuallyop readworkEnvironment
keychaininstalledop) installedSuggested Fixes
Fix 1: Gate
SSH_ASKPASSon 1Password authentication statusIn
setup_ssh_agent.sh, add an authentication check:Fix 2: Add error handling to
askpass-1password.shFix 3: Consider not unsetting
SSH_ASKPASSafter keychainLeaving
SSH_ASKPASSin the environment allows manualssh-addoperations to also benefit from 1Password after the user authenticates. Alternatively, export a helper function or alias.Fix 4: For
op-session-manager.sh, ensure interactive prompts are visibleConsider using
/dev/ttyforop signinoutput when in an interactive shell, or useop signin --rawwith explicit prompting, to avoid stdout redirection swallowing prompts:Files Affected
packages/1password-cli-tools/src/setup_ssh_agent.shpackages/1password-cli-tools/src/askpass-1password.shpackages/1password-cli-tools/src/op-session-manager.shpackages/1password-cli-tools/lib/config.js(.zshrcblock generation)Related Documentation