sefy-cli 0.8.0 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +56 -190
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  <a href="https://github.com/lacodda/sefy/blob/main/LICENSE"><img src="https://img.shields.io/crates/l/sefy?style=flat-square" alt="MIT"></a>
8
8
  </p>
9
9
 
10
- # sefy
10
+ > An encrypted store for notes, credentials and files that does not announce itself: one file with no header, no extension it must keep, and no name that gives it away.
11
11
 
12
12
  Every way of storing secrets announces itself. A `.kdbx` file says "password
13
13
  database". age and gpg write a header. VeraCrypt wants a container and a mount.
@@ -50,7 +50,7 @@ Master password:
50
50
  created /home/you/backups/notes.bak
51
51
  ```
52
52
 
53
- Put things in. Notes, logins, cards, ssh keys, and files kept byte for byte.
53
+ Put things in - notes, logins, cards, ssh keys, and files kept byte for byte:
54
54
 
55
55
  ```
56
56
  $ sefy add note "bank card" --text "PIN 4815" --tag money
@@ -64,177 +64,64 @@ $ sefy add file ~/.ssh/id_ed25519 --tag keys
64
64
  added "id_ed25519" as 3
65
65
  ```
66
66
 
67
- Look around.
68
-
69
- ```
70
- $ sefy ls
71
- 3 id_ed25519 file [keys]
72
- 2 mail login [mail]
73
- 1 bank card note [money]
74
-
75
- $ sefy show mail
76
- id: 2
77
- title: mail
78
- kind: login
79
- tags: mail
80
- login: someone@example.com
81
- password: <hidden — use sefy get>
82
- url: https://mail.example.com
83
- ```
84
-
85
- Or do not look around at all: `sefy` on its own opens a picker over the vault.
86
- Type a few letters, press Enter. The command line is exact and remembering is
87
- not.
67
+ Bare `sefy` opens a picker over everything in the vault:
88
68
 
89
69
  ```
90
70
  $ sefy
91
- ? Item ›
71
+ ? Item >
92
72
  > bank card note [money]
93
73
  mail login [mail]
94
74
  id_ed25519 file [keys]
95
75
  ```
96
76
 
97
77
  Take a secret out. It goes to the clipboard and is taken back off after 45
98
- seconds - sefy clears it only if the secret is still what is sitting there, so
99
- anything you copied meanwhile is left alone.
78
+ seconds - and only if the secret is still what is sitting there, so anything
79
+ you copied meanwhile is left alone.
100
80
 
101
81
  ```
102
82
  $ sefy get mail
103
83
  copied password of "mail" to the clipboard; clearing in 45s
104
84
  clipboard cleared
105
-
106
- $ sefy get "bank card" --stdout
107
- PIN 4815
108
- ```
109
-
110
- For a login you are about to use, `sefy open` does both halves at once: the
111
- browser loads while the password waits on the clipboard.
112
-
113
- ```
114
- $ sefy open mail
115
- opened https://mail.example.com
116
- copied password of "mail" to the clipboard; clearing in 45s
117
- ```
118
-
119
- Items are addressed by title, by an exact id, or by text to search for. When
120
- your words could mean more than one thing, sefy shows what they could mean
121
- instead of guessing:
122
-
123
- ```
124
- $ sefy get ma
125
- error: 2 items match "ma":
126
- 4 mailing list note
127
- 2 mail login
128
- narrow the text, or use an id
129
85
  ```
130
86
 
131
- Several machines? `sefy sync` carries the vault through a transport and folds
132
- what comes back into this one:
87
+ A new account needs a new password, and `sefy gen` makes one and keeps it in
88
+ the same breath - stored as a login, then put on the clipboard for the sign-up
89
+ form:
133
90
 
134
91
  ```
135
- $ sefy sync
136
- Master password:
137
- synced "vault" through github
138
- merged: 2 added, 0 updated, 14 unchanged
92
+ $ sefy gen --save forum --login someone@example.com --url https://forum.example.com
93
+ added "forum" as 4
94
+ generated 20 characters: 130 bits of entropy, strength 4/4
95
+ copied it to the clipboard; clearing in 45s
139
96
  ```
140
97
 
141
- Or fold in a copy you carried across by hand. Either way, where the two disagree
142
- about the same item, sefy keeps both versions rather than letting a timestamp
143
- decide which password you get to keep:
98
+ Items are addressed by title, by an exact id, or by text to search for; when
99
+ the words could mean more than one thing, sefy shows what they could mean
100
+ rather than guessing. `sefy open` loads the site and puts the password on the
101
+ clipboard in one step, `sefy sync` carries the vault through a transport and
102
+ folds what comes back into this one, and `sefy status` says what you are
103
+ holding without saying what is in it.
144
104
 
145
- ```
146
- $ sefy merge ~/from-laptop.bak
147
- Password for /home/you/from-laptop.bak:
148
- merged: 1 added, 1 updated, 1 unchanged
149
-
150
- 1 item changed on both sides and could not be resolved here.
151
- This vault's version was kept; the incoming one is beside it:
152
- "mail" → also kept as "mail (conflicted copy)"
153
- Compare them, keep the right one, and remove the other.
154
- ```
105
+ Every command, with its flags: **[the reference](https://lacodda.github.io/sefy/reference/commands/)**.
155
106
 
156
- New machine, or back after a week? `sefy status` says what you are holding
157
- without saying what is in it - counts and versions, never a title or a value:
107
+ ## What you get
158
108
 
159
- ```
160
- $ sefy status
161
- vault /home/you/backups/notes.bak
162
- size 72.1 KB
163
- items 17 items (12 login, 4 note, 1 file)
164
- tags 6 tags
165
- schema 4
166
- synced 2026-09-16 19:15 UTC (2 hours ago) through github (sync)
167
- plugins github, sftp
168
- ```
169
-
170
- A vault is never a trap. `sefy export` writes everything back out as plain
171
- JSON - which is exactly as sensitive as the vault and protects nothing, so the
172
- command makes you say so out loud:
173
-
174
- ```
175
- $ sefy export -o backup.json
176
- error: export writes every secret in this vault in the clear
177
- the resulting file protects nothing — encrypt it, or delete it when done
178
- pass --i-know-this-writes-plaintext to go ahead
179
- ```
180
-
181
- Full command reference: **[lacodda.github.io/sefy](https://lacodda.github.io/sefy/)**.
182
-
183
- ## Transports
184
-
185
- Carrying a vault to another machine is the job of a **plugin**: any executable
186
- named `sefy-plugin-*`, found in sefy's data directory or on `PATH`. sefy knows
187
- nothing about git, FTP or any cloud drive - it asks a plugin what it can do and
188
- what happened.
189
-
190
- Two transports ship alongside the CLI, and neither stores a credential of its
191
- own - each authenticates the way the machine already does:
192
-
193
- - **github** keeps the vault in a git repository. Point `SEFY_GITHUB_REPO` at
194
- one; version history comes free with it.
195
- - **sftp** keeps it on a server you control, over OpenSSH. Point
196
- `SEFY_SFTP_DESTINATION` at `you@server:/path`; nothing lands there but the
197
- blob.
198
-
199
- ```
200
- $ sefy plugin list
201
- future 9.0.0 unusable: it speaks protocol 99 and this build speaks 1
202
- github 0.7.0 pull, push
203
- sftp 0.7.0 pull, push
204
- ```
205
-
206
- With more than one installed, sefy asks which rather than choosing where your
207
- vault goes: `sefy sync --transport sftp`, or `SEFY_TRANSPORT=sftp` once.
208
-
209
- A transport is handed the **path of the sealed file** and nothing else - no
210
- master password, no key, no item. What it carries is what anyone would find on
211
- your disk: a blob it cannot read. That is also why a plugin cannot merge: it
212
- moves the other copy to a file, and sefy folds the two together itself, where
213
- both sides can actually be read.
214
-
215
- Broken plugins are listed with the reason rather than skipped: an omitted line
216
- would look exactly like a plugin that was never installed.
217
-
218
- The protocol is small enough to implement in a shell script - manifest on
219
- `--manifest`, one JSON request on stdin for `run`. Writing one:
220
- [plugin reference](https://lacodda.github.io/sefy/reference/plugin/) ·
221
- [ADR-0002](https://github.com/lacodda/sefy/blob/main/docs/adr/0002-plugin-protocol.md).
222
-
223
- ## How it works
224
-
225
- - The master password is stretched into a key with **Argon2id**.
226
- - The whole SQLite database is sealed with **XChaCha20-Poly1305** (AEAD).
227
- - The file on disk is `salt ‖ nonce ‖ ciphertext`. Salt and nonce are fresh on
228
- every save, so two saves of identical content share no prefix - and the
229
- format version lives *inside* the ciphertext, because a version byte in the
230
- clear would be the signature the format exists to avoid.
231
- - The decrypted database exists **only in memory**. SQLite is never given a
232
- path, so no page, journal or temporary file lands on disk.
233
- - Saves are atomic: ciphertext goes to a temporary file, is synced, and is
234
- renamed over the vault. A crash leaves either the old vault or the new one,
235
- and never plaintext.
236
-
237
- Details and rationale: [ADR-0001](https://github.com/lacodda/sefy/blob/main/docs/adr/0001-vault-file-format-and-cryptography.md).
109
+ - **A file that looks like nothing.** No magic bytes, no header, no extension
110
+ convention - salt and nonce fresh on every save, so two saves of identical
111
+ content share no prefix.
112
+ - **Notes, logins, cards, ssh keys and files** in one vault, tagged and
113
+ searchable, with files kept byte for byte.
114
+ - **Passwords made where they are kept.** `sefy gen` draws random characters,
115
+ pronounceable ones or a diceware passphrase (English or Russian lists built
116
+ in), reports its exact entropy beside an offline zxcvbn score, and can save
117
+ the result as a login in the same command.
118
+ - **Transports, not lock-in.** `sefy sync` carries the vault through a
119
+ `sefy-plugin-*` executable - github and sftp ship today - and folds what
120
+ comes back in without a credential ever passing through the transport.
121
+ - **Merge instead of overwrite.** Where two copies disagree about an item,
122
+ both are kept rather than letting a timestamp pick a winner.
123
+ - **A vault that is never a trap.** `export` writes plaintext JSON only after
124
+ you say so explicitly.
238
125
 
239
126
  ## Install
240
127
 
@@ -269,51 +156,30 @@ place any transport the archive carries into sefy's plugins directory, so
269
156
  Shell completions: `sefy completions bash` (also `zsh`, `fish`, `powershell`,
270
157
  `elvish`).
271
158
 
272
- ## Stability
273
-
274
- The **vault file format is stable at version 1**. Files written by this release
275
- will stay readable: any future change to the format arrives as version 2, able
276
- to read version 1 and migrate it. The Argon2 parameters are part of that
277
- promise, not a tuning knob.
278
-
279
- The database inside the ciphertext is versioned separately, and it does move:
280
- 0.2.0 added an identity to items so two copies of a vault can be merged, and
281
- 0.7.0 replaced the credential table with named fields so that a kind of record
282
- costs a template rather than a table. A vault from an earlier release opens and
283
- is migrated on the way in; the file on disk does not change shape.
284
-
285
- What an older build makes of it afterwards depends on the change. The 0.2.0
286
- migration left everything readable by 0.1.x. The 0.7.0 one does not: a login is
287
- now a kind 0.6.0 has never heard of, so that build lists it, exports it and
288
- syncs it while saying to upgrade before reading it. That is the
289
- forward-compatibility contract from 0.6.0 doing its job rather than a break -
290
- nothing is lost, and the newer build reads everything - but it is why the
291
- rename happened before 1.0 rather than after.
292
-
293
- The **plugin protocol is at version 1** as of 0.3.0. 0.4.0 put it to work and
294
- 0.5.0 added a second transport of a different shape without changing a field of
295
- it, which is the evidence that it was not built around the first one. Optional
296
- fields may be added to the manifest without breaking a plugin that predates
297
- them; changing what an existing field means would arrive as version 2, with both
298
- accepted for a time.
159
+ ## Documentation
299
160
 
300
- Released versions and what landed in each: [CHANGELOG on the Releases page](https://github.com/lacodda/sefy/releases).
161
+ Full command reference, concepts and guides:
162
+ **[lacodda.github.io/sefy](https://lacodda.github.io/sefy/)** - including
163
+ [how the vault works](https://lacodda.github.io/sefy/concepts/vault-format/)
164
+ and the [plugin reference](https://lacodda.github.io/sefy/reference/plugin/)
165
+ for transports.
301
166
 
302
- ## Building
167
+ ## Status
303
168
 
304
- ```
305
- cargo build --release # workspace: sefy-core (library) + sefy (CLI)
306
- cargo test # unit, integration and doc tests
307
- ```
169
+ The vault file format is stable at version 1, and the plugin protocol at
170
+ version 1 since 0.3.0; both promises hold across every release below. The
171
+ database schema inside the ciphertext moves between releases, and older
172
+ builds keep reading a vault safely even when they cannot see everything in
173
+ it - the [versions and compatibility](https://lacodda.github.io/sefy/concepts/versions/)
174
+ page has the detail.
175
+
176
+ Released versions and what landed in each: [CHANGELOG on the Releases page](https://github.com/lacodda/sefy/releases).
308
177
 
309
- Use a release build for daily work: Argon2id is deliberately expensive, and an
310
- unoptimized build makes it several times slower still.
178
+ ## Contributing
311
179
 
312
- The library is published separately as [`sefy-core`](https://crates.io/crates/sefy-core)
313
- if you want vaults from your own code. The documentation site lives in
314
- [`docs/`](https://github.com/lacodda/sefy/tree/main/docs); architecture decision
315
- records are in [`docs/adr/`](https://github.com/lacodda/sefy/tree/main/docs/adr).
180
+ Building the workspace, repository layout and commit conventions:
181
+ [CONTRIBUTING.md](https://github.com/lacodda/sefy/blob/main/CONTRIBUTING.md).
316
182
 
317
183
  ## License
318
184
 
319
- [MIT](https://github.com/lacodda/sefy/blob/main/LICENSE)
185
+ MIT (c) [Kirill Lakhtachev](https://lacodda.com)
package/package.json CHANGED
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "sefy-cli",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "sefy": {
5
- "binary": "v0.8.0"
5
+ "binary": "v0.9.0"
6
6
  },
7
7
  "description": "An inconspicuous encrypted store for notes, credentials and files",
8
8
  "license": "MIT",