opencode-1password-auth
v1.0.18
Published
1Password integration for OpenCode - authenticate providers and inject MCP secrets from 1Password environments
Downloads
2,140
Maintainers
Readme
OpenCode 1Password Auth Plugin
Authenticate LLM providers and inject MCP server secrets from 1Password environments.
⚠️ Important Note
OpenCode does NOT resolve {env:VAR} syntax in auth.json. This plugin works around this limitation by:
- Setting API keys via
client.auth.set()at runtime - Setting environment variables in
process.envfor MCP servers - Using
{env:VAR}references in config files for MCP servers only
Version 1.0.6+ includes critical timing fixes - the plugin now initializes immediately when loaded, not waiting for the server.connected event.
🚀 Quick Start
Run setup script:
# Windows .\setup.ps1 # macOS/Linux ./setup.shUpdate config files:
.\setup.ps1 -UpdateConfigAdd to OpenCode config (
~/.config/opencode/opencode.json):{ "plugin": ["opencode-1password-auth"] }Restart OpenCode completely
Check debug logs at
~/.opencode-1password-debug/debug.log
Features
- Provider Authentication: Automatically authenticate OpenCode providers (MiniMax, DeepSeek, OpenCode, etc.) from 1Password at runtime
- MCP Secret Injection: Inject secrets into MCP server environments from 1Password
- .env Access Warning: Warns when .env files are accessed
- Config File Management: Automatically update config files to use
{env:VAR}references (for MCP servers) - Debug Logging: Detailed logs at
~/.opencode-1password-debug/debug.log - Agent Hook Validation: Validates mounted 1Password FIFOs before shell execution for secure secret access
Prerequisites
1. 1Password Account
- 1Password account (西牙, Business, or Teams plan for service accounts)
- Ability to create environments and service accounts
2. 1Password Service Account
Create a service account in 1Password:
- Go to Settings > Service Accounts in 1Password
- Create a new service account with Read permissions to your vaults
- Copy the token - you'll need it for
OP_SERVICE_ACCOUNT_TOKEN
3. 1Password Environments
Create these environments in 1Password:
Config Environment (holds environment IDs):
OPENCODE_PROVIDERS_ENV_ID- Environment ID containing provider API keysOPENCODE_MCPS_ENV_ID- Environment ID containing MCP server secrets
Providers Environment (holds API keys):
- Variable names should match provider IDs (case-insensitive, underscores converted to hyphens)
- Examples:
opencode,OPENCODE,deepseek,DEEPSEEK,minimax-coding-plan,MINIMAX_CODING_PLAN - The plugin normalizes: lowercase + underscores → hyphens
- API keys as values
MCPS Environment (holds MCP secrets):
- Secret names matching your MCP server config (e.g.,
MINIMAX_API_KEY,MINIMAX_API_HOST)
Variable Naming Guide
The plugin normalizes variable names to match auth.json provider IDs:
| 1Password Variable | Normalized Provider ID | auth.json Key |
|-------------------|------------------------|---------------|
| MINIMAX_CODING_PLAN | minimax-coding-plan | minimax-coding-plan |
| OPENCODE | opencode | opencode |
| DEEPSEEK | deepseek | deepseek |
| minimax_coding_plan | minimax-coding-plan | minimax-coding-plan |
| open_code | open-code | open-code |
Rules:
- Variable names are case-insensitive
- Underscores (
_) are converted to hyphens (-) - The plugin sets environment variables in multiple formats for compatibility
- MCP variable names should match exactly what your MCP server expects
Setup
1. Run Setup Script
Use the provided setup script to configure environment variables:
Windows:
.\setup.ps1macOS/Linux:
./setup.shThe script will:
- Prompt for your 1Password service account token
- Prompt for your bootstrap environment ID
- Save environment variables to your system
- Verify the 1Password connection works
- Show a full audit of your configuration
Script Options:
.\setup.ps1- Interactive setup (default).\setup.ps1 -Audit- View current configuration without making changes.\setup.ps1 -UpdateConfig- Critical: Updateauth.jsonandopencode.jsonto use{env:VAR}references.\setup.ps1 -Uninstall- Remove environment variables
⚠️ IMPORTANT: You MUST run
.\setup.ps1 -UpdateConfigafter setting up environment variables to update your config files.
2. Install Plugin
Add to your opencode.json:
{
"plugin": ["opencode-1password-auth"]
}OpenCode will automatically install the plugin on next startup.
Architecture: Config as Index
The plugin uses a config environment as an index to your other environments. This design:
- Keeps your actual secrets isolated in dedicated environments
- Allows you to switch configurations by changing only
OP_CONFIG_ENV_ID - Enables different configs for dev/staging/prod
Config Environment
opencode-config
├── OPENCODE_PROVIDERS_ENV_ID = abc123... (ID of providers env)
├── OPENCODE_MCPS_ENV_ID = def456... (ID of mcps env)
└── OPENCODE_PLUGINS_ENV_ID = ghi789... (ID of plugins env, optional)To change configurations, simply update OP_CONFIG_ENV_ID to point to a different config environment.
Providers Environment
opencode-providers
├── opencode = your-opencode-api-key # or OPENCODE
├── deepseek = your-deepseek-api-key # or DEEPSEEK
└── minimax-coding-plan = your-minimax-api-key # or MINIMAX_CODING_PLANMCPS Environment
opencode-mcps
├── MINIMAX_API_KEY = your-minimax-api-key
└── MINIMAX_API_HOST = https://api.minimax.ioMCP Configuration
In your opencode.json, use {env:VARIABLE_NAME} syntax to reference injected secrets. This works for MCP servers because the plugin injects environment variables via the shell.env hook:
{
"mcp": {
"MiniMax": {
"type": "local",
"command": ["uvx", "minimax-coding-plan-mcp"],
"environment": {
"MINIMAX_API_KEY": "{env:MINIMAX_API_KEY}",
"MINIMAX_API_HOST": "{env:MINIMAX_API_HOST}"
}
}
}
}Note: While
{env:VAR}syntax works for MCP servers inopencode.json, it does NOT work for provider authentication inauth.json. For providers, the plugin usesclient.auth.set()instead.
How It Works (v1.0.10+)
- Immediate Initialization: When OpenCode loads the plugin, it immediately:
- Creates 1Password SDK client using
OP_SERVICE_ACCOUNT_TOKEN - Reads bootstrap environment ID from
OP_CONFIG_ENV_ID - Retrieves provider and MCP environment IDs
- Creates 1Password SDK client using
- Provider Authentication:
- Reads API keys from 1Password providers environment
- Sets
process.envvariables with multiple naming formats (e.g.,opencode,OPENCODE,opencode,OPENCODE) - Calls
client.auth.set()to authenticate each provider at runtime
- MCP Secret Injection:
- Reads secrets from 1Password MCP environment
- Injects them via the
shell.envhook when MCP servers start
- Config File Management:
- Updates
auth.jsonto use{env:providerId}references (though OpenCode doesn't resolve these) - Updates
opencode.jsonMCP config to use{env:VAR}references (which DO work for MCP)
- Updates
Authentication Flow
graph TD
A[OpenCode starts] --> B[Load 1Password Plugin]
B --> C[Immediate initialization]
C --> D{Read 1Password config}
D --> E[Set process.env variables]
D --> F[Call client.auth.set()]
F --> G[Provider authenticated at runtime]
E --> H[MCP servers get env vars]
G --> I[Chat requests work]
H --> INote:
client.auth.set()happens AFTER OpenCode readsauth.json, so the plugin must initialize early enough to intercept authentication attempts.
Requirements
- OpenCode
- 1Password account with service account token
- Windows/macOS/Linux with environment variables set
Troubleshooting
Plugin not loading?
- Ensure environment variables are set system-wide (not just in terminal)
- Restart OpenCode completely after setting environment variables
- Check OpenCode console for plugin loading errors
Can't read 1Password environments?
- Verify service account has access to the vaults containing your environments
- Check that environment IDs in config are correct
- Run
.\setup.ps1 -Auditto verify connection and configuration
Authentication failing with "Your api key: ****eek} is invalid"?
This means OpenCode is reading the literal {env:deepseek} string from auth.json. The plugin needs to authenticate providers earlier.
Solutions:
- Update to v1.0.6+ - Includes critical timing fixes
- Check debug logs - Look at
~/.opencode-1password-debug/debug.log - Verify plugin is in opencode.json - Ensure
"opencode-1password-auth"is in the plugin array - Restart OpenCode - Completely quit and restart to reload the plugin
Debug Logging
The plugin writes detailed logs to ~/.opencode-1password-debug/debug.log. Check this file for:
- Plugin initialization status
- 1Password connection attempts
client.auth.set()calls and results- Environment variable injections
Common Issues
- Timing: If the plugin initializes too late, OpenCode already attempted authentication
- Environment Variables: Must be set system-wide, not just in current terminal
- 1Password Permissions: Service account needs read access to environments
- Variable Names: Provider names in 1Password should match auth.json provider IDs (case-insensitive, underscores converted to hyphens)
Agent Hook Validation
The Agent Hook Validation feature validates that 1Password's mounted FIFOs (named pipes) are accessible before shell commands execute. This ensures secure secret access when the 1Password desktop app is running.
How It Works
- Command Pattern Matching: Before executing a bash command, the plugin checks if the command contains patterns indicating secret usage (e.g.,
$,${) - Desktop App Detection: Checks if the 1Password desktop app is running by verifying
~/.1password/mounted/envs/exists - FIFO Validation: If desktop app is detected, validates that all FIFOs in the mounted directory are readable
- Fallback to Service Account: If desktop app is not available, the plugin falls back to using the Service Account for authentication
Integration with OpenCode: The plugin registers a tool.execute.before hook for the bash tool, intercepting all shell commands executed via OpenCode. Validation only runs for commands that match the configured patterns. The plugin also uses the shell.env hook for MCP secret injection (separate from validation).
Fallback Status: The Service Account fallback is now fully implemented (v1.0.17+). When the 1Password desktop app is unavailable, the plugin will validate that the Service Account can access the required 1Password environments before allowing command execution.
Configuration Options
| Environment Variable | Default | Description |
|---------------------|---------|-------------|
| OP_AGENT_HOOK_VALIDATION_ENABLED | false | Enable/disable FIFO validation before shell execution |
| OP_AGENT_HOOK_BLOCK_ON_FAILURE | true | Block command execution if validation fails |
| OP_AGENT_HOOK_VALIDATION_TIMEOUT | 5000 | Timeout in milliseconds for FIFO validation |
| OP_AGENT_HOOK_COMMAND_PATTERNS | ["$", "${"] | JSON array of patterns that trigger validation |
Examples
Enable validation with defaults:
# Windows
setx OP_AGENT_HOOK_VALIDATION_ENABLED true
# macOS/Linux
export OP_AGENT_HOOK_VALIDATION_ENABLED=trueEnable with custom timeout and patterns:
# Windows
setx OP_AGENT_HOOK_VALIDATION_TIMEOUT 10000
setx OP_AGENT_HOOK_COMMAND_PATTERNS '["$", "${", "env:", "OP_"]'
# macOS/Linux
export OP_AGENT_HOOK_VALIDATION_TIMEOUT=10000
export OP_AGENT_HOOK_COMMAND_PATTERNS='["$", "${", "env:", "OP_"]'Disable blocking on validation failure:
setx OP_AGENT_HOOK_BLOCK_ON_FAILURE falseTroubleshooting Agent Hook Validation
Commands are blocked even when 1Password is running:
- Verify
OP_AGENT_HOOK_VALIDATION_ENABLED=trueis set - Check that
~/.1password/mounted/envs/exists and contains FIFOs - Increase
OP_AGENT_HOOK_VALIDATION_TIMEOUTif validation is timing out - Review debug logs at
~/.opencode-1password-debug/debug.log
Validation passes but secrets aren't available:
- The desktop app may be running but not unlocked
- Check that the correct vaults are linked in 1Password
- Verify Service Account fallback works by checking logs
"Mount path does not exist" errors:
- Ensure 1Password desktop app is running with the CLI integration enabled
- On macOS, check System Settings > Privacy & Security > Full Disk Access for OpenCode
- Verify
~/.1password/mounted/envs/exists (create if missing:mkdir -p ~/.1password/mounted/envs)
FIFO validation timeout:
- Increase
OP_AGENT_HOOK_VALIDATION_TIMEOUT(e.g., 10000 for 10 seconds) - Check for slow network drives or anti-virus software interfering
- Consider setting
OP_AGENT_HOOK_BLOCK_ON_FAILURE=falseif validation is unreliable
Security Considerations
What Agent Hook Validation DOES:
- ✅ FIFO Accessibility Check: Validates that 1Password FIFOs exist and are readable at
~/.1password/mounted/envs/ - ✅ Desktop App Detection: Verifies the 1Password desktop app is running by checking mount directory existence
- ✅ Service Account Fallback: When desktop app is unavailable, falls back to validating Service Account access to required 1Password environments
- ✅ Configurable Blocking: Respects
OP_AGENT_HOOK_BLOCK_ON_FAILUREsetting to block commands when validation fails
What Agent Hook Validation DOES NOT do:
- ❌ Command Injection Prevention: Does NOT prevent command injection or sanitize shell commands
- ❌ Input Validation: Does NOT validate or sanitize command arguments or user input
- ❌ SQLite Mount Verification: Does NOT use sqlite3 or verify active mounts via 1Password's database (only checks FIFO existence/readability)
- ❌ Security Boundary: Is NOT a comprehensive security boundary for command execution
Important Security Notes:
- Limited Scope: The validation only ensures 1Password secret access mechanisms are available before commands execute
- Not a Sandbox: Commands execute with full shell privileges after validation passes
- Pattern Matching Only: Validation triggers based on simple string patterns (
$,${), not semantic analysis
Recommended Additional Security Measures:
- Input Validation: Implement command validation/sanitization in your application layer
- Command Whitelisting: Consider whitelisting allowed commands for sensitive operations
- Principle of Least Privilege: Run OpenCode with minimal necessary permissions
- Audit Logging: Monitor command execution in production environments
- Defense in Depth: Combine this validation with other security controls
Use Case: This validation is designed for development environments where 1Password desktop integration is used for secret access. For production deployments, consider implementing additional security controls appropriate for your threat model.
Current Status (v1.0.17)
✅ Implemented
- Provider Authentication:
client.auth.set()at runtime - MCP Secret Injection: Via
shell.envhook - Config File Management: Auto-update
auth.jsonandopencode.jsonwith-UpdateConfigflag - Debug Logging: File-based logging at
~/.opencode-1password-debug/debug.log - Variable Normalization: Multiple naming formats supported
- Immediate Initialization: Plugin loads early in OpenCode lifecycle
- Agent Hook Validation: FIFO validation before shell execution with desktop app detection and Service Account fallback
🔄 Working Around OpenCode Limitations
The plugin works around OpenCode's limitation of not resolving {env:VAR} in auth.json by:
- Calling
client.auth.set()to authenticate providers at runtime - Setting
process.envvariables for MCP servers - Using timing fixes in v1.0.6+ to initialize before authentication attempts
Roadmap
Phase 2 - Enhanced Scripting
- [ ] Automated service account creation - Guide users through creating service accounts with correct permissions via 1Password API
- [ ] Bootstrap environment management via scripts - Add, list, remove environment references from the bootstrap environment through CLI
- [ ] Cross-platform setup improvements - Better support for macOS/Linux setup scripts
Phase 3 - Advanced Plugin Features
- [ ] Dynamic environment detection - Plugin automatically detects new environments added to bootstrap and integrates them
- [x] Config file injection - ✅ Implemented (uses
-UpdateConfigflag) - [ ] Custom environment support - Support for additional environments beyond the standard opencode-providers, opencode-plugins, opencode-mcps pattern
- [ ] Write support - Ability to store secrets back to 1Password environments
- [ ] Auth.json workaround - Investigate alternative approaches if
client.auth.set()timing issues persist
Phase 4 - Polish & Reliability
- [ ] Uninstall script - Clean removal of environment variables and plugin configuration
- [ ] Configuration validation - Validate OpenCode config files reference correct environment variables
- [ ] Health checks - Periodic verification that 1Password connection and authentication are working
- [ ] Better error messages - User-friendly error reporting for common issues
Deployment
Publishing New Versions
- Update version in
package.json - Commit changes with descriptive message:
git add . git commit -m "Brief description of changes" - Tag the release (optional but recommended):
git tag v1.0.6 git push origin v1.0.6 - Publish to npm:
npm publish - Update GitHub:
git push origin master
Version History
- v1.0.12: Fix MCP config detection and inject environment variables into process.env
- v1.0.11: Robust SDK import with ESM/CommonJS fallback, improved error handling
- v1.0.10: SDK import fix - correct named import for createClient
- v1.0.9: Timing fixes - immediate initialization, config hook, enhanced logging, ESM structure
- v1.0.8: Windows compatibility - permission handling fixes
- v1.0.7: Manual publish after local plugin testing
- v1.0.6: Timing fixes - immediate initialization, config hook, enhanced logging
- v1.0.5: Debug logging and error handling improvements
- v1.0.4: Variable normalization and multiple env var formats
- v1.0.3: Setup scripts with config file modification
- v1.0.2: MCP secret injection and .env warnings
- v1.0.1: Initial release with basic provider authentication
License
MIT
