valija 0.2.0 → 0.3.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.
- package/README.md +160 -26
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
# valija
|
|
2
2
|
|
|
3
|
-
> An encrypted vault for your AI context. Save it from one tool, load it in any other.
|
|
3
|
+
> An encrypted vault for your AI context. Save it from one tool, load it in any other — on any of your machines.
|
|
4
4
|
|
|
5
|
-
**valija** is an open source, end-to-end encrypted context vault for developers who use several AI
|
|
5
|
+
**valija** is an open source, end-to-end encrypted context vault for developers who use several AI
|
|
6
|
+
tools. Save distilled context ("we chose SQLCipher, next step is the restore flow") from inside
|
|
7
|
+
Claude Code, Claude Desktop, Cursor, or any MCP client — and load it later from any other. The vault
|
|
8
|
+
lives on your machine, encrypted with a passphrase. No cloud service, no accounts, no telemetry. If
|
|
9
|
+
you want it on more than one machine, you point it at a folder your own sync client already
|
|
10
|
+
replicates — valija never talks to a server of its own.
|
|
6
11
|
|
|
7
|
-
The name comes from *valija diplomática* — a sealed pouch that crosses borders and only its owner
|
|
12
|
+
The name comes from *valija diplomática* — a sealed pouch that crosses borders and only its owner
|
|
13
|
+
may open.
|
|
8
14
|
|
|
9
15
|
## Status
|
|
10
16
|
|
|
11
|
-
**
|
|
17
|
+
**Young but working.** The vault format migrates forward in place, never breaks: schema **v1 → v3**
|
|
18
|
+
upgrades run automatically on first open, always after taking a ciphertext backup. The newest
|
|
19
|
+
capability is **bring-your-own-cloud sync** — using one vault across several devices (see
|
|
20
|
+
[Use it on several devices](#use-it-on-several-devices)).
|
|
12
21
|
|
|
13
22
|
## Quickstart (5 minutes)
|
|
14
23
|
|
|
@@ -18,33 +27,137 @@ valija init # create your encrypted vault (passphrase + recovery
|
|
|
18
27
|
valija install claude-code # wire the MCP server in (also: claude-desktop, cursor)
|
|
19
28
|
```
|
|
20
29
|
|
|
21
|
-
|
|
30
|
+
`init` prints a **recovery kit once** — copy it somewhere safe offline before you close the
|
|
31
|
+
terminal. Your vault starts **unlocked**. Restart your AI tool, then, inside it:
|
|
32
|
+
*"save context: we decided X, next step is Y"* — and tomorrow, in a different tool:
|
|
33
|
+
*"load context for my-project"*.
|
|
22
34
|
|
|
23
|
-
|
|
35
|
+
## Updating
|
|
24
36
|
|
|
25
37
|
```
|
|
26
|
-
|
|
27
|
-
valija status # where the vault is, locked or not
|
|
28
|
-
valija projects # what's inside
|
|
29
|
-
valija search "auth" # full-text search from the terminal
|
|
30
|
-
valija export my-project # print the context pack (paste it into any non-MCP tool)
|
|
31
|
-
valija doctor # checks node, keychain, vault, client configs
|
|
38
|
+
npm install -g valija@latest # or: npm update -g valija
|
|
32
39
|
```
|
|
33
40
|
|
|
41
|
+
That's it — there's no separate migration step to run by hand. The next time any `valija` command
|
|
42
|
+
opens your vault, it checks the schema version and upgrades in place automatically if it's behind,
|
|
43
|
+
always taking a ciphertext backup (`vault.db.pre-NNN.bak`) first and removing it only once the
|
|
44
|
+
upgrade succeeds. Your passphrase, recovery kit, and existing projects/context are unaffected.
|
|
45
|
+
|
|
46
|
+
If you're only using valija on one machine, updating is the whole story — nothing else changes.
|
|
47
|
+
**New in 0.3.0:** if you'd like to start using the same vault on more than one device, see
|
|
48
|
+
[Use it on several devices](#use-it-on-several-devices) below; it's opt-in and requires no change to
|
|
49
|
+
an existing single-machine setup. Check [CHANGELOG.md](CHANGELOG.md) for what's new in each release.
|
|
50
|
+
|
|
51
|
+
## Everyday use
|
|
52
|
+
|
|
53
|
+
Saving and loading happen **inside your AI tool** through the MCP server — you just ask it to save or
|
|
54
|
+
load context in plain language. The CLI is for everything around that: session control, reading your
|
|
55
|
+
own data, and housekeeping.
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
valija status # where the vault is, lock state, sync/idle info
|
|
59
|
+
valija unlock # unlock for this session (asks for your passphrase)
|
|
60
|
+
valija lock # lock again (drops the key from the OS keychain)
|
|
61
|
+
valija projects # list projects with item counts and last activity
|
|
62
|
+
valija show my-project # print a project's items (--type to filter)
|
|
63
|
+
valija search "auth" # full-text search (-p to scope to one project)
|
|
64
|
+
valija export my-project # print the context pack (paste into any non-MCP tool)
|
|
65
|
+
valija doctor # health check: node, keychain, vault, sync, client configs
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Useful flags:
|
|
69
|
+
|
|
70
|
+
- `valija unlock --recovery-key <hex>` — unlock using the raw key from your recovery kit when you've
|
|
71
|
+
lost the passphrase. This is the one moment the kit exists for.
|
|
72
|
+
- `valija show <project> --type <decision|progress|preference|fact|handoff|imported>` — filter items.
|
|
73
|
+
- `valija search <query> -p <project>` — restrict the search to one project.
|
|
74
|
+
- `valija export <project> --json` / `-o <file>` — export as JSON, or write to a file instead of stdout.
|
|
75
|
+
|
|
76
|
+
## Locking, unlocking, and idle auto-lock
|
|
77
|
+
|
|
78
|
+
valija has **no daemon**. Unlocking puts the vault key in your OS keychain (Windows Credential
|
|
79
|
+
Manager, macOS Keychain, Linux Secret Service); MCP tools work only while the vault is unlocked, and
|
|
80
|
+
locking removes the key.
|
|
81
|
+
|
|
82
|
+
**Idle auto-lock:** an unlocked vault re-locks itself after **15 minutes of inactivity** — the key is
|
|
83
|
+
dropped the next time any command runs after the timer elapses (there's no background timer, so it's
|
|
84
|
+
the *next* command that notices). If your AI tool suddenly reports the vault is locked, this is why —
|
|
85
|
+
just `valija unlock` again. Change or disable it:
|
|
86
|
+
|
|
87
|
+
```
|
|
88
|
+
export VALIJA_AUTOLOCK_MINUTES=30 # change the timeout (minutes)
|
|
89
|
+
export VALIJA_AUTOLOCK_MINUTES=off # disable it (0 also works)
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
`valija status` shows the effective TTL and how long the vault has been idle.
|
|
93
|
+
|
|
94
|
+
## Where your vault lives
|
|
95
|
+
|
|
96
|
+
By default the vault is a single encrypted file at `~/.valija/vault.db`, with its plaintext header
|
|
97
|
+
`vault.json` beside it. Point `VALIJA_HOME` somewhere else to move it:
|
|
98
|
+
|
|
99
|
+
```
|
|
100
|
+
export VALIJA_HOME="$HOME/.valija" # default; set it to any folder you like
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
Device-local bookkeeping (this machine's id, per-vault sync state, the idle timer) lives **separately**
|
|
104
|
+
under `VALIJA_STATE_HOME` (default `~/.valija-state`), by design outside `VALIJA_HOME` so it never
|
|
105
|
+
lands in a synced folder.
|
|
106
|
+
|
|
107
|
+
## Use it on several devices
|
|
108
|
+
|
|
109
|
+
valija has no backend. To use one vault on a laptop and a desktop, put it in a folder a sync client
|
|
110
|
+
you already trust replicates — **Dropbox, iCloud Drive, OneDrive, Google Drive, Syncthing** — and
|
|
111
|
+
point `VALIJA_HOME` at it. valija only ever touches the local filesystem; the sync client is a black
|
|
112
|
+
box to it.
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
export VALIJA_HOME="$HOME/Dropbox/valija" # once per device, same synced path
|
|
116
|
+
valija init # (or move an existing vault there)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
The passphrase, salt, and KDF params live in the plaintext `vault.json` header, which syncs alongside
|
|
120
|
+
`vault.db` — so the **same passphrase unlocks the vault on every device**. The ritual is just *lock,
|
|
121
|
+
let it sync, unlock elsewhere*:
|
|
122
|
+
|
|
123
|
+
```
|
|
124
|
+
# on device A, when you're done
|
|
125
|
+
valija lock # confirms the vault is a single file at rest, safe to sync
|
|
126
|
+
|
|
127
|
+
# …wait for your sync client to show "up to date"…
|
|
128
|
+
|
|
129
|
+
# on device B
|
|
130
|
+
valija unlock # a clean handoff adopts silently; you continue where A left off
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
**If you skip the ritual and edit two devices before they sync,** your sync client keeps one copy and
|
|
134
|
+
usually drops the other as a "conflicted copy" file. valija detects this — `unlock` still opens the
|
|
135
|
+
vault but prints a `VAULT_FORK_DETECTED` warning, and **deletes nothing**. There is no automatic
|
|
136
|
+
merge, ever, by design. `valija doctor` helps you find and resolve the conflicted copy.
|
|
137
|
+
|
|
138
|
+
See **[docs/sync.md](docs/sync.md)** for the full walkthrough: the handoff ritual, resolving a fork,
|
|
139
|
+
OneDrive's naming quirk, and what sync data is (and isn't).
|
|
140
|
+
|
|
34
141
|
## Import your history
|
|
35
142
|
|
|
36
143
|
A fresh vault is empty — but your history already lives in ChatGPT and Claude. Import it:
|
|
37
144
|
|
|
38
145
|
```
|
|
39
|
-
valija import chatgpt-export.zip -p my-history
|
|
40
|
-
valija import chatgpt-export.zip -p my-history --all
|
|
41
|
-
valija import claude.zip -p work --query "postgres"
|
|
42
|
-
valija import export.json -p misc --from generic --all
|
|
146
|
+
valija import chatgpt-export.zip -p my-history # lists conversations, writes nothing
|
|
147
|
+
valija import chatgpt-export.zip -p my-history --all # import all of them
|
|
148
|
+
valija import claude.zip -p work --query "postgres" # or pick by title / date / index
|
|
149
|
+
valija import export.json -p misc --from generic --all # any other provider (see below)
|
|
43
150
|
```
|
|
44
151
|
|
|
45
|
-
Get the export from the provider's **Export data** (ChatGPT → a `.zip` containing `conversations.json`;
|
|
152
|
+
Get the export from the provider's **Export data** (ChatGPT → a `.zip` containing `conversations.json`;
|
|
153
|
+
Claude → a `.zip`/JSON). valija auto-detects the source, or pass `--from chatgpt|claude|generic`. With
|
|
154
|
+
no selection flag it **lists** conversations so you can look before importing; select with
|
|
155
|
+
`--pick 1,3-5`, `--query`, `--since <YYYY-MM-DD>`, or `--all`, and add `--dry-run` to preview. `.zip`
|
|
156
|
+
files are read entirely in memory — nothing is extracted to disk.
|
|
46
157
|
|
|
47
|
-
Imported conversations are **searchable** (`valija search`, `valija show <project> --type imported`)
|
|
158
|
+
Imported conversations are **searchable** (`valija search`, `valija show <project> --type imported`)
|
|
159
|
+
but stay **out of context packs** — they're a searchable archive, not context that auto-loads into
|
|
160
|
+
your AI tools.
|
|
48
161
|
|
|
49
162
|
**Any other provider — two doors:**
|
|
50
163
|
|
|
@@ -55,20 +168,41 @@ Imported conversations are **searchable** (`valija search`, `valija show <projec
|
|
|
55
168
|
{ "id": "abc", "title": "optional", "createdAt": "2024-05-01T09:00:00Z",
|
|
56
169
|
"messages": [ { "role": "user", "content": "…" }, { "role": "assistant", "content": "…" } ] } ] }
|
|
57
170
|
```
|
|
58
|
-
- **Via a connected AI (no parser needed)** — because valija is an MCP server, you can hand any AI
|
|
171
|
+
- **Via a connected AI (no parser needed)** — because valija is an MCP server, you can hand any AI
|
|
172
|
+
tool an arbitrary export and ask it to distill the important parts into `save_context`. Those become
|
|
173
|
+
real, pack-eligible context (decisions, preferences, facts).
|
|
174
|
+
|
|
175
|
+
## The MCP surface (what your AI tools see)
|
|
59
176
|
|
|
60
|
-
|
|
177
|
+
Five tools — `save_context`, `save_handoff`, `get_context`, `search_context`, `list_projects` — plus
|
|
178
|
+
`/save-context` and `/load-context` prompts in clients that support them. Wire it into a client with
|
|
179
|
+
`valija install <claude-code|claude-desktop|cursor>` (it backs up the existing config first and prints
|
|
180
|
+
a manual fallback if it can't). No sync, lineage, or device data is ever exposed through an MCP tool —
|
|
181
|
+
that's CLI-only plumbing.
|
|
61
182
|
|
|
62
|
-
|
|
183
|
+
## Configuration reference
|
|
184
|
+
|
|
185
|
+
| Variable | Default | What it does |
|
|
186
|
+
|---|---|---|
|
|
187
|
+
| `VALIJA_HOME` | `~/.valija` | Vault folder (`vault.db` + `vault.json`). Point it at a synced folder to sync. |
|
|
188
|
+
| `VALIJA_AUTOLOCK_MINUTES` | `15` | Idle auto-lock timeout in minutes; `0` or `off` disables it. |
|
|
189
|
+
| `VALIJA_STATE_HOME` | `~/.valija-state` | Device-local state (device id, sync bookkeeping, idle timer). Never synced. |
|
|
63
190
|
|
|
64
191
|
## Security model (short version)
|
|
65
192
|
|
|
66
|
-
- Everything at rest is ciphertext: SQLCipher whole-database encryption, full-text search index
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
-
|
|
193
|
+
- Everything at rest is ciphertext: SQLCipher whole-database encryption, full-text search index
|
|
194
|
+
included. The only plaintext file is `vault.json` (salt + KDF params + vault id) — no context, and
|
|
195
|
+
no sync/device metadata, ever.
|
|
196
|
+
- Passphrase → Argon2id → key. Losing the passphrase **and** the recovery kit means the data is gone,
|
|
197
|
+
by design.
|
|
198
|
+
- Any MCP client you connect receives plaintext of the context you ask it to load. Encryption
|
|
199
|
+
protects data *at rest*.
|
|
200
|
+
- No telemetry, no network calls at runtime, no daemon.
|
|
201
|
+
|
|
202
|
+
## Docs
|
|
70
203
|
|
|
71
|
-
|
|
204
|
+
- **[docs/sync.md](docs/sync.md)** — using one vault across devices, in depth.
|
|
205
|
+
- **[docs/SPEC.md](docs/SPEC.md)** — the full specification.
|
|
72
206
|
|
|
73
207
|
## License
|
|
74
208
|
|
package/package.json
CHANGED