# Hemmelig CLI The Hemmelig CLI allows you to create encrypted secrets directly from the command line, making it ideal for automation, CI/CD pipelines, and scripting. ``` _ _ _ _ | | | | ___ _ __ ___ _ __ ___ ___| (_) __ _ | |_| |/ _ \ '_ ` _ \| '_ ` _ \ / _ \ | |/ _` | | _ | __/ | | | | | | | | | | __/ | | (_| | |_| |_|\___|_| |_| |_|_| |_| |_|\___|_|_|\__, | |___/ ``` ## Installation ### Binary (Recommended for CI/CD) Download the pre-built binary for your platform from the [CLI releases](https://github.com/HemmeligOrg/Hemmelig.app/releases?q=cli-v&expanded=true). Replace `VERSION` below with the desired version (e.g., `1.0.0`): #### Linux (amd64) ```bash VERSION=1.0.1 curl -L https://github.com/HemmeligOrg/Hemmelig.app/releases/download/cli-v${VERSION}/hemmelig-linux-amd64 -o hemmelig chmod +x hemmelig sudo mv hemmelig /usr/local/bin/ ``` #### Linux (arm64) ```bash VERSION=1.0.1 curl -L https://github.com/HemmeligOrg/Hemmelig.app/releases/download/cli-v${VERSION}/hemmelig-linux-arm64 -o hemmelig chmod +x hemmelig sudo mv hemmelig /usr/local/bin/ ``` #### macOS (Apple Silicon) ```bash VERSION=1.0.1 curl -L https://github.com/HemmeligOrg/Hemmelig.app/releases/download/cli-v${VERSION}/hemmelig-darwin-arm64 -o hemmelig chmod +x hemmelig sudo mv hemmelig /usr/local/bin/ ``` #### macOS (Intel) ```bash VERSION=1.0.1 curl -L https://github.com/HemmeligOrg/Hemmelig.app/releases/download/cli-v${VERSION}/hemmelig-darwin-amd64 -o hemmelig chmod +x hemmelig sudo mv hemmelig /usr/local/bin/ ``` #### Windows Download `hemmelig-windows-amd64.exe` from the [CLI releases](https://github.com/HemmeligOrg/Hemmelig.app/releases?q=cli-v&expanded=true) and add it to your PATH. #### Verify Download ```bash VERSION=1.0.1 # Download checksums curl -L https://github.com/HemmeligOrg/Hemmelig.app/releases/download/cli-v${VERSION}/checksums.txt -o checksums.txt # Verify integrity sha256sum -c checksums.txt --ignore-missing ``` ### npm ```bash # Install globally npm install -g hemmelig # Or use with npx (no installation required) npx hemmelig "my secret" ``` ## Usage ```bash hemmelig [options] ``` Or pipe content from stdin: ```bash echo "my secret" | hemmelig [options] cat file.txt | hemmelig [options] ``` ## Options | Option | Description | | ----------------------- | --------------------------------------------------- | | `-t, --title ` | Set a title for the secret | | `-p, --password <pass>` | Protect with a password (if not set, key is in URL) | | `-e, --expires <time>` | Expiration time (default: 1d) | | `-v, --views <number>` | Max views before deletion (default: 1, max: 9999) | | `-b, --burnable` | Burn after first view (default: true) | | `--no-burnable` | Don't burn after first view | | `-u, --url <url>` | Base URL (default: https://hemmelig.app) | | `-h, --help, /?` | Show help message | ### Expiration Times Valid expiration values: `5m`, `30m`, `1h`, `4h`, `12h`, `1d`, `3d`, `7d`, `14d`, `28d` ## Examples ### Basic Usage ```bash # Create a simple secret (expires in 1 day, 1 view) hemmelig "my secret message" # Create a secret with a title hemmelig "database_password=secret123" -t "Database Credentials" # Set custom expiration and view count hemmelig "temporary token" -e 1h -v 3 ``` ### Password Protection ```bash # Create a password-protected secret hemmelig "sensitive data" -p "mypassword123" ``` When password-protected, the recipient must enter the password to decrypt the secret. The URL will not contain the decryption key. ### Self-Hosted Instances ```bash # Use your own Hemmelig instance hemmelig "internal secret" -u https://secrets.company.com ``` ## CI/CD Integration The CLI is designed for automation. It outputs only the secret URL to stdout, making it easy to capture and use in scripts. ### GitHub Actions Share secrets securely between workflow jobs or with external parties: ```yaml name: Deploy on: [push] jobs: deploy: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Share deployment credentials run: | SECRET_URL=$(npx hemmelig "${{ secrets.DEPLOY_KEY }}" \ -t "Deployment Key" \ -e 1h \ -v 1 \ -u https://secrets.company.com) echo "Secure link: $SECRET_URL" # Send to Slack, email, etc. ``` ### GitLab CI ```yaml share-credentials: stage: deploy script: - | SECRET_URL=$(npx hemmelig "$DB_PASSWORD" \ -t "Database Password" \ -e 4h \ -u https://secrets.company.com) echo "Secret URL: $SECRET_URL" ``` ### Jenkins Pipeline ```groovy pipeline { agent any stages { stage('Share Secret') { steps { script { def secretUrl = sh( script: ''' npx hemmelig "${API_KEY}" \ -t "API Key for deployment" \ -e 1h \ -u https://secrets.company.com ''', returnStdout: true ).trim() echo "Secret available at: ${secretUrl}" } } } } } ``` ## Automation Use Cases ### Secure Credential Handoff When onboarding new team members or sharing credentials with contractors: ```bash #!/bin/bash # generate-access.sh DB_CREDS="host: db.internal.com user: app_user password: $(openssl rand -base64 32)" SECRET_URL=$(echo "$DB_CREDS" | hemmelig \ -t "Database Access - $(date +%Y-%m-%d)" \ -e 24h \ -v 1) echo "Send this link to the new team member: $SECRET_URL" ``` ### Automated Secret Rotation Share rotated secrets with dependent services: ```bash #!/bin/bash # rotate-and-share.sh NEW_PASSWORD=$(openssl rand -base64 24) # Update the password in your system update_service_password "$NEW_PASSWORD" # Share with the dependent team SECRET_URL=$(hemmelig "$NEW_PASSWORD" \ -t "Rotated Service Password" \ -e 1h \ -v 1 \ -u https://secrets.company.com) # Notify via Slack curl -X POST "$SLACK_WEBHOOK" \ -H 'Content-Type: application/json' \ -d "{\"text\": \"Password rotated. New credentials: $SECRET_URL\"}" ``` ### Sharing Build Artifacts Securely ```bash #!/bin/bash # share-artifact.sh # Generate a signed URL or token for the artifact ARTIFACT_TOKEN=$(generate_artifact_token) SECRET_URL=$(hemmelig "$ARTIFACT_TOKEN" \ -t "Build Artifact Access Token" \ -e 4h \ -v 5) echo "Artifact access link: $SECRET_URL" ``` ### Emergency Access Credentials Create break-glass credentials that self-destruct: ```bash #!/bin/bash # emergency-access.sh EMERGENCY_CREDS=$(cat << EOF Emergency Admin Access ====================== URL: https://admin.company.com Username: emergency_admin Password: $(openssl rand -base64 32) MFA Backup: $(generate_mfa_backup) This access expires in 1 hour. EOF ) SECRET_URL=$(echo "$EMERGENCY_CREDS" | hemmelig \ -t "Emergency Access Credentials" \ -e 1h \ -v 1 \ -p "emergency-$(date +%s)") echo "Emergency access: $SECRET_URL" echo "Password hint: emergency-[unix timestamp]" ``` ## Programmatic Usage The CLI can also be used as a library in your Node.js projects: ```typescript import { createSecret } from 'hemmelig'; const result = await createSecret({ secret: 'my secret message', title: 'API Key', expiresIn: '1h', views: 1, burnable: true, baseUrl: 'https://hemmelig.app', // optional }); console.log(result.url); // https://hemmelig.app/secret/abc123#decryptionKey=... console.log(result.id); // abc123 ``` ### API Reference #### `createSecret(options: SecretOptions): Promise<CreateSecretResult>` | Option | Type | Default | Description | | ----------- | --------------- | ------------------------ | ----------------------------- | | `secret` | `string` | required | The secret content to encrypt | | `title` | `string` | - | Optional title | | `password` | `string` | - | Password protection | | `expiresIn` | `ExpirationKey` | `'1d'` | Expiration time | | `views` | `number` | `1` | Max views (1-9999) | | `burnable` | `boolean` | `true` | Burn on first view | | `baseUrl` | `string` | `'https://hemmelig.app'` | Server URL | **Returns:** | Property | Type | Description | | ----------- | -------- | ----------------------------- | | `url` | `string` | Full URL to access the secret | | `id` | `string` | The secret ID | | `expiresIn` | `string` | The expiration time set | ## Security Notes - **Client-side encryption**: All encryption happens locally before data is sent to the server - **Zero-knowledge**: The server never sees your plaintext secrets or encryption keys - **URL fragments**: When not using a password, the decryption key is in the URL fragment (`#decryptionKey=...`), which is never sent to the server - **Self-destructing**: Secrets are automatically deleted after the specified views or expiration time ## Troubleshooting ### Secret Creation Fails If you're using a self-hosted instance and secret creation fails, ensure: 1. The instance URL is correct and accessible 2. The server is running and healthy 3. CORS is configured to allow requests from the CLI origin ### Piped Content Issues When piping content, the CLI preserves all internal newlines and formatting. Only trailing whitespace is trimmed. ```bash # This preserves the JSON formatting cat config.json | hemmelig -t "Config" ```