Initial commit
This commit is contained in:
12
.claude-plugin/plugin.json
Normal file
12
.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "local-env-file-management",
|
||||||
|
"description": "Tools to populate local .env files from 1password secrets.",
|
||||||
|
"version": "0.0.0-2025.11.28",
|
||||||
|
"author": {
|
||||||
|
"name": "Dennis Somerville",
|
||||||
|
"email": "densom@users.noreply.github.com"
|
||||||
|
},
|
||||||
|
"commands": [
|
||||||
|
"./commands"
|
||||||
|
]
|
||||||
|
}
|
||||||
3
README.md
Normal file
3
README.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# local-env-file-management
|
||||||
|
|
||||||
|
Tools to populate local .env files from 1password secrets.
|
||||||
102
commands/env-add.md
Normal file
102
commands/env-add.md
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
---
|
||||||
|
description: Add a new environment variable to .env.1password template and optionally to 1Password
|
||||||
|
argument-hint: <VAR_NAME> [op-reference-or-value]
|
||||||
|
---
|
||||||
|
|
||||||
|
You are tasked with adding a new environment variable to the `.env.1password` template file and optionally creating or updating the corresponding secret in 1Password.
|
||||||
|
|
||||||
|
## Instructions:
|
||||||
|
|
||||||
|
1. **Parse arguments**:
|
||||||
|
- First argument (required): The variable name (e.g., `API_KEY`)
|
||||||
|
- Second argument (optional): Either:
|
||||||
|
- A 1Password reference like `op://Private/myapp/api_key`
|
||||||
|
- A value to be stored in 1Password
|
||||||
|
- If not provided, ask the user for input
|
||||||
|
|
||||||
|
2. **Check for .env.1password**: Look for the template file in the current working directory.
|
||||||
|
- If it doesn't exist, ask if the user wants to create it (and offer to run `/claude-1password:env-init` if a `.env` exists)
|
||||||
|
|
||||||
|
3. **Check if variable already exists**:
|
||||||
|
- If the variable name already exists in `.env.1password`, ask if they want to update it
|
||||||
|
- Show the current value/reference before updating
|
||||||
|
|
||||||
|
4. **Determine the 1Password reference**:
|
||||||
|
|
||||||
|
**Option A**: If the second argument looks like a 1Password reference (`op://...`):
|
||||||
|
- Use it as-is
|
||||||
|
- Verify it's valid by trying `op read "reference"` (optional, warn if it fails)
|
||||||
|
|
||||||
|
**Option B**: If the second argument is a value (not starting with `op://`):
|
||||||
|
- Ask the user for the 1Password item details:
|
||||||
|
- Vault name (default: "Private")
|
||||||
|
- Item name (suggest based on project or existing pattern)
|
||||||
|
- Field name (default: variable name in lowercase)
|
||||||
|
- Offer to create the item/field in 1Password using the CLI:
|
||||||
|
```bash
|
||||||
|
op item create --category=password --title="item-name" \
|
||||||
|
--vault="vault-name" field-name="value"
|
||||||
|
```
|
||||||
|
Or if the item exists, update it:
|
||||||
|
```bash
|
||||||
|
op item edit "item-name" --vault="vault-name" field-name="value"
|
||||||
|
```
|
||||||
|
- Construct the reference: `op://vault/item/field`
|
||||||
|
|
||||||
|
**Option C**: If no second argument provided:
|
||||||
|
- Ask the user whether they want to:
|
||||||
|
1. Provide an existing 1Password reference
|
||||||
|
2. Provide a value to store in 1Password
|
||||||
|
3. Leave it as a placeholder for manual editing later
|
||||||
|
|
||||||
|
5. **Update .env.1password**:
|
||||||
|
- Add the new variable in the format: `VAR_NAME=op://vault/item/field`
|
||||||
|
- Optionally add a comment above it if the user wants to document it
|
||||||
|
- Maintain alphabetical order or append to the end (ask user preference)
|
||||||
|
|
||||||
|
6. **Optionally update .env**:
|
||||||
|
- Ask if they want to immediately sync to `.env` by running `/claude-1password:env-sync`
|
||||||
|
- Or just update `.env.1password` for now
|
||||||
|
|
||||||
|
7. **Output summary**: Show the user:
|
||||||
|
- The variable that was added: `VAR_NAME=op://...`
|
||||||
|
- Whether it was also created/updated in 1Password
|
||||||
|
- Next steps (e.g., "Run `/claude-1password:env-sync` to update your `.env` file")
|
||||||
|
|
||||||
|
## Examples:
|
||||||
|
|
||||||
|
### Example 1: Add with existing 1Password reference
|
||||||
|
```
|
||||||
|
/claude-1password:env-add NEW_API_KEY op://Private/myapp/new_api_key
|
||||||
|
```
|
||||||
|
|
||||||
|
Result in `.env.1password`:
|
||||||
|
```
|
||||||
|
NEW_API_KEY=op://Private/myapp/new_api_key
|
||||||
|
```
|
||||||
|
|
||||||
|
### Example 2: Add with a new value
|
||||||
|
```
|
||||||
|
/claude-1password:env-add STRIPE_KEY sk_test_abc123
|
||||||
|
```
|
||||||
|
|
||||||
|
You would then:
|
||||||
|
1. Ask for vault/item/field details (or use smart defaults)
|
||||||
|
2. Create/update in 1Password
|
||||||
|
3. Add to `.env.1password` with the generated reference
|
||||||
|
|
||||||
|
### Example 3: Add placeholder for manual editing
|
||||||
|
```
|
||||||
|
/claude-1password:env-add DATABASE_PASSWORD
|
||||||
|
```
|
||||||
|
|
||||||
|
You would prompt for what to do, and potentially add:
|
||||||
|
```
|
||||||
|
DATABASE_PASSWORD=op://Private/myapp/database_password
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling:
|
||||||
|
|
||||||
|
- If 1Password CLI is not installed or not authenticated, warn the user but still allow adding to `.env.1password` as a placeholder
|
||||||
|
- If variable name is invalid (contains spaces, special chars except `_`), suggest a corrected name
|
||||||
|
- If 1Password operation fails, show the error but still update the template file
|
||||||
65
commands/env-init.md
Normal file
65
commands/env-init.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
description: Initialize a .env.1password template from an existing .env file
|
||||||
|
argument-hint: [path-to-env-file]
|
||||||
|
---
|
||||||
|
|
||||||
|
You are tasked with creating a `.env.1password` template file from an existing `.env` file.
|
||||||
|
|
||||||
|
## Instructions:
|
||||||
|
|
||||||
|
1. **Read the .env file**: If the user provided a path argument, use that path. Otherwise, look for `.env` in the current working directory.
|
||||||
|
|
||||||
|
2. **Parse the file**: Extract all environment variable key-value pairs. Ignore:
|
||||||
|
- Empty lines
|
||||||
|
- Lines starting with `#` (comments)
|
||||||
|
- Malformed lines without `=`
|
||||||
|
|
||||||
|
3. **Generate template**: For each variable, create a line in the format:
|
||||||
|
```
|
||||||
|
VAR_NAME=op://vault-name/item-name/field-name
|
||||||
|
```
|
||||||
|
|
||||||
|
You should:
|
||||||
|
- Keep the variable name exactly as it appears
|
||||||
|
- For the 1Password reference, suggest a sensible structure:
|
||||||
|
- `vault-name`: Default to "Private" or ask the user
|
||||||
|
- `item-name`: Use a descriptive name based on the project or variable context
|
||||||
|
- `field-name`: Use the variable name in lowercase or the actual field name in 1Password
|
||||||
|
|
||||||
|
Example transformation:
|
||||||
|
```
|
||||||
|
DATABASE_URL=postgresql://localhost:5432/mydb
|
||||||
|
API_KEY=abc123secret
|
||||||
|
```
|
||||||
|
|
||||||
|
Becomes:
|
||||||
|
```
|
||||||
|
DATABASE_URL=op://Private/project-secrets/database_url
|
||||||
|
API_KEY=op://Private/project-secrets/api_key
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Add security header**: Prepend or update the security comment to the top of the generated `.env.1password` file:
|
||||||
|
```
|
||||||
|
# This file was auto-generated from .env.1password
|
||||||
|
# DO NOT commit this file to version control
|
||||||
|
# Generated on: [current date/time]
|
||||||
|
|
||||||
|
```
|
||||||
|
(Note the blank line after the header)
|
||||||
|
|
||||||
|
If the `.env.1password` template file already exists, check for the security header and add it if it does not exist.
|
||||||
|
|
||||||
|
5. **Preserve comments**: Keep any comment lines from the original file to maintain documentation.
|
||||||
|
|
||||||
|
6. **Write the template**: Save the result as `.env.1password` in the same directory as the source `.env` file.
|
||||||
|
|
||||||
|
7. **Output summary**: Show the user:
|
||||||
|
- How many variables were converted
|
||||||
|
- The path to the new `.env.1password` file
|
||||||
|
- A reminder to update the 1Password references to match their actual vault structure
|
||||||
|
- Instructions: "Edit `.env.1password` to update the `op://` references to match your 1Password vault, item, and field names. Then run `/claude-1password:env-sync` to generate your `.env` file."
|
||||||
|
|
||||||
|
## Error Handling:
|
||||||
|
|
||||||
|
- If the `.env` file doesn't exist, inform the user and ask if they want to create a new empty template
|
||||||
|
- If `.env.1password` already exists, ask if they want to overwrite it
|
||||||
91
commands/env-sync.md
Normal file
91
commands/env-sync.md
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
description: Populate .env file from .env.1password template using 1Password CLI
|
||||||
|
argument-hint: [path-to-template]
|
||||||
|
---
|
||||||
|
|
||||||
|
You are tasked with generating a `.env` file by resolving 1Password secret references from a `.env.1password` template file.
|
||||||
|
|
||||||
|
## Prerequisites Check:
|
||||||
|
|
||||||
|
1. **Verify 1Password CLI is installed**: Run `op --version` to check if the 1Password CLI is available.
|
||||||
|
- If not installed, inform the user to install it from https://developer.1password.com/docs/cli/get-started/
|
||||||
|
|
||||||
|
2. **Verify 1Password CLI is authenticated**: Run `op account list` to check if the user is signed in.
|
||||||
|
- If not authenticated, inform the user to run `op signin` first
|
||||||
|
|
||||||
|
## Instructions:
|
||||||
|
|
||||||
|
1. **Locate the template file**: If the user provided a path argument, use that path. Otherwise, look for `.env.1password` in the current working directory.
|
||||||
|
- If `.env.1password` doesn't exist, inform the user and suggest running `/claude-1password:env-init` first
|
||||||
|
|
||||||
|
2. **Check if .env already exists**:
|
||||||
|
- If `.env` already exists, ask the user if they want to overwrite it
|
||||||
|
- Consider backing up the existing `.env` as `.env.backup` before overwriting
|
||||||
|
|
||||||
|
3. **Use op inject command**: Use the 1Password CLI `op inject` command to resolve all secret references in the template file and generate the `.env` file.
|
||||||
|
|
||||||
|
The basic command syntax is:
|
||||||
|
```bash
|
||||||
|
op inject -i .env.1password -o .env
|
||||||
|
```
|
||||||
|
|
||||||
|
The `op inject` command will:
|
||||||
|
- Automatically find all `op://vault/item/field` references in the template
|
||||||
|
- Resolve them by fetching the secrets from 1Password
|
||||||
|
- Replace the references with the actual secret values
|
||||||
|
- Preserve all comments, empty lines, and non-secret values exactly as they appear
|
||||||
|
- Handle multiple references on a single line
|
||||||
|
- Provide clear error messages if any references are invalid or inaccessible
|
||||||
|
|
||||||
|
If the user opted to overwrite the existing file, make sure to use the `--force` flag in the op command.
|
||||||
|
|
||||||
|
4. **Output summary**: Show the user:
|
||||||
|
- Success message: "Successfully generated .env from .env.1password"
|
||||||
|
- The path to the generated `.env` file
|
||||||
|
- Number of secret references that were resolved (count `op://` occurrences in the template)
|
||||||
|
- A reminder to add `.env` to `.gitignore` if not already present
|
||||||
|
- Security reminder: "Remember to delete this file when no longer needed"
|
||||||
|
|
||||||
|
## Example:
|
||||||
|
|
||||||
|
Template (`.env.1password`):
|
||||||
|
```
|
||||||
|
# Database configuration
|
||||||
|
DATABASE_URL=op://Private/myapp/database_url
|
||||||
|
API_KEY=op://Private/myapp/api_key
|
||||||
|
|
||||||
|
# Non-secret values can be stored directly
|
||||||
|
NODE_ENV=development
|
||||||
|
```
|
||||||
|
|
||||||
|
Command executed:
|
||||||
|
```bash
|
||||||
|
op inject -i .env.1password -o .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Generated (`.env`):
|
||||||
|
```
|
||||||
|
# Database configuration
|
||||||
|
DATABASE_URL=postgresql://user:pass@localhost:5432/db
|
||||||
|
API_KEY=sk_live_abc123xyz789
|
||||||
|
|
||||||
|
# Non-secret values can be stored directly
|
||||||
|
NODE_ENV=development
|
||||||
|
```
|
||||||
|
|
||||||
|
## Additional Options:
|
||||||
|
|
||||||
|
- **Force overwrite**: If you want to skip the overwrite confirmation, you can add the `--force` flag: `op inject -i .env.1password -o .env --force`
|
||||||
|
- **In-memory only**: To output to stdout without writing a file (useful for verification): `op inject -i .env.1password`
|
||||||
|
- **Different paths**: You can specify any template and output paths: `op inject -i path/to/template -o path/to/.env`
|
||||||
|
|
||||||
|
## Error Handling:
|
||||||
|
|
||||||
|
- If `.env.1password` doesn't exist, inform the user and suggest running `/claude-1password:env-init` first
|
||||||
|
- If `.env` already exists, ask if they want to overwrite it
|
||||||
|
- If `op inject` fails, show the specific error message from the CLI and suggest solutions:
|
||||||
|
- **"not signed in"**: User needs to run `op signin`
|
||||||
|
- **"item not found"** or **"vault not found"**: Check that the `op://` references in `.env.1password` match actual items in 1Password
|
||||||
|
- **"field not found"**: Verify the field name exists in the 1Password item
|
||||||
|
- For any errors, show which reference(s) caused the problem to help the user debug
|
||||||
|
- If the command succeeds but the output seems incorrect, suggest the user manually verify their 1Password references
|
||||||
53
plugin.lock.json
Normal file
53
plugin.lock.json
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
{
|
||||||
|
"$schema": "internal://schemas/plugin.lock.v1.json",
|
||||||
|
"pluginId": "gh:densom/claude-1password:plugins/1password",
|
||||||
|
"normalized": {
|
||||||
|
"repo": null,
|
||||||
|
"ref": "refs/tags/v20251128.0",
|
||||||
|
"commit": "f30e98bedfec7f21e3aefd73b36cae33f1efa34d",
|
||||||
|
"treeHash": "b3f64f25abd79765d39a63b4f7b3bcfd8c13e8d1f8196cf4cac5042a477e4d02",
|
||||||
|
"generatedAt": "2025-11-28T10:16:18.123744Z",
|
||||||
|
"toolVersion": "publish_plugins.py@0.2.0"
|
||||||
|
},
|
||||||
|
"origin": {
|
||||||
|
"remote": "git@github.com:zhongweili/42plugin-data.git",
|
||||||
|
"branch": "master",
|
||||||
|
"commit": "aa1497ed0949fd50e99e70d6324a29c5b34f9390",
|
||||||
|
"repoRoot": "/Users/zhongweili/projects/openmind/42plugin-data"
|
||||||
|
},
|
||||||
|
"manifest": {
|
||||||
|
"name": "local-env-file-management",
|
||||||
|
"description": "Tools to populate local .env files from 1password secrets.",
|
||||||
|
"version": null
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"path": "README.md",
|
||||||
|
"sha256": "de26a26814ddfa74a1f75d812e19efd6ddfac6b26c2f1eafd6c81c6c4c2749a3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": ".claude-plugin/plugin.json",
|
||||||
|
"sha256": "5c355ae73cb06b029b17b19b7fc3fafb80261104aeef62ad6003bf973c03352a"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/env-init.md",
|
||||||
|
"sha256": "b0492607d02ecbf36feae389e28e488ba02be3e0fecd9d35fc202d11f0d37e3b"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/env-add.md",
|
||||||
|
"sha256": "25a1495bc79786b462f1934f5ed35f9e76c085c41797f5e7f768b5f73348214e"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "commands/env-sync.md",
|
||||||
|
"sha256": "19bd685da4369ec90cf9fbc5ffab09228f91c1a5e654fa5261db0fd34c1a953e"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dirSha256": "b3f64f25abd79765d39a63b4f7b3bcfd8c13e8d1f8196cf4cac5042a477e4d02"
|
||||||
|
},
|
||||||
|
"security": {
|
||||||
|
"scannedAt": null,
|
||||||
|
"scannerVersion": null,
|
||||||
|
"flags": []
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user