Skip to content

feat: make 1P field name configurable via OP_FIELD#13

Merged
busla merged 2 commits into
mainfrom
configurable-op-field
May 11, 2026
Merged

feat: make 1P field name configurable via OP_FIELD#13
busla merged 2 commits into
mainfrom
configurable-op-field

Conversation

@busla
Copy link
Copy Markdown
Contributor

@busla busla commented May 11, 2026

Why

Two fragility issues with the 1Password field lookup:

  1. Hardcoded field name: the fallback was the literal string "API Key" in both wrappers. op read is exact-match and case-sensitive — users with API key (lowercase k) or any non-standard naming hit a silent retrieval failure. The diagnostic block from PR fix(claude-env.sh): capture op stderr to surface actual 1P errors #12 confirmed this as the most common real-world cause.
  2. No discoverability: even with the field name configurable, users have to know what fields exist in their 1P item. The installer prompted for a free-form string with no guidance.

What

Part 1 — OP_FIELD configurability (commit 1)

Adds OP_FIELD as a configurable variable, defaulting to "API Key" so existing installs work unchanged. Five touchpoints:

File Change
claude-env.sh New OP_FIELD="API Key" default + ${OP_FIELD} in lookup + reference in diagnostic block
claudestart.ps1 New $OP_Field = "API Key" default + extend local.env regex to include OP_FIELD and OP_ACCOUNT (same fragility class) + $OP_Field in lookup + reference in diagnostic block
install.sh Prompt for the field, read existing value as default, serialize to local.env
install.ps1 Matching PowerShell prompt + serialization

Part 2 — Field enumeration in installer (commit 2)

After OP_ITEM is entered, the installer calls op item get <item> --vault <vault> to enumerate the actual fields and shows them as a numbered list. User can either type the field name or pick by number. Falls back to free-form prompt with a warning if op enumeration fails (op missing, not signed in, item doesn't exist).

  Fields available in op://Employee/ai.apro.is litellm:
      [1] password
      [2] username
      [3] notesPlain
      [4] API Key
      [5] genai-azure
      [6] management

  1Password field name (or number) [API Key]: 4

Implementation notes:

  • op item get does NOT accept the op://Vault/Item syntax (only op read does). Installer parses OP_ITEM into --vault + item name.
  • Bash JSON parsing without jq: scope to the "fields" array via awk (URL entries also have "label" keys), then grep field labels. Pretty-printed JSON has whitespace after colons; the regex tolerates it.
  • PowerShell side uses ConvertFrom-Json and walks $parsed.fields[].label directly.

Backwards compatibility

Existing local.env files without OP_FIELD keep working — each wrapper sets the default before sourcing/parsing local.env. Users get the override capability when they re-run the installer, which preserves their current values as prompt defaults.

Verification

  • OP_FIELD="custom-name" in local.env propagates to runtime variable (functional test against claude-env.sh)
  • ✅ All lookup sites use the variable; only default declarations and explanatory comments still mention "API Key"
  • ✅ Field enumeration against a real 1P item returns the correct labels (password, username, API Key, etc. — no website from the URL section)
  • ✅ Bash syntax check passes for both claude-env.sh and install.sh

🤖 Generated with Claude Code

busla added 2 commits May 11, 2026 10:15
The fallback 1Password field name was hardcoded as the literal string
"API Key" in both wrappers. Users with non-standard field names (e.g.
"API key" with lowercase k, or org-specific names like "token") had to
either rename the field in 1Password or hit a silent retrieval failure.
op's `read` command is exact-match and case-sensitive, so the wrapper
had no graceful fallback.

This adds OP_FIELD as a configurable value, defaulting to "API Key" so
existing installs work unchanged. Affects five touchpoints:

  - claude-env.sh: new default + uses ${OP_FIELD} in lookup + updated
    diagnostic block
  - claudestart.ps1: new default + adds OP_FIELD (and OP_ACCOUNT — same
    fragility class) to the local.env regex + uses $OP_Field in lookup
    + updated diagnostic block
  - install.sh: prompts for "1Password field name" alongside item, reads
    existing value as default, writes OP_FIELD line to local.env
  - install.ps1: matching prompt + serialization

Backwards-compatible: existing local.env files without OP_FIELD continue
to work because each wrapper sets the default before sourcing/parsing
local.env. Users get the override capability when they re-run the
installer (which preserves their current values as prompt defaults).

Verified: setting OP_FIELD="custom-name" in local.env propagates
correctly to the runtime variable; all lookup sites use the variable
(only default-value declarations and comments still mention "API Key").
After the user enters OP_ITEM, call \`op item get\` to enumerate the
item's actual fields and show them as a numbered list. User can either
type the field name or pick by number. Falls back to the free-form
prompt with a warning if op enumeration fails (op not installed, not
signed in, item doesn't exist).

Implementation notes:

  - \`op item get\` does NOT accept the op://Vault/Item syntax (only
    \`op read\` does). The installer parses op://Vault/Item into
    --vault and item-name args.
  - JSON parsing without jq: scope to the "fields" array via awk,
    then grep field labels. URL entries also have "label" keys, so
    scoping is required to avoid showing "website" alongside actual
    fields.
  - Pretty-printed JSON has whitespace after colons; the regex
    tolerates it (\`"label":[[:space:]]*"..."\`).
  - PowerShell side uses ConvertFrom-Json which already filters
    correctly (only $parsed.fields[].label).

UX:

  Fields available in op://Employee/ai.apro.is litellm:
      [1] password
      [2] username
      [3] notesPlain
      [4] API Key
      [5] genai-azure
      [6] management

  1Password field name (or number) [API Key]: 4

User can type "4", "API Key", or just press Enter for the default.
@busla busla merged commit 09d29c8 into main May 11, 2026
busla added a commit that referenced this pull request May 11, 2026
Followups from #13. Two issues users hit on main:

1. install.ps1:127 used "$OpItem:" — PowerShell parses $Var: as a
   drive-qualified variable lookup ($env:USER syntax) and errors out
   on the entire script. Wrap with ${OpItem} to delimit.

2. Pre-#13 local.env files have OP_ITEM with the field baked into the
   path (e.g. op://V/Item/API Key). Post-#13 the wrapper appends
   /${OP_FIELD} itself, producing bogus lookups like
   op://V/Item/API Key/API Key. The installer offered the legacy value
   as the default, so users who hit enter kept it broken.

   Fixed in two places (defense in depth):
   - install.sh / install.ps1: detect 3+ segment OP_ITEM in existing
     local.env, split trailing segment(s) into OP_FIELD, show user
     what changed before prompting.
   - claude-env.sh / claudestart.ps1: silently apply the same split
     after sourcing local.env, so users who pull new code without
     reinstalling still get correct behavior on next launch.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant