[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"project-81801":3},{"id":4,"name":5,"fullName":6,"owner":7,"repo":5,"description":8,"homepage":9,"htmlUrl":10,"language":11,"languages":10,"totalLinesOfCode":10,"stars":12,"forks":13,"watchers":14,"openIssues":15,"contributorsCount":16,"subscribersCount":16,"size":16,"stars1d":16,"stars7d":17,"stars30d":17,"stars90d":16,"forks30d":16,"starsTrendScore":16,"compositeScore":18,"rankGlobal":10,"rankLanguage":10,"license":19,"archived":20,"fork":20,"defaultBranch":21,"hasWiki":20,"hasPages":20,"topics":22,"createdAt":10,"pushedAt":10,"updatedAt":28,"readmeContent":29,"aiSummary":30,"trendingCount":16,"starSnapshotCount":16,"syncStatus":31,"lastSyncTime":32,"discoverSource":33},81801,"cottage","sayanarijit\u002Fcottage","sayanarijit","A modern git based age-encrypted secrets manager for teams.","https:\u002F\u002Fcottage-cli.pages.dev",null,"Rust",41,1,38,5,0,3,42.7,"Apache License 2.0",false,"main",[23,24,25,26,27],"commandline","encryption-decryption","git","gitops","secrets-management","2026-06-12 04:01:35","\u003Cp align=\"center\">\n  \u003Cpicture>\n    \u003Csource media=\"(prefers-color-scheme: dark)\" srcset=\"https:\u002F\u002Fs13.gifyu.com\u002Fimages\u002Fb7mxd.webp\">\n    \u003Csource media=\"(prefers-color-scheme: light)\" srcset=\"https:\u002F\u002Fs13.gifyu.com\u002Fimages\u002Fb7mxl.webp\">\n    \u003Cimg alt=\"The cottage logo\" width=\"600\" src=\"https:\u002F\u002Fs13.gifyu.com\u002Fimages\u002Fb7mxl.webp\">\n  \u003C\u002Fpicture>\n\u003C\u002Fp>\n\n[![Cottage Verify](https:\u002F\u002Fgithub.com\u002Fsayanarijit\u002Fcottage\u002Factions\u002Fworkflows\u002Fcottage-verify.yml\u002Fbadge.svg)](https:\u002F\u002Fgithub.com\u002Fsayanarijit\u002Fcottage\u002Factions\u002Fworkflows\u002Fcottage-verify.yml)\n[![Crates.io Version](https:\u002F\u002Fimg.shields.io\u002Fcrates\u002Fv\u002Fcottage)](https:\u002F\u002Fcrates.io\u002Fcrates\u002Fcottage)\n[![PyPI - Version](https:\u002F\u002Fimg.shields.io\u002Fpypi\u002Fv\u002Fcottage)](https:\u002F\u002Fpypi.org\u002Fproject\u002Fcottage\u002F)\n[![Docker Image Version](https:\u002F\u002Fimg.shields.io\u002Fdocker\u002Fv\u002Fsayanarijit\u002Fcottage?label=docker)](https:\u002F\u002Fhub.docker.com\u002Fr\u002Fsayanarijit\u002Fcottage)\n\n**cott*age*** is a GitOps tool for teams to manage [age-encrypted](https:\u002F\u002Fage-encryption.org\u002F) secrets in git repositories.\n\nIt provides a simple workflow to encrypt\u002Fdecrypt secrets, manage recipients, and keep\nsecrets out of the repo while still allowing for easy sharing via VCS. cottage also\ngenerates redacted previews of encrypted secrets for better visibility and supports both\npersistent and temporary decryption workflows, while ensuring secrets are never committed\nin plaintext.\n\n![Intro Demo](https:\u002F\u002Fvhs.charm.sh\u002Fvhs-6P2I0IyW7AJADjAEzVjOJP.gif)\n\n1. [Features](#features)\n2. [Installation](#installation)\n3. [Quick Start](#quick-start)\n4. [GitOps](#gitops)\n5. [Git Hooks](#git-hooks)\n6. [Access Control](#access-control)\n   1. [Rules](#rules)\n   2. [Verification](#verification)\n7. [Any Provider as Upstream](#any-provider-as-upstream)\n8. [Sync with any device](#sync-with-any-device)\n9. [Learn More](#learn-more)\n10. [Troubleshooting](#troubleshooting)\n11. [Comparison](#comparison)\n    1. [age vs Other Encryption](#age-vs-other-encryption)\n    2. [cottage vs SOPS](#cottage-vs-sops)\n    3. [cottage vs dotenvx](#cottage-vs-dotenvx)\n    4. [cottage vs agebox](#cottage-vs-agebox)\n12. [License](#license)\n\n## Features\n\n- **Exposure-safe**: Uses Rust's type system to make sure bugs can never accidentally expose secrets.\n- **Team-friendly**: Share public keys (recipients) in the repo, keep private keys (identities) local.\n- **Access Control**: Simple allow\u002Fdeny rules to control which secrets are encrypted for which recipients.\n- **Manages .gitignore**: Automatically updates `.gitignore` to keep unencrypted secrets out of the repo.\n- **Previews**: Generates timestamped redacted previews of encrypted secrets for better visibility.\n- **Rich diffs**: Keeps git diff clean & reviewable, while `ctg diff` shows diff of locally modified secrets with tracked encrypted counterparts.\n- **Checksum verification**: Prevents tampering by verifying that encrypted secrets and recipient lists match the metadata.\n- **Git hooks**: Easily set up git hooks to automatically check\u002Fencrypt secrets before commit and decrypt them after checkout.\n- **Persistent secrets workflow**: `ctg decrypt\u002Fedit\u002Fsync` keeps decrypted secrets on disk.\n- **Temporary secrets workflow**: `ctg run` (shortcut `ctgx`) decrypts secrets temporarily to run a command, then deletes them regardless of the command's success or failure.\n- **Environment injection workflow**: `ctg env` injects decrypted secrets as environment variables to run a command, without writing them to disk at all.\n- **Clean up**: `ctg clean` deletes all decrypted secrets from local repo to let you run your AI agents with a tiny bit less worry.\n- **Supports jj and non-git directories**: `ctg init` turns any directory into a secret store.\n- **Sync with any provider**: Lets you configure any provider with an API as the upstream, and start using `ctg pull\u002Fdiff\u002Fpush` like `git pull\u002Fdiff\u002Fpush`.\n- **Sync with any device**: Secrets encrypted with cottage and managed in a git repo can be synced across devices with [Cottage Sync](https:\u002F\u002Fcottage-sync.github.io).\n\n## Installation\n\n```bash\n# rust cargo-binstall\ncargo binstall --locked cottage\n\n# rust cargo\ncargo install --locked cottage\n\n# python pip\npip install cottage\n\n# python uv\nuv pip install cottage\n```\n\nAlso available as docker images:\n\n```bash\n# Docker\ndocker run --rm -v $PWD:\u002Fapp sayanarijit\u002Fcottage --version\n\n# Podman\npodman run --rm -v $PWD:\u002Fapp quay.io\u002Fsayanarijit\u002Fcottage --version\n```\n\nOr download the latest release from [GitHub](https:\u002F\u002Fgithub.com\u002Fsayanarijit\u002Fcottage\u002Freleases).\n\n## Quick Start\n\nInit project:\n\n```bash\nmkdir project && cd project\n\ngit init  # Optional, cottage works better with git but it's not required\nctg init  # Sets up the .cottage directory and necessary files\n\ntree -a\n# .\n# ├ .cottage\u002F           \u003C- Auto-generated by `ctg init`\n# │ ├ identity        \u003C- Your private key, keep it safe. Move it to `~\u002F.config\u002Fcottage\u002Fidentity` to use it globally, or replace it with a soft link to one of your existing private keys.\n# │ └ recipients\u002F     \u003C- This is where your team keeps the public keys of all the recipients.\n# │     └ sayanarijit \u003C- Your public key. Commit it. To use an existing public key, just copy (don't softlink) that key here.\n# ├ .git\u002F...\n# ├ .gitattributes      \u003C- Added `*.cott.age binary export-ignore filter=cottage-encrypted -diff` to avoid polluting git diff\n# └ .gitignore          \u003C- Added `\u002F.cottage\u002Fidentity` for obvious reasons\n\n# You can run `ctg clean --all` anytime to clean up everything cottage ever did.\n```\n\nCreate or edit a secret.\n\n```bash\nctg edit secret.yml --clean    # Opens secret.yml in $EDITOR\nctg encrypt secret.yml --clean # Another way to encrypt secrets\n# encrypt secret.yml\n#    into secret.yml.cott.age\n#    edit secret.yml.cott.toml\n#    edit .gitignore\n# delete secret.yml\n```\n\nRun a command with temporary decrypted secrets:\n\n```bash\ncat secret.yml\n# cat: secret.yml: No such file or directory\n\nctg run kubectl apply -f secret.yml          # decrypts secret.yml.cott.age to secret.yml and runs the command\nctg run kubectl apply -f secret.yml.cott.age # also replaces the path argument with the decrypted file path\nctg run kubectl apply -f .                   # decrypts all .cott.age files in . and runs the command\nctg run .\u002Fdeploy.sh                          # decrypts all .cott.age files in repo and runs the command\n\ncat secret.yml\n# cat: secret.yml: No such file or directory\n```\n\nOr use the shortcut:\n\n```bash\nctgx .\u002Fdeploy.sh  # same as ctg run -- .\u002Fdeploy.sh\n```\n\nRun a command with secrets injected as environment variables, without writing to disk at all:\n\n```bash\nctg env -- .\u002Fdeploy.sh # Export secrets from .env.cott.age (default) without writing them to disk, then run deploy.sh\nctg env -F .env.prod.cott.age -- .\u002Fdeploy.sh # exports from .env.prod.cott.age instead of .env.cott.age\nctg env -F secrets.json.cott.age -- printenv COTTAGE_SECRET # Also supports non-dotenv files.\n```\n\n## GitOps\n\nTo share your secrets with team members, just push to the git repo.\n\n```bash\ngit add .\ngit commit -m \"Add secret.yml\"\ngit push origin main\n```\n\nAsk your teammates to add their public keys to `.cottage\u002Frecipients` and push the\nchanges. Then you can pull and re-encrypt the secrets for them.\n\n```bash\ngit pull origin main\n\nctg sync  # or `ctg decrypt && ctg encrypt`\n# encrypt secret.yml\n#    into secret.yml.cott.age\n#    edit secret.yml.cott.toml\n\nctg clean  # optional\n# delete secret.yml\n\n# review changes, commit and push\ngit add .\ngit commit -m \"Add new recipient to secrets\"\ngit push origin main\n```\n\nNow your teammates can pull the latest changes and decrypt secrets for themselves.\n\n## Git Hooks\n\nYou can use [prek](https:\u002F\u002Fgithub.com\u002Fj178\u002Fprek) or [pre-commit](https:\u002F\u002Fpre-commit.com\u002F) to set up git hooks to automatically check\u002Fencrypt secrets before commit and decrypt them after checkout.\n\nSee the [example prek configuration here](examples\u002Fprek.toml).\n\nAfter adding the `prek.toml` file, run:\n\n```bash\nprek install\nprek install --hook-type post-checkout\nprek install --hook-type post-merge\nprek install --hook-type post-rewrite\n```\n\n## Access Control\n\n### Rules\n\nIn the metadata file, you can annotate which recipients the secret should be encrypted for.\nThis allows you to have different secrets for different environments (e.g. staging vs production) and only encrypt them for the relevant recipients.\n\n```toml\n# secret.yml.cott.toml\n[secret]\nallow = [\"sayanarijit\"]  # Only encrypt for sayanarijit\n```\n\n```toml\n# secret.yml.cott.toml\n[secret]\ndeny = [\"sayanarijit\"]  # Encrypt for everyone except sayanarijit\n```\n\n```toml\n# secret.yml.cott.toml\n[secret]\nallow = [\"env\u002Fstaging\u002F*\"]  # Supports glob patterns, only encrypt for recipients in env\u002Fstaging\ndeny = [\"env\u002Fstaging\u002Fbadservice\"]  # Encrypt for everyone in env\u002Fstaging except badservice\n```\n\nDeny rules take precedence over allow rules.\n\nSee [metadata specification](.\u002FSPECIFICATION.md#secretmetadata) for more details.\n\n### Verification\n\nYou can run `ctg verify` in CI to verify that the encrypted secrets and recipient lists match the metadata rules, to prevent tampering.\n\n```yaml\n# .github\u002Fworkflows\u002Fcottage-verify.yml\nname: Cottage Verify\non: [push, pull_request]\npermissions:\n  contents: read\njobs:\n  verify-secrets:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v3\n      - name: Verify secrets\n        run: docker run --rm -v \"${{ github.workspace }}:\u002Fapp\" ghcr.io\u002Fsayanarijit\u002Fcottage verify\n```\n\n## Any Provider as Upstream\n\nWith cottage, you can sync secrets with any provider that has an API, not just git.\n\nFor that, create a file named `cottage.toml` in the project root and configure the upstream settings.\n\nSee the [example `cottage.toml` here](.\u002Fcottage.toml) and the [secret specific upstream configuration here](.\u002Fexamples\u002Fsecrets\u002Fsecret.json.cott.toml).\n\nThe workflow is similar to git, but instead of `git pull` and `git push`, you run `ctg pull` and `ctg push` to sync secrets with the configured upstream.\n\nExample:\n\n```bash\n# Pull latest changes into local encrypted secrets\n# Similar to `git pull origin`\nctg pull myvault\n\n# Compare diff with local decrypted secrets\nctg diff\n\n# Sync local decrypted secrets with local encrypted secrets\nctg sync\n\n# Push changes from local encrypted secrets to upstream\n# Similar to `git push origin main`\nctg push myvault\n```\n\nSee [upstream configuration specification](.\u002FSPECIFICATION.md#upstreamconfig) for more details.\n\n## Sync with any device\n\nUse [Cottage Sync](https:\u002F\u002Fcottage-sync.github.io) to sync your secrets across your devices and browse without needing the CLI.\n\n## Learn More\n\nSee [examples](examples\u002F) directory for more usage examples.\n\n## Troubleshooting\n\n```bash\n# See debug logs with -v, -vv or -vvv\nctg run -vvv -- .\u002Fdeploy.sh\n```\n\n## Comparison\n\n### age vs Other Encryption\n\n[age](https:\u002F\u002Fage-encryption.org) uses a modern, simple algorithm optimized for secure file encryption, with a focus on usability and minimal attack surface. It also [supports SSH RSA and Ed25519 keys](https:\u002F\u002Fwords.filippo.io\u002Fusing-ed25519-keys-for-encryption\u002F), though it's recommended to use different keys for separate purposes and scopes.\n\n### cottage vs SOPS\n\nWhile [SOPS](https:\u002F\u002Fgetsops.io\u002F) and cottage have many overlapping features, cottage has the following advantages:\n\n- Auto manage .gitignore to ensure unencrypted secrets are never committed to git.\n- Encrypted secrets being pure age encrypted .age files, allows for better interoperability with a wider ecosystem of tools.\n- Cleaner diffs - unlike SOPS, which generates diffs for every value of every secret, even if the actual change is just adding\u002Fremoving a recipient, cottage only generates one diff per file, explicitly pointing out the change in recipients checksum.\n\n### cottage vs dotenvx\n\ncottage borrows the `ctg env` API from [dotenvx](https:\u002F\u002Fdotenvx.com).\n\n- Supports any file type, not just dotenv files.\n- Manages multiple secrets in a repo.\n- Access control rules to encrypt secrets for specific recipients.\n- Cleaner diffs - see [cottage vs SOPS](#cottage-vs-sops).\n\n### cottage vs agebox\n\n[agebox](https:\u002F\u002Fgithub.com\u002Fslok\u002Fagebox) is very similar to cottage in core philosophy but lacks many [features](#features).\n\n## License\n\nMIT OR Apache-2.0\n","Cottage 是一个基于 Git 的团队秘密管理工具，使用 age 加密技术来保护敏感信息。其核心功能包括通过简单的命令行操作实现加密\u002F解密、管理接收者以及防止未加密的秘密被提交到代码仓库中。此外，Cottage 还支持生成加密秘密的预览版本以提高透明度，并确保即使在临时解密工作流中也能保证数据安全。该工具特别适用于需要在多个开发人员之间共享和维护敏感配置或凭证的场景，同时保持这些信息的安全性和访问控制。采用 Rust 语言编写，Cottage 在设计上注重安全性与用户体验的平衡。",2,"2026-06-11 04:06:45","CREATED_QUERY"]