@hraness/message-like-me 0.8.20 → 0.8.22

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.
@@ -1,15 +1,16 @@
1
1
  # Start using Textbutler
2
2
 
3
- Textbutler is a local Mac assistant for selected conversations. Start with its
4
- inbox and replies you write yourself. Automatic replies stay paused until you
5
- choose a ready agent and explicitly enable a contact.
6
-
7
- AI replies require a verified Textbutler bundle with reviewed composition
8
- admission and use a separately installed [xcb](https://github.com/hraness/xcb)
9
- native runtime and an explicitly connected subscription account. This local
10
- pilot requires current xcb admission and a successful account check. Installation
11
- does not enable replies, and live messaging still needs verification with your
12
- chosen recipient. Claude API retains a separate trusted runtime admission gate.
3
+ Textbutler is an AI butler for the iMessage, WhatsApp, and Beeper chats you choose on your Mac.
4
+ Start with its inbox and replies you write yourself. Automatic replies stay
5
+ paused until you choose a ready agent account, turn them on for a contact, and
6
+ resume the butler.
7
+
8
+ AI replies need a local build of Textbutler and a Claude Code, Codex, or Devin
9
+ subscription connected through [xcb](https://github.com/hraness/xcb). The account
10
+ also has to pass `providers check`. Installing doesn't turn replies on, and you
11
+ should test live messaging with a recipient you trust. The Claude API route
12
+ needs a separately reviewed runtime that neither the source checkout nor the
13
+ local build supplies.
13
14
 
14
15
  ## Open the guided terminal
15
16
 
@@ -27,11 +28,11 @@ bun run textbutler:install
27
28
  ~/.local/bin/textbutler
28
29
  ```
29
30
 
30
- The installer builds a self-contained local pilot, checks the reviewed
31
- composition receipt against current source and contact profiles, and verifies
32
- its contents and exact Bun runtime before use. Missing or stale composition
33
- evidence blocks the build. Source daemon startup carries no such admission and
34
- keeps subscription inference unavailable. It starts no services and connects no accounts.
31
+ The installer builds a self-contained local copy, checks your source files and
32
+ both contact permission profiles against the reviewed record in
33
+ `qualification/`, and verifies its contents and exact Bun runtime before use. If
34
+ the source doesn't match the reviewed record, the build stops. A daemon started
35
+ from source never runs AI replies. The installer starts no services and connects no accounts.
35
36
  An existing, different `textbutler` command is preserved. This is a local build,
36
37
  not a signed public release. Connect xcb separately for AI replies. Keep the same
37
38
  Bun runtime installed. To upgrade a verified existing installation, stop its
@@ -41,7 +42,7 @@ rollback, and atomically switches the command. It never replaces an unrelated
41
42
  command or changes your settings. Restart the installed daemon afterward.
42
43
 
43
44
  The terminal has numbered actions for setup, app connections, conversations,
44
- replies, contacts, pause and the menu bar. Enter goes back from a selection;
45
+ replies, contacts, pause, the menu bar and macOS access. Enter goes back from a selection;
45
46
  `q` or Ctrl-C closes the terminal. It does not stop an installed background
46
47
  service. Commands below use `bun run textbutler`; the help abbreviates that
47
48
  prefix to `textbutler`. You can use `~/.local/bin/textbutler` for these commands.
@@ -100,9 +101,42 @@ source service is installed.
100
101
  See [messaging app support](messaging-apps.md) for Beeper limitations and native
101
102
  alternatives, including requirements that affect Telegram AI processing.
102
103
 
103
- ## Give TextButler access to iMessage
104
+ ## Shape a contact's butler
105
+
106
+ Contact habitats keep a small owner-authored `soulCore` (voice, relationship
107
+ context, shared context and boundaries) separate from the butler's learned tone
108
+ and formality. The contact-local memory archive can retain 64 sourced notes;
109
+ each reply sees only a small snapshot, and the butler can search older notes
110
+ locally for relevant preferences or open topics. Inspect or clear it with
111
+ `habitats show CONTACT` or `habitats memory-clear CONTACT REVISION`.
112
+
113
+ Search and memory are contact-scoped. JavaScript is separately disabled by
114
+ default; enable it only for a contact whose butler should receive the pure-data
115
+ tool. It runs code in a fresh QuickJS WebAssembly runtime without network,
116
+ filesystem, timers or host APIs, under strict CPU and memory budgets. Exa web
117
+ search remains separately owner-controlled and can send public queries to the
118
+ search provider, so leave it off when that is not wanted.
119
+
120
+ Configure an individual plan while the daemon is paused, using the exact
121
+ revision reported by `habitats show CONTACT`:
122
+
123
+ ```sh
124
+ textbutler habitats configure CONTACT REVISION '{"version":1,"guidance":"Be considerate and remember useful shared context without assuming familiarity.","contextMessages":12,"maxReplyCharacters":640,"humor":"match","webSearch":false,"memeSearch":true,"javascript":true,"memorySearch":true,"soulCore":{"voice":"Warm and concise","relationshipContext":"Longtime friend","sharedContext":"They are planning a trip together","boundaries":"Do not make plans or commitments for the owner"}}'
125
+ ```
104
126
 
105
- Use the native app when you want macOS Full Disk Access to belong to TextButler.
127
+ Replace the contact ID and plan values with what you want for that conversation.
128
+ The learned style can evolve from sourced feedback, but it cannot rewrite the
129
+ owner-authored `soulCore` or change tool grants. Tool output is evidence, never
130
+ permission to send a message. See [contact calculation and memory tools](javascript-tools.md)
131
+ for the runtime limits and memory-search behavior.
132
+
133
+ ## Give Textbutler access to iMessage
134
+
135
+ In the guided terminal, **Give Textbutler access** walks you through the two
136
+ macOS settings below in order and opens each System Settings pane when you
137
+ press Enter or `o`. It never causes a macOS prompt itself.
138
+
139
+ Use the native app when you want macOS Full Disk Access to belong to `TextButler.app`.
106
140
  The app supervises its pinned runtime and background service. Build it from an
107
141
  already installed, verified payload on your Mac:
108
142
 
@@ -113,15 +147,17 @@ bun run textbutler:app build \
113
147
  bun run textbutler:app install --from /absolute/new/app-build-directory
114
148
  ```
115
149
 
116
- The default destination is `~/Applications/TextButler.app`. Building and
117
- installing the app does not start replies or change macOS permissions. In
150
+ The default destination is `~/Applications/TextButler.app`, which macOS lists
151
+ as Textbutler. Building and installing the app does not start replies or change
152
+ macOS permissions. macOS never asks for Full Disk Access, so `install` ends
153
+ with a notice; at a terminal, press Enter to open the Full Disk Access pane. In
118
154
  **System Settings → Privacy & Security → Full Disk Access**, click **+**, press
119
155
  **Command-Shift-G**, enter `~/Applications/TextButler.app`, and choose **Open**.
120
156
  Enable its switch. macOS may require your password in its own dialog.
121
157
 
122
158
  Configure the exact Ghostget `src/cli.ts`, Bun runtime, private state directory
123
159
  and `imessage:ACCOUNT` binding using `setup` above. This development version pins
124
- Ghostget 0.18.21 and its reviewed `imsg` helper artifact. Native setup provisions
160
+ Ghostget 0.18.43 and its reviewed `imsg` helper artifact. Native setup provisions
125
161
  that pinned helper into the connector state directory (`imessage transport install`)
126
162
  before linking; a missing or mismatched artifact stops setup instead of reaching
127
163
  messaging. Setup links only
@@ -137,6 +173,12 @@ bun run textbutler:app imessage-setup \
137
173
  --data-dir "$HOME/Library/Application Support/Textbutler"
138
174
  ```
139
175
 
176
+ Before macOS asks to let Textbutler control Messages, setup prints a notice;
177
+ press Enter to continue or `s` to skip. If you choose Don't Allow, macOS won't
178
+ ask again: turn on Textbutler in **System Settings → Privacy & Security →
179
+ Automation**, then run the setup command again. `textbutler doctor` shows
180
+ which of these steps is left.
181
+
140
182
  After app setup completes, use the installed `daemon install` command to
141
183
  register its background service. If an older service is installed, first use
142
184
  `daemon uninstall`; this preserves your settings and contacts. Startup verifies
@@ -153,11 +195,26 @@ with the following command:
153
195
  bun run textbutler:app install --from /absolute/new/app-build-directory --upgrade
154
196
  ```
155
197
 
198
+ Apps now include the Textbutler icon, and releases from before the icon can't
199
+ verify them. To go back to an earlier release, stop the
200
+ service, move `~/Applications/TextButler.app` and `state/macos-app.json` in
201
+ your data folder somewhere safe, then build and install the app from that
202
+ release. Then turn on macOS access for the reinstalled app again.
203
+
156
204
  The upgrade verifies both versions and retains the previous signed
157
205
  app and receipt. If it reports an uncertain transition, preserve its records
158
206
  and reconcile that transition before retrying. Recheck Full Disk Access and
159
207
  Messages Automation after the upgrade.
160
208
 
209
+ Changing the connector's provider implementation changes its reported
210
+ identity. Existing conversation enrollments then report that the provider
211
+ identity changed and must be enrolled again; per-operation owner permissions
212
+ likewise key on the implementation and must be approved again through the
213
+ permission command. Re-enrolling preserves each contact's memory and run
214
+ history: enroll the same conversation coordinate, grant the new binding, and
215
+ update the contact's route reference to the new enrollment in one owner-state
216
+ write, then revoke the superseded grants.
217
+
161
218
  See [local data](local-data.md) for retained setup records and installation data
162
219
  removal. Repeating setup preserves an already linked account and its identity.
163
220
 
@@ -181,8 +238,8 @@ bun run textbutler setup \
181
238
  --xcb-model FULL_MODEL_KEY
182
239
  ```
183
240
 
184
- For Codex, use `--xcb-account codex:ACCOUNT_ID` and a matching observed model.
185
- Repeat setup to add a second account. The command pins the executable bytes and
241
+ For Codex or Devin, use `--xcb-account codex:ACCOUNT_ID` or `--xcb-account devin:ACCOUNT_ID`
242
+ and a matching observed model. Repeat setup to add another provider's account. The command pins the executable bytes and
186
243
  explicit routing; it does not activate a contact. Setup refuses changes to an
187
244
  existing binary or account/model binding. After an xcb upgrade, stop the daemon
188
245
  and review its private `state/host.json` binding before updating the executable
@@ -244,10 +301,25 @@ bun run textbutler menubar install
244
301
  `start` opens it now; `install` registers login startup. The first start retrieves
245
302
  and verifies the pinned shared native companion. No local Rust build is needed.
246
303
 
247
- The menu gives you pause, connection checks, conversation selection, per-contact
248
- activation, agent selection, the reply inbox and recent activity. Draft previews
249
- are intentionally labeled: use the terminal to review complete outgoing actions
250
- before sending. The menu cannot send hidden or truncated draft content.
304
+ The menu starts with one status line, then the one thing to do next: start
305
+ Textbutler, open the macOS setting iMessage still needs, read the setup guide,
306
+ or check for replies. **Conversations** holds per-contact replies and agent
307
+ choice, conversation search and app connections; **Pause automatic replies**
308
+ and **Resume automatic replies** sit at the top level. **Details** keeps
309
+ activity, agent accounts and capabilities out of the way. When an action
310
+ doesn't work, a ⚠︎ line under the status says why. Suggestions show a preview
311
+ only: use the terminal to review complete outgoing actions before sending. The
312
+ menu cannot send hidden or truncated draft content.
313
+
314
+ If you installed `TextButler.app`, you can have it run the menu too, so macOS
315
+ lists Textbutler rather than Bun under Login Items. This is off by default while
316
+ the local app identity is checked on a clean macOS account. To try it, use the
317
+ installed command the app was built from:
318
+ `HRANESS_LOCAL_APP=1 ~/.local/bin/textbutler menubar install`. If the app was
319
+ built from another version, the command stops and says so. After
320
+ `bun run textbutler:install --upgrade`, the installer tells you when the menu
321
+ still starts the previous version: run `textbutler menubar install` again, or
322
+ rebuild and upgrade the app when the menu runs through it.
251
323
 
252
324
  Menu startup and daemon startup are separate. Quitting the menu leaves the
253
325
  installed daemon running. `menubar stop` closes the menu; `daemon uninstall`
@@ -8,8 +8,8 @@ menu companion's private helper or open provider databases.
8
8
 
9
9
  The automation contract was first admitted with
10
10
  [Ghostget 0.18.2](https://github.com/hraness/ghostget/releases/tag/v0.18.2).
11
- This development version of native TextButler iMessage setup pins Ghostget
12
- 0.18.21. Its matching artifact and live conversation checks remain pending.
11
+ This development version of the native `TextButler.app` iMessage setup pins Ghostget
12
+ 0.18.43. Its matching artifact and live conversation checks remain pending.
13
13
  The required contract preserves the native helper's resource bundle, avoids
14
14
  opening unrelated protected folders during state validation, and exposes bounded
15
15
  discovery diagnostics without message bodies. Valid native chat rows without
@@ -39,7 +39,7 @@ Restarting Textbutler does not silently clear it.
39
39
  | --- | --- |
40
40
  | `status`, `start` | Observe capabilities; explicitly start supported synchronization. |
41
41
  | `conversations`, `enroll`, `enrollments` | Exact account generation and direct participant-bound conversation enrollment. |
42
- | `poll`, `history`, `events` | Bounded history, durable observation cursors, revisions, catch-up and gap detection. |
42
+ | `poll`, `pollSet`, `history`, `events` | Bounded history, durable observation cursors, revisions, catch-up and gap detection; `pollSet` shares one provider session across a contact set and reports each enrollment separately. An enrollment busy with another operation reports its current stored row — not necessarily synced this tick. |
43
43
  | `grant`, `grant.get`, `grant.by-intent`, `revoke` | Recipient, action, expiry and quota limits; idempotent issuance lookup and immediate revocation. |
44
44
  | `asset`, `prepare` | Admit exact attachment bytes and bind the ordered action list to a context revision and expiry. |
45
45
  | `submit`, `cancel`, `run` | Journal an action claim before dispatch and retain accepted, failed, partial or indeterminate results. |
@@ -0,0 +1,63 @@
1
+ # Contact calculation and memory tools
2
+
3
+ Each contact plan controls two local tools. `memorySearch` defaults to `true` and
4
+ searches that conversation's retained memory archive. `javascript` defaults to
5
+ `false`; enable it in the owner's complete plan with `habitats configure` while
6
+ automatic replies are paused. Learning preserves both flags.
7
+
8
+ Memory search ranks exact words and phrases in the contact's source notes. It
9
+ returns up to eight excerpts with their source IDs, digests, authors and
10
+ categories. Each excerpt contains at most 256 UTF-8 bytes, and the complete result
11
+ fits within 4,096 bytes. Results report omitted matches and shortened text. A
12
+ search reads the archive without changing it or contacting an external service.
13
+
14
+ JavaScript supports small calculations and data transformations. The model supplies
15
+ a synchronous function body and optional JSON input, available as `input`:
16
+
17
+ ```json
18
+ {"kind":"javascript","code":"return input.prices.reduce((total, price) => total + price, 0);","input":{"prices":[12,8,5]}}
19
+ ```
20
+
21
+ The result is JSON, such as `{"ok":true,"value":25}`. A failed calculation returns
22
+ a bounded error code. The model may use the remaining tool call to correct it.
23
+ All tools share the existing limit of two calls per reply.
24
+
25
+ Each calculation runs in a new QuickJS interpreter compiled to WebAssembly. The
26
+ host supplies only copied JSON. There are no file, network, process, module,
27
+ timer or messaging APIs inside the interpreter. `Date` and `Math.random` are
28
+ unavailable. A calculation cannot inspect contact memory unless the reply agent
29
+ passes selected data as input. That data stays on the local host during execution.
30
+
31
+ | Resource | Limit |
32
+ | --- | --- |
33
+ | Code | 8,192 UTF-8 bytes |
34
+ | Input JSON | 16,384 UTF-8 bytes |
35
+ | Output JSON | 4,096 UTF-8 bytes |
36
+ | QuickJS heap | 8 MiB |
37
+ | Interpreter stack | 256 KiB |
38
+ | Cooperative interrupt | 50 ms, with at most 5,000 interrupt checks |
39
+ | Worker watchdog | 250 ms after worker startup; a calculation that misses this gets a resource-limit result and termination is requested |
40
+ | Worker startup | 2,000 ms maximum before a bounded failure result |
41
+ | Worker admission | One active worker, up to sixteen queued calls, with a 5,000 ms queue wait |
42
+ | Input/output structure | 16 levels and 1,024 values |
43
+
44
+ The interpreter checks its deadline during execution and is disposed after every
45
+ call. A separate worker watchdog requests termination if a native engine
46
+ operation fails to reach an interrupt check. The host returns a bounded
47
+ resource-limit result; one worker remains active, and at most sixteen later calls
48
+ wait up to five seconds for its slot. Calls beyond that queue return
49
+ resource-limit. If termination cannot be confirmed, JavaScript stays unavailable
50
+ for that app process and queued calls time out; restarting the app clears the
51
+ fail-closed guard. JSON output rejects pending asynchronous work. Loading the
52
+ interpreter and generating the model response take additional time. The
53
+ WebAssembly runtime and worker have fixed overhead outside the QuickJS heap
54
+ limit.
55
+
56
+ Submitted replies retain tool outcomes for inspection and reflection. JavaScript
57
+ evidence labels the code with its SHA-256 digest. Offline personality evaluation
58
+ does not execute either tool and cannot measure tool behavior from a text replay.
59
+
60
+ The implementation uses the pinned `quickjs-emscripten-core` and embedded
61
+ `@jitl/quickjs-singlefile-browser-release-sync` packages. The upstream
62
+ [runtime documentation](https://github.com/justjake/quickjs-emscripten/blob/main/doc/quickjs-emscripten/classes/QuickJSRuntime.md)
63
+ describes interpreter memory, stack and interrupt controls.
@@ -2,7 +2,7 @@
2
2
 
3
3
  Textbutler keeps settings, contact memory, reply journals and setup records in
4
4
  `~/Library/Application Support/Textbutler`, unless you select another data
5
- directory. These files are private to the Mac user. XCB and Ghostget keep their
5
+ directory. These files are private to the Mac user. xcb and Ghostget keep their
6
6
  own accounts and credentials in their separately configured state directories.
7
7
 
8
8
  Explicit CLI media imports live in the selected contact's private `outbox`.
@@ -24,9 +24,22 @@ directory until completion or rollback is proven. Keep both locations intact
24
24
  while an upgrade is unresolved.
25
25
 
26
26
  When habitats are enabled, the run journal additionally keeps per-contact
27
- habitat state (the promoted reply plan, bounded reply episodes, observed
28
- follow-up windows, evaluation records and rollback lineage), replayable
29
- inference receipts for each evaluation, and a global daily table of API
27
+ habitat state (personality and tool configuration, owner-authored soul anchors,
28
+ learned excerpts, reply episodes, observed follow-up windows, evaluation records
29
+ and rollback history). A reply episode can include up to two tool queries and
30
+ results shortened to 4 KiB each, plus the kinds of actions submitted. Learned
31
+ memory holds up to 64 source-backed 1 KiB excerpts under a 96 KiB encoded archive
32
+ limit, with categories, source message IDs, authors, dates, source digests and
33
+ truncation flags. Digests cover the bounded canonical observations used by
34
+ learning. Episodes retain at most eight 512-byte excerpts shown while composing
35
+ the final reply, plus up to 24 IDs and digests for excerpts exposed only by tool
36
+ steps. Clearing learned memory removes the active excerpts and prevents older
37
+ observations from restoring them; retained episodes, inference records and
38
+ `MEMORY.md` are separate records. JavaScript tool evidence stores a code digest,
39
+ not executable source, and a bounded result.
40
+ Habitat state is limited to 512 KiB per
41
+ contact. The journal keeps the latest 32 replayable inference records per
42
+ contact and a global daily table of API
30
43
  usage reservations with their provider-cost settlements. Gateway and other
31
44
  provider credentials live under `state/provider-credentials` with owner-only
32
45
  permissions; they never enter contact workspaces or journal evidence.
@@ -47,7 +60,7 @@ needed to settle that operation first.
47
60
  To erase an installation, the owner can then delete its complete Textbutler
48
61
  data directory. This removes settings, contact memory, journals, setup results
49
62
  and the iMessage account binding. It does not delete Messages history, Ghostget
50
- or XCB accounts, or macOS permission grants. Removing individual binding or
63
+ or xcb accounts, or macOS permission grants. Removing individual binding or
51
64
  custody records is not a supported way to replace an account or retry a failed
52
65
  operation. Reinstalling the command and uninstalling the background service
53
66
  both preserve data by default.
@@ -29,7 +29,7 @@ repository's layout. This change does not activate a provider backend.
29
29
  application work or turn the operation into success.
30
30
  - The existing contact task profile still requires `noCommandTools`, exact tool
31
31
  inventory, read/write isolation, isolated configuration, authentication outside
32
- the workspace and `hostBrokerOnly`. Oompa's persistent coding session is a
32
+ the workspace and `hostBrokerOnly`. xcb's persistent coding session is a
33
33
  separate explicit profile. It cannot reuse the contact task policy unchanged.
34
34
 
35
35
  ## 1. Package-local process seam
@@ -186,7 +186,7 @@ admission and application factory wiring remain pending:
186
186
  confinement, relay and account-generation checks retain their existing owners.
187
187
  - Keep the current unqualified task paths unavailable until each exact runtime,
188
188
  configuration and effective tool inventory has relevant evidence. Add a
189
- separate persistent coding profile for Oompa, with its own application
189
+ separate persistent coding profile for xcb, with its own application
190
190
  authority and lifecycle, rather than widening contact task capabilities.
191
191
 
192
192
  Acceptance requires migration of actual consumers and removal of replaced
@@ -1,7 +1,7 @@
1
1
  # AI subscriptions through xcb
2
2
 
3
3
  Textbutler uses [xcb (Excalibur)](https://github.com/hraness/xcb) to draft replies
4
- through an explicitly connected Claude Code or Codex subscription. xcb owns
4
+ through an explicitly connected Claude Code, Codex, or Devin subscription. xcb owns
5
5
  provider sign-in, runtime admission, operating-system confinement and account
6
6
  custody. Textbutler owns contact context, response policy and every message send.
7
7
  Textbutler is an MIT-licensed reference application for this separation.
@@ -36,8 +36,9 @@ bun run textbutler setup \
36
36
  --xcb-model FULL_MODEL_KEY
37
37
  ```
38
38
 
39
- Repeat setup with `--xcb-account codex:ACCOUNT_ID` and its full model key to add
40
- a Codex account. Setup records the xcb executable's SHA-256 and the explicit
39
+ Repeat setup with `--xcb-account codex:ACCOUNT_ID` or `--xcb-account devin:ACCOUNT_ID`
40
+ and the matching full model key to add a Codex or Devin account; one account per
41
+ provider. Setup records the xcb executable's SHA-256 and the explicit
41
42
  account/model binding. It does not copy subscription credentials, create a
42
43
  provider sign-in or enable a contact. Restart the installed daemon, run `providers list`,
43
44
  and use the returned Textbutler account ID with `providers check ACCOUNT_ID`.
@@ -23,14 +23,14 @@ remain visible in setup and must be resolved before that claim is made.
23
23
 
24
24
  ## Interface direction
25
25
 
26
- XCB is a useful interaction reference: a clear status view, filtered pickers,
26
+ xcb is a useful interaction reference: a clear status view, filtered pickers,
27
27
  contextual choices, complete review and clean cancellation. Textbutler follows
28
28
  that separation with a thin terminal client over its owner control protocol.
29
29
  All permission, account, contact, grant and dispatch checks remain in the daemon.
30
30
 
31
31
  The native menu already uses the shared Rust desktop foundation. A new Rust
32
32
  runtime is not required to make these controls usable. If the terminal grows
33
- into a full-screen workspace, XCB's Ratatui/Crossterm interface is an appropriate
33
+ into a full-screen workspace, xcb's Ratatui/Crossterm interface is an appropriate
34
34
  reference. The subscription connection uses xcb's dedicated zero-tool `generate`
35
35
  contract. It does not use the workspace coding command or inherit its tools and
36
36
  sessions.
@@ -41,7 +41,7 @@ The verified bundle connects to an explicitly selected xcb installation after
41
41
  its build checks reviewed composition evidence against current source bytes and
42
42
  both contact profiles. A source daemon has no embedded admission and keeps
43
43
  subscription inference unavailable. xcb handles
44
- Claude Code or Codex subscription authentication, confinement and provider
44
+ Claude Code, Codex, or Devin subscription authentication, confinement and provider
45
45
  custody. Textbutler uses zero-tool generation, parses one operation proposal at
46
46
  a time and applies its contact-scoped broker policy before any effect.
47
47
 
@@ -8,7 +8,7 @@ credentials, synchronization and send implementation. Textbutler never runs
8
8
  ```mermaid
9
9
  flowchart LR
10
10
  App[Textbutler menu companion] --> Butler[Textbutler daemon]
11
- Butler --> Agents[Agentrouter]
11
+ Butler --> Xcb[xcb]
12
12
  Butler --> Ghostget[Ghostget owner process]
13
13
  Ghostget --> Messages[iMessage helper]
14
14
  Ghostget --> WhatsApp[Pinned wacli linked device]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hraness/message-like-me",
3
- "version": "0.8.20",
3
+ "version": "0.8.22",
4
4
  "description": "A local-first CLI and Agent Skill for studying private messaging history and drafting messages that sound like you.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -94,15 +94,17 @@
94
94
  "devDependencies": {
95
95
  "@anthropic-ai/claude-agent-sdk": "0.3.268",
96
96
  "@anthropic-ai/sdk": "0.125.0",
97
- "@hraness/agentmixer": "https://github.com/hraness/agentmixer/releases/download/v0.1.1/hraness-agentmixer-0.1.1.tgz",
98
- "@hraness/algal": "github:hraness/algal#c5bd50452a676dc0b035ef206178c397de0cba92",
99
- "@hraness/desktop-foundation": "https://github.com/hraness/desktop-foundation/releases/download/v0.7.0/hraness-desktop-foundation-0.7.0.tgz",
97
+ "@hraness/agentmixer": "https://github.com/hraness/xcb/releases/download/v0.3.0/hraness-agentmixer-0.3.0.tgz",
98
+ "@hraness/algal": "github:hraness/algal#ac68f096d2e10e1824b9ee4d6fe031b4846094da",
99
+ "@hraness/desktop-foundation": "https://github.com/hraness/desktop-foundation/releases/download/v0.8.0/hraness-desktop-foundation-0.8.0.tgz",
100
100
  "@hraness/local-custody": "github:hraness/local-custody#v0.4.0",
101
- "@hraness/support-foundation": "github:hraness/support-foundation#2d034b357680353574411217d68b02b6755b07ed",
101
+ "@hraness/support-foundation": "github:hraness/support-foundation#8bb514d24b79dc3f305390700ae312cab88e7ad2",
102
+ "@jitl/quickjs-singlefile-browser-release-sync": "0.32.0",
102
103
  "@modelcontextprotocol/sdk": "1.30.0",
103
104
  "@types/bun": "1.3.14",
104
105
  "effect": "3.22.1",
105
106
  "fast-check": "4.9.0",
107
+ "quickjs-emscripten-core": "0.32.0",
106
108
  "sigstore": "4.1.1",
107
109
  "typescript": "6.0.3",
108
110
  "zod": "4.6.2"