> 这不是密码管理器。不是笔记应用。更不是深海海底异常标本分类来源登记册。但前两件事它做得比它们都好。开玩笑的(也不完全是)。
<div align="center">
<img src="https://assets.kitploit.com/production/public/readmes/13610/534f3cc38369a739749d2f98a8e4ec4a1c5df0a0a597aff5295b8cb1e39cc08e.webp" alt="dredge-doge-vs-cheems"/>
[](https://goreportcard.com/report/github.com/DeprecatedLuar/dredge)
[](https://oosmetrics.com/repo/DeprecatedLuar/dredge-cargo)
[](https://go.dev)
<!-- [](https://codecov.io/gh/DeprecatedLuar/dredge-cargo) -->
<div align="center">
[安装](#install) • [快速开始](#quick-start) • [功能特性](#features) • [链接命令](#link) • [命令](#commands) • [工作原理](#how-it-works) • [安全性](#security) • [为什么](#why)
</div>
</div>
<div align="center">
搜索,别整理。**_笔记、配置、密钥、秘密_** — 从你的终端开始,只需五秒。
</div>
<div align="center">
<a href="https://github.com/DeprecatedLuar/dredge-cargo/stargazers">
<img src="https://img.shields.io/github/stars/DeprecatedLuar/dredge-cargo?style=for-the-badge&logo=github&color=1f6feb&logoColor=white&labelColor=black"/>
</a>
<a href="https://github.com/deprecatedluar/dredge-cargo/blob/main/LICENSE">
<img src="https://img.shields.io/github/license/DeprecatedLuar/dredge-cargo?style=for-the-badge&color=green&labelColor=black"/>
</a>
<a href="https://github.com/DeprecatedLuar/dredge-cargo/releases">
<img src="https://img.shields.io/github/v/release/DeprecatedLuar/dredge-cargo?style=for-the-badge&color=orange&labelColor=black"/>
</a>
</div>
---
> *“别拿那些琐碎杂事来烦我。”* —— 渔夫
<div align="center">
<!-- 演示gif -->
<img src="https://assets.kitploit.com/production/public/readmes/13610/a31d2a13bfbae4b1b41843137d86ddbc2c38b512972389761eab9dfc3ba6023d.gif" alt="dredge 演示" width="800"/>
</div>
```bash
go install github.com/DeprecatedLuar/dredge-cargo/cmd/dredge@latest
```
<div align="right">
[其他安装方式 ↓](#install)
</div>
---
<h2 id="features"><img height="44" src="https://assets.kitploit.com/production/public/readmes/13610/5e6da8f5d6e3dc6eb114152fb8cc8ee944547f43aa95f2cbb4b7430fde0c08a0.webp"/> 你从未见过的炫酷功能</h2>
- **加密存储** —— 克隆仓库,你只会看到一堆绝对的加密乱码。没有密码你根本不知道仓库里有什么。(我用了 AES-256-GCM + Argon2id)
- **即时搜索** —— 我自己写了个自定义模糊搜索算法,因为我懒得想,希望能毫秒级地在300多个条目中找到想要的那个。
- **存储任何东西** —— 笔记、脚本、dotfiles、图片、zip压缩包。只要是一个存在的文件,都可以存入 dredge。
- **实时文件链接** —— 很酷的功能:把任意条目符号链接到系统路径,这样你可以直接读取和编辑,或者通过 dredge 来操作。任何改动都会与仓库双向同步。
- **Git 支持** —— 你拥有的私有仓库。只需 `git clone`,数据就到手了。
- **会话密码** —— 每个终端会话只需输入一次密码。之后就可以免密使用,直到你关闭终端。(请阅读安全部分以更好理解)
- **回收站 + 撤销** —— 删除的条目进入回收站。误删只需 `dredge undo`。
---
<h2><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/21ca061b01116178eca9bbfd0698ebcaf0f63e614165fbc7b904f54508e01836.webp"/> 在 dredge 里存什么?</h2>
我不会评判你。那些只出现一次就让你头疼的 API 密钥、SSH 配置、AI 提示词、密码、可以直接执行的 shell 脚本、邮件模板?、dotfiles(虽然有点怪但能用)、zip 存档、电影清单、快捷访问的 URL 列表……
甚至《电锯人》第2章日文版的 _合法_ 拷贝。(我可能恰好就存了那一份)
---
<h2 id="install"><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/db2b1ad73c3323b870934910e70cd8249c788b4ffdfaf79b09c75c05c8741937.webp"/> 安装</h2>
 
### Go
```bash
go install github.com/DeprecatedLuar/dredge-cargo/cmd/dredge@latest
```
确保 `$GOPATH/bin`(通常是 `~/go/bin`)在你的 `PATH` 中。
### 通用
```bash
curl -sSL https://raw.githubusercontent.com/DeprecatedLuar/the-satellite/main/satellite.sh | bash -s -- install DeprecatedLuar/dredge-cargo:dredge
```
<details>
<summary>其他安装方法</summary>
<br>
**手动安装**
1. 从 [releases](https://github.com/DeprecatedLuar/dredge-cargo/releases) 下载适用于你系统的二进制文件
2. 赋予执行权限:`chmod +x dredge-*`
3. 移动到 PATH:`mv dredge-* ~/.local/bin/dredge`
---
**从源码构建**
```bash
git clone https://github.com/DeprecatedLuar/dredge-cargo
cd dredge-cargo
go build -o dredge ./cmd/dredge
mv dredge ~/.local/bin/
```
</details>
---
<h2 id="quick-start"><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/b937e031192b68639bfed048d771e9881136e1d0915985740574b930022b2926.webp"/> 快速开始</h2>
```bash
# 用已有的 git 远程初始化
dredge init yourusername/vault # GitHub 简写
# 或:dredge init [email protected]:you/vault.git
# 添加第一个条目
dredge add "OpenAI Key" -c "sk-..." -t keys api # 不加 -c 会打开编辑器
# 搜索它
dredge search openai
# 推送到 git
dredge push
```
<details>
<summary>用法</summary>
<br>
```bash
# 添加任何东西
dredge add My SSH Config -t ssh dotfiles --import ~/.ssh/config
dredge add "Master Architect Prompt" --import prompt.md -t ai prompts
dredge add "Watchlist" -c "Dune 2, Oppenheimer..." -t lists
dredge add "project-backup" --import project.tar.gz # 二进制文件也行 :D
# 搜索 —— 随便输点什么你记得的
dredge search prompt
dredge search aws key
dredge search ssh
# 查看、编辑、删除
dredge view <id>
dredge edit <id>
dredge rm <id>
dredge undo # 找回来
# 搜索结果带有编号 —— 直接输入编号即可查看
dredge search ssh # 显示:1. [xKP] SSH Config 2. [mNq] SSH Key
dredge 1 # 直接查看
# Git 同步
dredge push
dredge pull
dredge sync # pull + push
```
</details>
---
<h2 id="how-it-works"><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/479f1ebf816d929f37e78e3a97679f47640eb18c52a9f1c129745bdffb7df1be.webp"/> 工作原理</h2>
> *“我无法想象深处藏着什么。”* —— 灯塔看守人
好吧,简单总结一下:
我决定使用两种主要的加密技术:Argon2id 和 AES-256(具体是 GCM 模式)。
选择 Argon2id,因为它是 RFC 9106 的推荐方案,也是 2015 年 PHC 的获胜者。就这么简单。
选择 AES 的 GCM 模式,因为它能让所有加密数据由于指纹的存在而无法被篡改。这个理由也够了。
目前,所有内容都以加密文件形式存储在 `~/.local/share/dredge/` 中。该目录也是一个 git 仓库(至少目前是这样)。所以 `dredge push` 会提交并推送所有内容以作备份。每个条目都是一个独立的加密 blob,带有一个随机的 3 字符 ID。我决定不暴露任何文件名,这样即使有人能看到你的文件,也不知道它们是什么。
### 加密流程
```
你的密码
+ 16 字节随机盐 ← 盐存储在 .dredge-key 中
→ Argon2id(64 MB 内存 · 4 线程 · 1 次迭代)
→ 32 字节主密钥(盐 + 密码 = 真正的密钥)
主密钥 + 条目内容(TOML 格式:标题、标签、内容)
→ AES-256-GCM,每次操作使用新的随机 12 字节 nonce
→ [12B nonce][密文 + 16B 认证标签]
→ 写入磁盘为 items/xKP (随机 ID,无扩展名)
```
因此,你的整个保险库共享同一个派生密钥(这意味着如果你丢失了密钥,你就会丢失数据,请务必保管好密钥)。每个条目使用相同的密钥,但各自拥有独立的随机 nonce。即使对相同内容加密两次,也会产生完全不同的密文。
### 各文件位置
```
~/.local/share/dredge/ ← 保险库(git 仓库)
├── .git/
├── .gitignore ← 排除 .spawned/ 和 links.json
├── .dredge-key ← 盐 + 加密验证字符串
├── items/
│ ├── xKP ← 加密的条目
│ ├── mNq ← 加密的条目
│ └── ...
├── .spawned/ ← 链接条目的明文副本
└── links.json ← 符号链接清单
```
所有加密文件和 `.dredge-key` 都存储在 git 仓库中,所有明文文件(你决定系统可读的那些)永远不会被跟踪。所以你可以随意处理它们。
### 会话模式
在终端中输入第一个命令后,派生的 32 字节密钥会被缓存在 `$XDG_RUNTIME_DIR/dredge/$PPID/.key`(仅 root 可访问)。
同一终端中之后的所有 dredge 命令都会使用缓存的密钥。这意味着你不再需要输入密码。每个终端根据父 PID 拥有自己独立的目录。因此,终端关闭后,密钥就会从磁盘上蒸发。
<details>
<summary>更深的技术细节</summary>
<br>
**密钥派生 —— Argon2id:** RFC 9106 推荐参数(64 MB 内存、4 线程、1 次迭代)。`.dredge-key` 中的盐并非秘密,它只是确保即使拥有这个文件,暴力破解你的密码也代价极高。保密你的密码才是关键,你懂的。
**密码 —— AES-256-GCM:** 对每次加密进行指纹标记。同时提供机密性和完整性。篡改密文不会解密出垃圾,而是会解密失败并报错。
**密码验证:** `.dredge-key` 中包含用你的主密钥加密的字符串 `dredge-vault-v1`。每次新会话时,dredge 解密此字符串来验证密码是否正确。如果从中没有得到 `dredge-vault-v1`,则密码错误,它在大约 100 毫秒内就会失败,而不是在执行操作中途才发现密码错误。
**缓存的内容:** 会话文件存储的是派生出的 32 字节密钥(密码+盐),而不是密码本身(我没那么蠢)。因此,即使有人在活动会话期间读取了 `.key`,他们也无法从其中恢复你的密码。
</details>
---
<h2 id="security"><img height="56" src="https://assets.kitploit.com/production/public/readmes/13610/8dd63d36b5812744ccd584320794a580b7e1ee13ac9d33a1af0fa8ef8e364381.webp"/> 安全性</h2>
> *“空手回来总比永远回不来好。”* —— 渔夫
### 威胁模型(这部分我用 AI 写的,但没错)
**有人克隆了你的私有 git 仓库:**
他们得到的是加密的 blob 和 `.dredge-key`。盐不是秘密——它的作用是使预计算攻击变得不可行。没有你的密码,条目就是一堆不透明的二进制数据。Argon2id 让离线暴力破解变得代价高昂。请使用强密码。
**有人能访问你正在运行的会话:**
派生密钥在终端会话期间存在于 `$XDG_RUNTIME_DIR/dredge/$PPID/.key` 中。每个终端有自己独立的目录——关闭终端,密钥就消失了。该路径是用户范围的(权限 700)且基于 RAM。能够读取你会话目录的攻击者可以解密你的保险库。请像对待主目录中的任何敏感凭证一样对待它。如果有人拥有你机器的 root 权限,那 dredge 密钥是你最不需要担心的。
**有人可以物理接触你离线状态的机器:**
磁盘上的条目是加密的。会话密钥存储在基于 RAM 的存储中,重启后不会保留。链接的条目(`.spawned/`)是磁盘上的明文——参见下文。
### 明文存在的位置
| 位置 | 何时 | 生命周期 |
|----------|------|---------|
| 仅 RAM | 每次查看、搜索或编辑 | 命令退出后释放 |
| `$XDG_RUNTIME_DIR/dredge/$PPID/edit-*.txt` | 仅在 `dredge edit` 期间 | 编辑器关闭后删除 |
| `~/.local/share/dredge/.spawned/<id>` | 执行 `dredge link` 之后 | 直到你执行 `dredge unlink` |
spawned 文件是磁盘上唯一的持久明文,而且它之所以存在,是因为你明确地将某个条目链接到了系统路径上。其他所有内容都只存在于内存中。
### 注意事项
- **`--password` / `DREDGE_PASSWORD`:** 在命令行内联密码会暴露在 shell 历史记录和 `ps` 输出中。环境变量可能会泄漏给子进程。在共享环境中请避免使用。
- **`--vault` / `DREDGE_VAULT`:** 覆盖当前会话的活动保险库,而不持久化修改。适合跨多个保险库编写脚本。
- **链接的条目:** 链接条目的明文存在于符号链接的目标位置(例如 `~/.ssh/config`)。它不会被 git 跟踪,但以明文形式存在于磁盘上。
<div align="center">
<img src="https://assets.kitploit.com/production/public/readmes/13610/dcc75e764202f8315a3a56114ee19e79a70acd9dcc1094f70031f022e18ad76d.webp" width="700"/>
</div>
<h2 id="link"><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/ca14a510c662e4e6a349bbc44aa1eb397d2ded5d06ba7bd7f21f2cca50a0c1bd.webp"/> 链接命令</h2>
将任意存储的条目链接到你文件系统的某个路径:
```bash
dredge link <id> ~/.ssh/config
```
此命令会在 `~/.ssh/config` 处创建一个符号链接,指向 dredge 管理的明文副本(文件会被暴露到磁盘上供你使用)。你可以直接编辑文件,也可以通过 `dredge edit` 或其他任何你喜欢的方式编辑,所有改动都会自动同步回加密存储。
**自动修复:** 如果你重命名了符号链接(例如 `mv ~/.ssh/config ~/.ssh/config-backup`),dredge 会自动检测并跟踪新路径。删除的符号链接会在会话启动时被清理。
<div align="center">
<img src="https://assets.kitploit.com/production/public/readmes/13610/474132cd19d95d478c40ab360838423dcfcef2033d09f230a8640051dcd08d8e.gif" alt="dredge 链接演示" width="800"/>
</div>
在新机器上:
```bash
git clone [email protected]:you/vault.git ~/.local/share/dredge
dredge link <id> ~/.ssh/config
# 同样的 SSH 配置,同样的密钥,每台机器上的任何更新都会被 git 跟踪
```
这其实正是我构建 dredge 的原因。我的 SSH 配置在所有机器上都是相同的,但我不能简单地把它们塞进我的 dotfiles 里。
---
<h2 id="commands"><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/8c572a94c96ee031536884f6f6d32202d53ca05943b0b1083ed05b86fad3641a.webp"/> 所有命令</h2>
<div align="left">
| 命令 | 描述 | 示例 |
|:--------|:------------|:--------|
| `add` / `a` / `new` / `+` | 添加条目(不加 -c 标志会打开编辑器) | `dredge add "OpenAI Key" -c "sk-..." -t keys` |
| `search` / `s` | 搜索条目 | `dredge search aws key` |
| `list` / `ls` | 列出所有条目 | `dredge ls` |
| `view` / `v` | 查看条目 | `dredge view xKP` 或 `dredge 1` |
| `cat` / `c` | 输出原始内容(用于管道传输) | `dredge cat xKP \| bash` |
| `edit` / `e` | 编辑条目 | `dredge edit xKP` |
| `rm` | 删除(进入回收站) | `dredge rm 1 2 3` |
| `undo` | 恢复最后删除的条目 | `dredge undo` |
| `link` / `ln` | 将条目链接到系统路径 | `dredge link xKP ~/.ssh/config` |
| `unlink` | 移除链接 | `dredge unlink xKP` |
| `mv` / `rename` | 重命名条目 ID | `dredge mv xKP abc` |
| `export` | 将文件条目导出到磁盘 | `dredge export xKP ./output/` |
| `copy` / `cp` | 将条目内容复制到剪贴板 | `dredge copy xKP` |
| `lock` | 锁定保险库(清除会话密钥) | `dredge lock` |
| `init` / `use` | 初始化或激活一个保险库 | `dredge init ~/vaults/work` |
| `push` / `pull` / `sync` | Git 同步(自动提交更改) | `dredge sync` |
| `drop` | 丢弃未提交的更改 | `dredge drop xKP` 或 `dredge drop --all` |
| `status` | 显示待处理的更改 | `dredge status` |
| `passwd` | 更改保险库密码 | `dredge passwd` |
| `update` | 更新到最新版本 | `dredge update` |
</div>
### Git 同步(by wlad031)
Git 同步使用原生 `git`,可与任何远程服务器配合使用(GitHub/GitLab/Gitea 等)。
`dredge init` 接受一个可选的 git 远程。如果省略,dredge 会初始化一个纯本地 git 仓库(无远程)。
**自动提交行为:** `push`、`pull` 和 `sync` 会在与远程同步之前,将尚未同步的未提交更改保存在一个提交中。如果你需要丢弃本地更改以优先使用远程版本,请使用 `dredge drop`。
**自动历史记录保留:** `push` 和 `sync` 应用 `dredge.toml` 中的策略。条目元数据和二进制存储各自拥有独立的按条目版本和加密字节限制,而 `history.deleted.retain_for` 控制已删除 ID 的可恢复时长。如果策略没有删除任何内容,Dredge 会正常推送。如果需要压缩,Dredge 会验证替换历史,并使用精确的 force-with-lease;如果远程同时更新,将安全停止而不是被覆盖。`pull` 从不压缩或强制推送。
使用 `dredge history`、`dredge history deleted` 或 `dredge history <id>` 查看保留的历史记录。使用 `dredge history restore <id>` 恢复已删除的加密条目。更改密码不会重新加密历史 blob,因此在旧密码下创建并恢复的版本可能无法用当前密码解密。
接受的远程格式:
```bash
# GitHub 简写(展开为 https://github.com/<所有者>/<仓库>.git)
dredge init owner/repo
# HTTPS
dredge init https://github.com/owner/repo.git
dredge init https://gitlab.com/group/repo.git
# SSH(scp 风格)
dredge init [email protected]:owner/repo.git
dredge init [email protected]:group/repo.git
# SSH URL
dredge init ssh://[email protected]/owner/repo.git
# 本地路径远程(高级)
dredge init /srv/git/dredge-vault.git
```
- Dredge 不会为你创建远程仓库。
- 如果没有配置 `origin`,`dredge push`/`pull`/`sync` 会报错并给出提示。
- 如果你已经设置了 git 远程,`dredge init` 不会覆盖它。
---
<h2 id="why"><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/b68b7786d5870a11a1d49137213cb61e51a25165c205d3a99298d7a27a616242.webp"/> 为什么</h2>
<img src="https://assets.kitploit.com/production/public/readmes/13610/23c3be123dc3423443be52804789e0647f1aaa477647cc9945dad19e4fe789a2.webp" alt="dredge 标志" align="right" width="200"/>
> *“我是一个收藏家——收藏很多东西:艺术与文物、珍宝与真相……还有那些占据欲望边缘的奇物。”* —— 收藏家
存储某样东西却不知道在需要时去哪找,这种心理负担让我厌烦。
我受够了把所有重要的东西(以及不重要的——总之就是各种东西)散落在各处。有时候我得登录一个六年前创建的邮箱,因为那里关联了一个我急需访问的随机服务……总之,我意识到很多工具尽管各有噱头,但在信息存储这个非常重要的方面都有重叠。所以我做了一个专注于那_一特定重叠_的工具,让其他工具去做它们最擅长的事。
我很懒,所以我想要一个能直接工作、能读懂我心思的东西,添加一个条目或从知识库中检索它都不费吹灰之力。
我曾经下载过 [jrnl](https://jrnl.sh),很喜欢它的概念,但讨厌它的实现,因为有些参数很奇怪,它根本没有条目的区分,搜索会匹配*所有东西*。Dredge 才是真正我想要的东西。(所以嘛,基本上就是个个人工具)
<div align="center">
<img src="https://assets.kitploit.com/production/public/readmes/13610/90f2f36bb0ca104704eb98c1ad2711f7c53b008a66ddfc4334e4503986e515b7.webp" width="600"/>
</div>
---
<h2><img height="32" src="https://assets.kitploit.com/production/public/readmes/13610/dee19080cbb4c8dc2511711c86f32617b12ee55e34ffc08658215533f7420640.webp"/> 贡献者</h2>
非常感谢为 dredge 做出贡献的各位:
<table>
<tr>
<td align="center">
<a href="https://github.com/timcondit"><img src="https://assets.kitploit.com/production/public/readmes/13610/5c0d0e21e68f12b1687cb275ffdfa6b84b6b825998061fb623d88640fcd20f10.jpg" width="48" /><br/>timcondit</a>
</td>
<td align="center">
<a href="https://github.com/wlad031"><img src="https://assets.kitploit.com/production/public/readmes/13610/84d9b6594e04f211f09cbf1b128c591c80ac702807a91a75a5973a4bd384c238.jpg" width="48" /><br/>wlad031</a>
</td>
</tr>
</table>
---
<div align="center">
由 <img src="https://assets.kitploit.com/production/public/readmes/13610/1838297af83d5d3f60028a5f542ff33ccac6b76e0ebe57671a9d9e9f40ec40a1.webp" height="200" style="vertical-align:middle"/> Luar 制作
</div>