synartesis 0.8.7 → 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.
- package/CHANGELOG.md +142 -0
- package/README.md +78 -4
- package/dist/{chunk-JE7MOCZO.js → chunk-AEEKBR5D.js} +1813 -52
- package/dist/cli.js +710 -1005
- package/dist/proxy.js +182 -49
- package/manifests/aws-docs.yaml +26 -0
- package/manifests/brave.yaml +33 -0
- package/manifests/chrome-devtools.yaml +115 -0
- package/manifests/exa.yaml +20 -0
- package/manifests/fetch.yaml +20 -0
- package/manifests/github.yaml +67 -85
- package/manifests/playwright.yaml +106 -0
- package/manifests/tavily.yaml +27 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,148 @@
|
|
|
2
2
|
|
|
3
3
|
What changed, and why it mattered. Dates are release dates.
|
|
4
4
|
|
|
5
|
+
## 0.9.0 — 2026-09-24
|
|
6
|
+
|
|
7
|
+
0.8.4 to 0.8.8 made Synartesis correct once you were using it. This release is
|
|
8
|
+
about the part before and around that: connecting what you already have without
|
|
9
|
+
breaking it, and being asked less once you have. Several bugs made someone who
|
|
10
|
+
followed the instructions worse off than someone who never installed it. Those
|
|
11
|
+
come first.
|
|
12
|
+
|
|
13
|
+
### Fixed: wrapping a server no longer breaks it
|
|
14
|
+
|
|
15
|
+
- **Wrapping a server dropped its API keys.** `install` copied the client
|
|
16
|
+
entry's `env` onto the proxy's entry, and the proxy then started the real
|
|
17
|
+
server with almost none of it. Every server now starts through one path,
|
|
18
|
+
with the environment it was given. Existing installs are fixed without
|
|
19
|
+
re-running anything.
|
|
20
|
+
- **`undo` could not authenticate, and in one case undid the wrong store.** It
|
|
21
|
+
started servers with only what the policy declared, so a token held in the
|
|
22
|
+
client config was missing. For the memory server that was silent: without
|
|
23
|
+
`MEMORY_FILE_PATH` it opened its default file, sent the inverse there, and
|
|
24
|
+
reported success. `undo` now reads the environment and working directory from
|
|
25
|
+
the client entry that wraps the server. Each session records a keyed
|
|
26
|
+
fingerprint of every declared variable, never the value, and an undo whose
|
|
27
|
+
variables differ refuses and names them.
|
|
28
|
+
- **One server's missing token was everybody's problem.** `${VAR}` in a policy
|
|
29
|
+
was expanded for every server when the file was read, so undoing a filesystem
|
|
30
|
+
session failed unless the GitHub token was exported. It is expanded per
|
|
31
|
+
server, when that server starts.
|
|
32
|
+
- **A server update took GitHub down.** github-mcp-server 1.12.2 renamed the
|
|
33
|
+
tools the shipped policy read from, and the proxy refused to start. A rule
|
|
34
|
+
whose snapshot, inverse or verify tool has gone now falls back to being held,
|
|
35
|
+
and the proxy starts and says which rules it disabled. `check` still fails
|
|
36
|
+
hard. `github.yaml` is rewritten for 1.12.
|
|
37
|
+
- **`install` covers what it says.** It reads every Claude Code project, not
|
|
38
|
+
only the one it was run from (Claude Code's default scope is per project).
|
|
39
|
+
Running it again after `uninstall` covers the same server again instead of
|
|
40
|
+
duplicating it and then dropping it. Skip reasons are printed whole, where
|
|
41
|
+
"Please set SLACK_BOT_TOKEN" used to be cut off. It will not rewrite a Codex
|
|
42
|
+
table it could not fully read. `installed.json`, which holds the original
|
|
43
|
+
entries and their tokens, is now owner-only.
|
|
44
|
+
- **Bare `undo` and `show` skip empty sessions.** Most sessions record nothing;
|
|
45
|
+
bare `undo` refused on the empty one instead of finding the one with work.
|
|
46
|
+
|
|
47
|
+
### Added: cover more of what people connect
|
|
48
|
+
|
|
49
|
+
- **Browsers.** Policies for Playwright MCP and Chrome DevTools MCP, written
|
|
50
|
+
from each server's real tool list. Reads are reads. Every interaction is
|
|
51
|
+
recorded, arguments included, and not held: nothing a browser does can be
|
|
52
|
+
undone, and holding every click made both unusable. Running agent-written
|
|
53
|
+
code and uploading files are still held.
|
|
54
|
+
- **A tool its server marks read-only is read as a read** when no rule mentions
|
|
55
|
+
it, instead of held. The MCP specification calls annotations untrusted unless
|
|
56
|
+
they come from a trusted server; the trust relied on is that you chose to
|
|
57
|
+
connect this one. It only ever loosens a hold on a read. It never applies on a
|
|
58
|
+
pinned server, `trust_annotations: false` turns it off, and `check` lists
|
|
59
|
+
every tool let through this way.
|
|
60
|
+
- **Hosted servers.** A server with a token in its headers is reached directly:
|
|
61
|
+
Streamable HTTP, falling back to SSE only where the server says it does not
|
|
62
|
+
speak the newer one, with redirects refused. `install` moves the header values
|
|
63
|
+
into the client entry's `env`, and the policy names the variables. A request
|
|
64
|
+
refused at the door, such as an expired token, is recorded as never sent. A
|
|
65
|
+
server that signs in through a browser is covered with `install --remote`,
|
|
66
|
+
through mcp-remote, which keeps the sign-in itself.
|
|
67
|
+
- **Four more clients:** Gemini CLI, GitHub Copilot CLI, Antigravity, and
|
|
68
|
+
Devin Desktop (what Windsurf became) plus the older Windsurf path. Every path
|
|
69
|
+
and variable syntax was checked against the vendor's own documentation.
|
|
70
|
+
- **Read-only policies** for fetch, Brave Search, Exa, Tavily and the AWS
|
|
71
|
+
documentation server. Each server was started and its tool list read first.
|
|
72
|
+
|
|
73
|
+
### Added: ask less, tell the person
|
|
74
|
+
|
|
75
|
+
- **A desktop notification when a call is held**, on macOS and Linux. It names
|
|
76
|
+
the server and the tool, never the arguments. `synartesis notify --test`
|
|
77
|
+
checks it reaches you; `SYNARTESIS_NOTIFY=0` turns it off.
|
|
78
|
+
- **`synartesis allow <server.tool>`.** `--for 1h` stops holding that tool until
|
|
79
|
+
the time runs out, with no restart. `--always` edits the policy in place,
|
|
80
|
+
keeping its comments, and a tool that cannot be undone stays marked that way
|
|
81
|
+
(you type its name to confirm). `--stop` holds it again. `A` in `watch` and
|
|
82
|
+
the console, and a button on the desktop card, approve the call in front of
|
|
83
|
+
you and allow the tool for an hour.
|
|
84
|
+
- **A person's no reaches the agent.** A retry of a denied call is told who
|
|
85
|
+
said no, when and why, instead of opening a fresh hold. `approve` on the
|
|
86
|
+
denied call takes the denial back. Denials live in their own table, so a
|
|
87
|
+
spent approval, which is also stored as denied, is never reported as a refusal.
|
|
88
|
+
- **Why a call is held.** A tool with no rule says so, rather than "this action
|
|
89
|
+
cannot be undone".
|
|
90
|
+
|
|
91
|
+
### Changed
|
|
92
|
+
|
|
93
|
+
- **The agent is never handed the command to approve its own call.** It used
|
|
94
|
+
to be in the refusal text and in the instructions every agent receives, and
|
|
95
|
+
an agent with a shell could run it, recorded under your name. `approve` and
|
|
96
|
+
`allow` now need a person at a terminal unless given `--unattended`, which is
|
|
97
|
+
recorded. This stops an agent following instructions or making a mistake. It
|
|
98
|
+
does not stop a process working to defeat it while running as you, which can
|
|
99
|
+
write the journal directly.
|
|
100
|
+
- **`show` and `undo` speak the same words as everything else.** No more
|
|
101
|
+
`reversible applied` or `result rolled_back` at the end of a dry run that
|
|
102
|
+
wrote nothing. A read-heavy session's reads fold into one line.
|
|
103
|
+
- **`install --print` starts nothing.** It promised to write nothing and then
|
|
104
|
+
started every server, which meant a download for each npx server and a
|
|
105
|
+
browser window for each sign-in. `install` also says which server it is
|
|
106
|
+
starting, instead of going quiet until the last one answers.
|
|
107
|
+
- `check` offers `pin` only once the policy has been used. The desktop window
|
|
108
|
+
points at `install`, not bare `init`. The `--http` server answers an ended
|
|
109
|
+
session with 404, as the MCP specification asks.
|
|
110
|
+
- A policy using `{{args.id}}` (loaded, then sent as those characters) or
|
|
111
|
+
`${args.id}` (failed with no line number) is refused with the line and the
|
|
112
|
+
spelling that works.
|
|
113
|
+
|
|
114
|
+
### Docs
|
|
115
|
+
|
|
116
|
+
- The user guide's only complete policy example did not parse. It does now,
|
|
117
|
+
and a test loads every policy shown in the README, the guide and the install
|
|
118
|
+
page. The manual setup snippets give each server its own entry with
|
|
119
|
+
`--server`, and the Claude Code command has its `--`.
|
|
120
|
+
|
|
121
|
+
## 0.8.8 — 2026-09-22
|
|
122
|
+
|
|
123
|
+
### Fixed
|
|
124
|
+
|
|
125
|
+
- **The GitHub Models preset added in 0.8.7 could never have worked.** GitHub
|
|
126
|
+
retired its inference API on 30 July 2026, three weeks before that entry was
|
|
127
|
+
written. The host is still there and still answers -- `200 OK`, with
|
|
128
|
+
`content-type: text/plain` and a body of `OK`, whatever path you ask for --
|
|
129
|
+
which is exactly the shape of thing that looks alive until you try to use
|
|
130
|
+
it. The entry was built from blog posts and community threads, every one of
|
|
131
|
+
them written before the retirement, while the vendor's own documentation
|
|
132
|
+
said in plain words that the API was gone.
|
|
133
|
+
|
|
134
|
+
Removed, and replaced with **OpenRouter**: one key, many models, and
|
|
135
|
+
nineteen of the free ones currently advertise tool support, which is the
|
|
136
|
+
constraint that actually decides whether a model can drive this window at
|
|
137
|
+
all. Its catalogue is public, so which nineteen can be checked rather than
|
|
138
|
+
guessed.
|
|
139
|
+
|
|
140
|
+
Groq, added in the same release, was checked the same way and is fine.
|
|
141
|
+
|
|
142
|
+
The note now at the head of the preset list is the part worth keeping: send
|
|
143
|
+
a request to the host before adding one. A preset that does not work is
|
|
144
|
+
worse than no preset, because the person who picks it concludes this window
|
|
145
|
+
is broken rather than that the service is.
|
|
146
|
+
|
|
5
147
|
## 0.8.7 — 2026-09-22
|
|
6
148
|
|
|
7
149
|
### Added
|
package/README.md
CHANGED
|
@@ -102,7 +102,8 @@ Then, from anywhere:
|
|
|
102
102
|
synartesis install
|
|
103
103
|
```
|
|
104
104
|
|
|
105
|
-
That finds what Claude Code, Claude Desktop, Cursor
|
|
105
|
+
That finds what Claude Code, Claude Desktop, Cursor, Codex, Gemini CLI, Copilot
|
|
106
|
+
CLI, Antigravity or Devin Desktop (Windsurf) already list,
|
|
106
107
|
writes one policy covering all of it, and points each entry at the proxy.
|
|
107
108
|
Servers it recognises get the policy that ships for them and work immediately;
|
|
108
109
|
the rest are drafted with every tool held until you say how to undo it. Your
|
|
@@ -219,12 +220,15 @@ Every tool gets one of four classifications, written down in a manifest:
|
|
|
219
220
|
| `readonly` | Changes nothing | `get_customer` | Recorded, forwarded |
|
|
220
221
|
| `reversible` | Prior state can be restored exactly | `update_customer` | State captured before the write; written back on undo |
|
|
221
222
|
| `compensable` | Cannot be reversed, but can be offset | `create_charge` | A different call neutralises it |
|
|
222
|
-
| `irreversible` | Neither | `send_email` | **Suspended until a human approves it
|
|
223
|
+
| `irreversible` | Neither | `send_email` | **Suspended until a human approves it**, or recorded without asking where the policy says `gate: never` |
|
|
223
224
|
|
|
224
225
|
A tool your manifest does not mention is treated as `irreversible`. That is
|
|
225
226
|
deliberate: silently forwarding an unknown destructive call is the one failure
|
|
226
|
-
worth avoiding most.
|
|
227
|
-
|
|
227
|
+
worth avoiding most. The one exception is a tool its own server marks
|
|
228
|
+
read-only: that is read as a read, and `check` lists every tool let through that
|
|
229
|
+
way, so you can see exactly what was trusted. (`trust_annotations: false` on a
|
|
230
|
+
server turns it off, and a pinned server never gets it.) `synartesis check`
|
|
231
|
+
names the rest, so you meet that decision before your agent does.
|
|
228
232
|
|
|
229
233
|
A few calls are reversible only when nothing is in the way — moving a file onto
|
|
230
234
|
a free path is undone by moving it back, moving it onto an existing file
|
|
@@ -235,6 +239,65 @@ than putting half of it back and calling that success.
|
|
|
235
239
|
|
|
236
240
|
---
|
|
237
241
|
|
|
242
|
+
## Being asked less, and told when it matters
|
|
243
|
+
|
|
244
|
+
**You hear about a held call when it happens.** On macOS and Linux a desktop
|
|
245
|
+
notification names the server and the tool, never the arguments, since they can
|
|
246
|
+
carry secrets and notification history is kept. `synartesis notify --test`
|
|
247
|
+
checks it reaches you; `SYNARTESIS_NOTIFY=0` turns it off. Windows has none yet,
|
|
248
|
+
and `watch` shows every held call on every platform.
|
|
249
|
+
|
|
250
|
+
**Stop being asked, for a while or for good.**
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
synartesis allow crm.send_email --for 1h # a row in the journal; next call on
|
|
254
|
+
synartesis allow crm.send_email --always # edits the policy; next client restart
|
|
255
|
+
synartesis allow crm.send_email --stop # held again from the next call
|
|
256
|
+
synartesis allow # what is let through right now
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
`--for` goes up to a day and runs out by itself. `--always` changes only that
|
|
260
|
+
tool's gate, in place, keeping every comment in the file. A tool that cannot be
|
|
261
|
+
undone stays marked that way everywhere it shows up: it is recorded, just no
|
|
262
|
+
longer held. For those you type the tool's name to confirm. In `watch` and the
|
|
263
|
+
console, `A` approves the call in front of you and stops asking about that tool
|
|
264
|
+
for an hour. The desktop card has the same button.
|
|
265
|
+
|
|
266
|
+
**A no reaches the agent.** When you deny a call and the agent tries the same
|
|
267
|
+
call again, it is told who said no, when, and why. It does not see a fresh
|
|
268
|
+
"waiting for approval". `approve` on the denied call takes the denial back.
|
|
269
|
+
|
|
270
|
+
**The agent is never handed the way to approve itself.** Nothing it reads
|
|
271
|
+
contains an `approve` or `allow` command, and both refuse to run without a
|
|
272
|
+
person at a terminal unless given `--unattended`, which is recorded as such.
|
|
273
|
+
|
|
274
|
+
---
|
|
275
|
+
|
|
276
|
+
## Hosted servers and browsers
|
|
277
|
+
|
|
278
|
+
**Hosted servers.** A server your client reaches at a `url` with a token in its
|
|
279
|
+
headers is covered directly. `install` moves the header values into the
|
|
280
|
+
client entry's `env`, where the client already keeps secrets, and the policy
|
|
281
|
+
names the variables rather than holding the token. The proxy speaks Streamable
|
|
282
|
+
HTTP, falls back to SSE only where the server says it does not speak the newer
|
|
283
|
+
one, and refuses redirects. A request the server refuses at the door (an
|
|
284
|
+
expired token, say) is recorded as never sent, not as an outcome nobody knows.
|
|
285
|
+
A server that signs you in through a browser instead is covered with
|
|
286
|
+
`install --remote`, through [mcp-remote](https://www.npmjs.com/package/mcp-remote),
|
|
287
|
+
which does the sign-in and keeps the token itself.
|
|
288
|
+
|
|
289
|
+
**Browsers.** Nothing a browser does can be undone, and holding every click
|
|
290
|
+
made Playwright and Chrome DevTools unusable behind this. Their shipped policies
|
|
291
|
+
read reads as reads and record every interaction, arguments included, without
|
|
292
|
+
holding it. Running code the agent wrote, and uploading files from your disk,
|
|
293
|
+
are still held.
|
|
294
|
+
|
|
295
|
+
**Policies that ship:** filesystem, memory, git, github, Playwright, Chrome
|
|
296
|
+
DevTools, and a read-only set for fetch, Brave Search, Exa, Tavily and the AWS
|
|
297
|
+
documentation server. Each was written from the server's real tool list.
|
|
298
|
+
|
|
299
|
+
---
|
|
300
|
+
|
|
238
301
|
## Writing a policy for your own server
|
|
239
302
|
|
|
240
303
|
Four servers ship with a policy. For anything else — a database, a ticketing
|
|
@@ -407,6 +470,7 @@ get it if it is not installed.
|
|
|
407
470
|
|---|---|
|
|
408
471
|
| `synartesis` | The screen. Everything below can be done from it |
|
|
409
472
|
| `install` / `uninstall` / `status` | Cover the clients on this machine, put them back, say what is covered |
|
|
473
|
+
| `install --remote` | Also cover hosted servers that sign in through a browser, via mcp-remote |
|
|
410
474
|
| `init <server> -- <cmd>` | Introspect a server and draft a manifest |
|
|
411
475
|
| `check` | Load a manifest and verify it against the servers it names |
|
|
412
476
|
| `pin` | Print the `pins:` block for the servers you have now |
|
|
@@ -415,6 +479,8 @@ get it if it is not installed.
|
|
|
415
479
|
| `show <id> --live` | The same, plus what has changed in the world since |
|
|
416
480
|
| `show <id> --full` | Every argument, snapshot and inverse, nothing elided |
|
|
417
481
|
| `gates` / `approve <id>` / `deny <id>` | What is waiting, and answering it |
|
|
482
|
+
| `allow <server.tool> --for 1h \| --always \| --stop` | Stop being asked about one tool, for a while or for good |
|
|
483
|
+
| `notify --test` | Send one notification, to see whether they reach you |
|
|
418
484
|
| `resolve <id> --applied\|--failed` | Settle a call whose outcome nothing established |
|
|
419
485
|
| `undo <id>` | Reverse a session, newest action first |
|
|
420
486
|
| `undo <id> --dry-run` | Plan it and change nothing |
|
|
@@ -515,6 +581,14 @@ holding a call waiting on a person, or one whose undo halted on a conflict. A
|
|
|
515
581
|
pruned session cannot be undone afterwards, which is the whole of the trade.
|
|
516
582
|
Nothing prunes on a timer.
|
|
517
583
|
|
|
584
|
+
**What needing a terminal protects against.** `approve` and `allow` refuse to
|
|
585
|
+
run without a person at a terminal, and nothing an agent reads names them. That
|
|
586
|
+
stops an agent following its instructions, or making a mistake, into approving
|
|
587
|
+
its own calls. It does not stop a process working to defeat it while running as
|
|
588
|
+
you: anything with your permissions can write the journal directly. For a
|
|
589
|
+
boundary the agent cannot cross, deny it those commands in its own permission
|
|
590
|
+
settings.
|
|
591
|
+
|
|
518
592
|
**Durability.** The journal runs `synchronous = NORMAL`. A crash of the process
|
|
519
593
|
or of the CLI mid-undo loses nothing; only the machine losing power can cost the
|
|
520
594
|
tail of the write-ahead log. `SYNARTESIS_SYNC=full` asks for an fsync per commit
|