synomem 0.1.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 (130) hide show
  1. package/AGENTS.md +42 -0
  2. package/ARCHITECTURE.md +126 -0
  3. package/CHANGELOG.md +35 -0
  4. package/CODE_OF_CONDUCT.md +29 -0
  5. package/CONTRIBUTING.md +48 -0
  6. package/LICENSE +21 -0
  7. package/README.md +247 -0
  8. package/SECURITY.md +117 -0
  9. package/dist/backend.d.ts +9 -0
  10. package/dist/backend.d.ts.map +1 -0
  11. package/dist/backend.js +60 -0
  12. package/dist/backend.js.map +1 -0
  13. package/dist/cli.d.ts +34 -0
  14. package/dist/cli.d.ts.map +1 -0
  15. package/dist/cli.js +1040 -0
  16. package/dist/cli.js.map +1 -0
  17. package/dist/client.d.ts +168 -0
  18. package/dist/client.d.ts.map +1 -0
  19. package/dist/client.js +1031 -0
  20. package/dist/client.js.map +1 -0
  21. package/dist/config.d.ts +33 -0
  22. package/dist/config.d.ts.map +1 -0
  23. package/dist/config.js +153 -0
  24. package/dist/config.js.map +1 -0
  25. package/dist/credentials.d.ts +36 -0
  26. package/dist/credentials.d.ts.map +1 -0
  27. package/dist/credentials.js +127 -0
  28. package/dist/credentials.js.map +1 -0
  29. package/dist/errors.d.ts +9 -0
  30. package/dist/errors.d.ts.map +1 -0
  31. package/dist/errors.js +60 -0
  32. package/dist/errors.js.map +1 -0
  33. package/dist/fs-utils.d.ts +7 -0
  34. package/dist/fs-utils.d.ts.map +1 -0
  35. package/dist/fs-utils.js +68 -0
  36. package/dist/fs-utils.js.map +1 -0
  37. package/dist/import.d.ts +655 -0
  38. package/dist/import.d.ts.map +1 -0
  39. package/dist/import.js +226 -0
  40. package/dist/import.js.map +1 -0
  41. package/dist/index.d.ts +20 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +11 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/mcp/index.d.ts +14 -0
  46. package/dist/mcp/index.d.ts.map +1 -0
  47. package/dist/mcp/index.js +698 -0
  48. package/dist/mcp/index.js.map +1 -0
  49. package/dist/mcp-server.d.ts +3 -0
  50. package/dist/mcp-server.d.ts.map +1 -0
  51. package/dist/mcp-server.js +45 -0
  52. package/dist/mcp-server.js.map +1 -0
  53. package/dist/oauth.d.ts +27 -0
  54. package/dist/oauth.d.ts.map +1 -0
  55. package/dist/oauth.js +201 -0
  56. package/dist/oauth.js.map +1 -0
  57. package/dist/ports/projections.d.ts +6 -0
  58. package/dist/ports/projections.d.ts.map +1 -0
  59. package/dist/ports/projections.js +2 -0
  60. package/dist/ports/projections.js.map +1 -0
  61. package/dist/ports/repository.d.ts +31 -0
  62. package/dist/ports/repository.d.ts.map +1 -0
  63. package/dist/ports/repository.js +2 -0
  64. package/dist/ports/repository.js.map +1 -0
  65. package/dist/projections.d.ts +24 -0
  66. package/dist/projections.d.ts.map +1 -0
  67. package/dist/projections.js +531 -0
  68. package/dist/projections.js.map +1 -0
  69. package/dist/remote.d.ts +120 -0
  70. package/dist/remote.d.ts.map +1 -0
  71. package/dist/remote.js +286 -0
  72. package/dist/remote.js.map +1 -0
  73. package/dist/schemas.d.ts +901 -0
  74. package/dist/schemas.d.ts.map +1 -0
  75. package/dist/schemas.js +424 -0
  76. package/dist/schemas.js.map +1 -0
  77. package/dist/service.d.ts +126 -0
  78. package/dist/service.d.ts.map +1 -0
  79. package/dist/service.js +2 -0
  80. package/dist/service.js.map +1 -0
  81. package/dist/skill-install.d.ts +34 -0
  82. package/dist/skill-install.d.ts.map +1 -0
  83. package/dist/skill-install.js +256 -0
  84. package/dist/skill-install.js.map +1 -0
  85. package/dist/storage.d.ts +94 -0
  86. package/dist/storage.d.ts.map +1 -0
  87. package/dist/storage.js +1229 -0
  88. package/dist/storage.js.map +1 -0
  89. package/dist/types.d.ts +442 -0
  90. package/dist/types.d.ts.map +1 -0
  91. package/dist/types.js +2 -0
  92. package/dist/types.js.map +1 -0
  93. package/dist/version.d.ts +3 -0
  94. package/dist/version.d.ts.map +1 -0
  95. package/dist/version.js +14 -0
  96. package/dist/version.js.map +1 -0
  97. package/docs/cli.md +180 -0
  98. package/docs/examples.md +70 -0
  99. package/docs/mcp.md +96 -0
  100. package/docs/recovery.md +45 -0
  101. package/docs/releasing.md +61 -0
  102. package/docs/skill.md +93 -0
  103. package/docs/storage-format.md +83 -0
  104. package/openapi/synomem-v1.yaml +674 -0
  105. package/package.json +100 -0
  106. package/skills/synomem/SKILL.md +71 -0
  107. package/skills/synomem/agents/openai.yaml +8 -0
  108. package/skills/synomem/references/examples.md +28 -0
  109. package/src/backend.ts +91 -0
  110. package/src/cli.ts +1623 -0
  111. package/src/client.ts +1261 -0
  112. package/src/config.ts +170 -0
  113. package/src/credentials.ts +194 -0
  114. package/src/errors.ts +64 -0
  115. package/src/fs-utils.ts +85 -0
  116. package/src/import.ts +284 -0
  117. package/src/index.ts +61 -0
  118. package/src/mcp/index.ts +973 -0
  119. package/src/mcp-server.ts +46 -0
  120. package/src/oauth.ts +252 -0
  121. package/src/ports/projections.ts +6 -0
  122. package/src/ports/repository.ts +67 -0
  123. package/src/projections.ts +624 -0
  124. package/src/remote.ts +516 -0
  125. package/src/schemas.ts +457 -0
  126. package/src/service.ts +140 -0
  127. package/src/skill-install.ts +332 -0
  128. package/src/storage.ts +1603 -0
  129. package/src/types.ts +458 -0
  130. package/src/version.ts +16 -0
package/AGENTS.md ADDED
@@ -0,0 +1,42 @@
1
+ # AGENTS.md
2
+
3
+ This repository is a public TypeScript package. Changes should be reviewable, portable, secure by default, and appropriate for an OSS audience.
4
+
5
+ ## Working agreement
6
+
7
+ - Read `ARCHITECTURE.md`, `SECURITY.md`, and the local `.docs/plan.md` when present before architectural changes.
8
+ - Use Node.js 22.13 or newer, ESM, strict TypeScript, and the built-in `node:sqlite` API.
9
+ - Keep V1 single-machine and local-first. Do not add hosted services, telemetry, accounts, network listeners, or postinstall behavior.
10
+ - Do not publish packages, create releases, alter npm configuration, or write into a user’s real `~/.agents` directory without explicit authorization.
11
+ - Tests and demos must use isolated temporary homes.
12
+ - Never commit real Synomem data, SQLite databases, environment files, secrets, generated coverage, or npm tarballs.
13
+
14
+ ## Architectural invariants
15
+
16
+ - SQLite event rows are canonical and append-only. State changes are new events.
17
+ - Agent IDs are validated stable identities; aliases never silently merge identities.
18
+ - MCP writes use the actor bound at server startup. Tool arguments cannot override it.
19
+ - `WINS.md`, inbox files, and `profile.json` are generated projections. `NOTES.md` is human-owned and must never be overwritten.
20
+ - Machine reads stay context-bounded: compact list/change feeds have conservative defaults, hard limits, byte budgets, and opaque cursors. `WINS.md` is not a machine query source.
21
+ - Projection cleanup may remove only regular files listed in the generated-files manifest.
22
+ - Normal mutations must not rebuild or rewrite every pending inbox entry; full regeneration belongs to the explicit rebuild operation.
23
+ - `system` actors are automation identities and have no implicit agent or administrative authority.
24
+ - Raw JSON/JSONL export must remain available when canonical rows are unsupported or malformed; writes must fail closed across unknown event semantics.
25
+ - Do not follow symlinks outside the configured home.
26
+ - Evidence is descriptive metadata, never captured tool output or secret material.
27
+ - No filesystem work occurs at module import time, and library code never calls `process.exit()`.
28
+
29
+ ## Quality gates
30
+
31
+ Run these before handing work off:
32
+
33
+ ```bash
34
+ npm run format:check
35
+ npm run lint
36
+ npm run typecheck
37
+ npm test
38
+ npm run test:coverage
39
+ npm run pack:check
40
+ ```
41
+
42
+ Update documentation and `CHANGELOG.md` when behavior, commands, policy, storage, or public types change. Add tests for security boundaries and observable behavior, not merely implementation details.
@@ -0,0 +1,126 @@
1
+ # Architecture
2
+
3
+ Synomem is one ESM package with four adapters over a shared asynchronous domain-service port:
4
+
5
+ ```text
6
+ TypeScript library ─┐ ┌─> SynomemClient ─> SynomemStorage ─> SQLite events
7
+ CLI ─┼─> configured factory ──┤ ├─> indexes
8
+ stdio MCP ─┘ └─> RemoteSynomemService ─> HTTPS API └─> files
9
+ ```
10
+
11
+ A single package keeps validation, policy, migrations, types, CLI behavior, and MCP behavior
12
+ consistent. Public operations are asynchronous. CLI and MCP receive the service through an
13
+ injectable factory and do not reach into concrete storage or projection objects. SQLite remains
14
+ behind the local service so a later hosted transport can preserve domain semantics without exposing
15
+ database APIs remotely.
16
+
17
+ ## Domain model
18
+
19
+ One workspace contains stable agent identities and four record aggregates:
20
+
21
+ - Kudos: given, acknowledged, or revoked recognition.
22
+ - Memos: sent, read, or archived one-to-one messages, including self-memos.
23
+ - Notes: owner-scoped knowledge with optimistic revisions and archive state.
24
+ - Todos: assigned actions with updates, completion, reopening, and cancellation.
25
+
26
+ Every mutation appends a versioned event with a workspace ID, aggregate ID, aggregate version,
27
+ actor, timestamp, optional actor-scoped idempotency key, source, and metadata. The store assigns a
28
+ monotonic ingestion sequence inside the write transaction. Historical rows are never updated or
29
+ deleted to represent state changes.
30
+
31
+ SQLite schema version 3 adds the generalized event envelope and `items_current`. Existing kudos
32
+ events remain valid through deterministic legacy normalization. Unsupported or malformed semantics
33
+ make writes and rebuilds fail closed while raw JSON and JSONL export remains available.
34
+
35
+ ## Query models
36
+
37
+ `events` is canonical. `agents`, `aliases`, `kudos_current`, and `items_current` are transactional,
38
+ rebuildable query indexes. `items_current` stores only bounded summary fields and participant IDs;
39
+ full bodies, reasons, evidence, descriptions, source data, and metadata stay in canonical events.
40
+
41
+ List reads default to 10 records and allow at most 50. Change reads default to 20 and allow at most 100. Both use opaque sequence cursors and an approximate 24 KiB item-data budget. Detail reads
42
+ reconstruct one requested aggregate. Generated Markdown is never a machine query source.
43
+
44
+ ## Authorization
45
+
46
+ MCP servers bind one actor at startup, and tool inputs cannot override it. Humans have local
47
+ administrative authority. Agents can manage their own notes, recipient memo state, and todos they
48
+ created or received. System actors have no implicit agent or administrator authority. Actor
49
+ principals are keyed by both kind and ID; matching text IDs across kinds do not share author access.
50
+
51
+ Delivery and ownership are distinct from visibility. Direct participants can access their record;
52
+ `workspace` grants other workspace actors access; `public` makes a record eligible for public export.
53
+ The filesystem owner remains the ultimate local authority.
54
+
55
+ ## Concurrency and durability
56
+
57
+ SQLite uses WAL, foreign keys, `synchronous=FULL`, a bounded busy handler, and `BEGIN IMMEDIATE`
58
+ transactions. Actor-scoped idempotency protects retries. Note and todo revisions use aggregate
59
+ versions so stale writes fail with `REVISION_CONFLICT` rather than overwriting concurrent state.
60
+
61
+ V1 supports one machine and one filesystem owner. A future hosted service must enforce the same
62
+ policies server-side and add authentication, tenant isolation, transport security, conflict handling,
63
+ availability, and explicit data migration.
64
+
65
+ ## Projections
66
+
67
+ Normal mutations synchronize only affected agents. `rebuild` recreates all derived indexes and
68
+ files. `WINS.md`, `MEMORY.md`, `TODOS.md`, inbox entries, and `profile.json` are generated.
69
+ `NOTES.md` is human-owned and never overwritten or added to the generated-files manifest.
70
+
71
+ Cleanup removes only manifest-listed regular files beneath the configured home and never follows
72
+ symlinks. Projection timestamps derive from canonical event time for deterministic rebuilds.
73
+
74
+ ## Module boundaries
75
+
76
+ - `src/types.ts`: public types and event contracts.
77
+ - `src/schemas.ts`: runtime validation and payload limits.
78
+ - `src/storage.ts`: SQLite ownership, migrations, indexes, transactions, backups, and raw recovery.
79
+ - `src/client.ts`: public domain API, policy, lifecycle, and aggregate reconstruction.
80
+ - `src/service.ts`: transport-neutral asynchronous service, capability, and factory contracts.
81
+ - `src/ports/`: repository and projection contracts injected into the authoritative core.
82
+ - `src/import.ts`: consistent local snapshot, bounded canonical bundle, and remote import client.
83
+ - `src/oauth.ts` and `src/credentials.ts`: PKCE login/refresh and OS credential-store boundary.
84
+ - `src/projections.ts`: deterministic safe filesystem views.
85
+ - `src/cli.ts`: command parsing, human/JSON output, and stable exit codes.
86
+ - `src/mcp/index.ts`: actor binding, tools, resources, prompts, and visibility enforcement.
87
+ - `src/skill-install.ts`: explicit constrained skill placement.
88
+
89
+ ## Future boundary
90
+
91
+ `SynomemCore` receives repository and projection ports; `SynomemClient` composes it with the local
92
+ SQLite and filesystem implementations and retains local administration. The current storage class
93
+ is not a public API contract. Adapters use explicit service capabilities and administrative methods
94
+ instead of accessing it. A hosted implementation should expose domain operations through an
95
+ authenticated service, not connect clients directly to a remote database or synchronize SQLite
96
+ files.
97
+
98
+ Repository operations are async-capable even though SQLite executes its statements synchronously.
99
+ The local adapter serializes asynchronous domain transactions on each connection and keeps a
100
+ separate synchronous transaction primitive for migrations and local projection maintenance. This
101
+ lets a remote implementation hold a transaction across awaited driver calls without changing
102
+ domain behavior or allowing overlapping transactions on one SQLite connection.
103
+
104
+ `RemoteSynomemService` is the client-side implementation of the same service contract. It calls the
105
+ versioned domain API described by `openapi/synomem-v1.yaml`, sends credentials only in the
106
+ authorization header, moves retry keys to `Idempotency-Key`, and never sends actor identity as
107
+ authority. It does not connect to Postgres or create local projections.
108
+
109
+ Configuration schema version 3 makes backend selection explicit. Existing schema version 2 files
110
+ migrate to `{ "kind": "local" }`; remote selection records only the service origin and workspace
111
+ identifier. Credentials are never stored in `config.json`. `SynomemClient` remains intentionally
112
+ local-only and refuses a remote backend before creating or opening SQLite; adapter factories are
113
+ responsible for selecting `RemoteSynomemService`. The CLI and stdio MCP use that configured factory
114
+ by default, so remote mode performs no SQLite or filesystem projection writes.
115
+
116
+ Remote credentials are indexed by service origin, workspace, and stable `(kind,id)` actor identity;
117
+ display-name changes do not orphan them. The environment token takes precedence without
118
+ persistence. Interactive authorization uses protected-resource and authorization-server discovery,
119
+ PKCE S256, a fixed registered loopback callback, and OS credential storage. Refresh tokens never
120
+ enter Synomem configuration or events.
121
+
122
+ Local-to-remote import is deliberately not synchronization. The client creates a consistent,
123
+ checksummed SQLite snapshot bundle, previews it against an explicit destination, and submits it only
124
+ after confirmation. The remote service owns authorization, plan signing, empty-target enforcement,
125
+ validation, and transactional ingestion. The local source and backend configuration remain
126
+ unchanged.
package/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ All notable changes will be documented here. The format follows
4
+ [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and releases follow Semantic Versioning.
5
+
6
+ ## [Unreleased]
7
+
8
+ ## [0.1.0] - 2026-09-04
9
+
10
+ ### Added
11
+
12
+ - Four distinct event-sourced domains: kudos, one-recipient memos, owner-private notes, and todos.
13
+ - Consent-based cross-agent todo assignment with explicit acceptance and rejection.
14
+ - Unified, context-bounded item and change feeds with opaque sequence watermarks.
15
+ - Persistent workspace and agent identities, actor-scoped idempotency, and optimistic revisions.
16
+ - Local-first SQLite storage with append-only canonical events and rebuildable projections.
17
+ - TypeScript library, `synomem` CLI, actor-bound `synomem-mcp` stdio server, and portable agent skill.
18
+ - Explicit local and remote backend configuration through a shared asynchronous domain-service
19
+ boundary.
20
+ - OAuth authorization-code PKCE, OS credential storage, and an HTTPS remote service client.
21
+ - Previewed, checksummed local-to-remote import without implicit synchronization.
22
+ - Public OpenAPI contract for independently operated hosted services.
23
+
24
+ ### Security
25
+
26
+ - MCP mutations cannot override the actor bound at server startup.
27
+ - Notes remain owner-private, and direct-record authorization distinguishes actor kind and ID.
28
+ - Machine-facing reads enforce hard item limits, byte budgets, and opaque cursors.
29
+ - Unknown canonical semantics fail writes closed while raw JSON and JSONL recovery remain available.
30
+ - Remote credentials remain outside configuration, events, command arguments, and normal output.
31
+ - Skill installation is explicit, constrained to supported runtime directories, and dry-run by
32
+ default.
33
+
34
+ [Unreleased]: https://github.com/Coaden/synomem/compare/v0.1.0...HEAD
35
+ [0.1.0]: https://github.com/Coaden/synomem/releases/tag/v0.1.0
@@ -0,0 +1,29 @@
1
+ # Code of Conduct
2
+
3
+ ## Our standard
4
+
5
+ Synomem is committed to a welcoming, respectful, and harassment-free community. We value technical rigor, curiosity, kindness, clear feedback, and recognition grounded in real contributions.
6
+
7
+ Examples of positive behavior include:
8
+
9
+ - showing empathy and respect for different experiences and viewpoints;
10
+ - giving and accepting constructive technical feedback;
11
+ - focusing criticism on ideas and code rather than people;
12
+ - acknowledging contributions accurately;
13
+ - taking responsibility, apologizing, and repairing harm.
14
+
15
+ Unacceptable behavior includes harassment, discrimination, threats, sexualized attention, personal attacks, deliberate intimidation, doxxing, publishing private information, sustained disruption, or retaliation against someone who reports a concern.
16
+
17
+ ## Scope
18
+
19
+ This policy applies in project spaces and when someone publicly represents the project, including repositories, issues, pull requests, discussions, community events, and project-related private communication.
20
+
21
+ ## Enforcement
22
+
23
+ Report conduct concerns privately to the repository maintainers through GitHub. Maintainers will review reports promptly, protect reporter privacy as practical, and respond proportionally. Possible actions include a private correction, warning, temporary restriction, removal of content, or permanent exclusion from project spaces.
24
+
25
+ Maintainers must disclose conflicts of interest and recuse themselves when appropriate. Good-faith reports will not result in retaliation.
26
+
27
+ ## Attribution
28
+
29
+ This policy is inspired by the Contributor Covenant and common open-source community standards. It may be refined as the community grows.
@@ -0,0 +1,48 @@
1
+ # Contributing to Synomem
2
+
3
+ Thank you for helping make durable agent coordination more useful—and slightly more robotic.
4
+
5
+ ## Before opening a change
6
+
7
+ For substantial features, open an issue first so scope and storage compatibility can be discussed. Security reports belong in GitHub private vulnerability reporting, not public issues.
8
+
9
+ By participating, you agree to follow the [Code of Conduct](CODE_OF_CONDUCT.md).
10
+
11
+ ## Development setup
12
+
13
+ ```bash
14
+ git clone https://github.com/Coaden/synomem.git
15
+ cd synomem
16
+ npm install
17
+ npm test
18
+ ```
19
+
20
+ Node.js 22.13 or newer is required. The project uses ESM, strict TypeScript, Node’s built-in SQLite module, Vitest, ESLint, and Prettier.
21
+
22
+ ## Pull requests
23
+
24
+ 1. Create a focused branch from `main`.
25
+ 2. Add or update tests for observable behavior and security boundaries.
26
+ 3. Update documentation and `CHANGELOG.md` when public behavior changes.
27
+ 4. Run every quality gate:
28
+
29
+ ```bash
30
+ npm run format:check
31
+ npm run lint
32
+ npm run typecheck
33
+ npm test
34
+ npm run test:coverage
35
+ npm run pack:check
36
+ ```
37
+
38
+ 5. Explain the motivation, implementation, tests, and storage or security impact in the pull request.
39
+
40
+ Keep commits reviewable. Do not commit real Synomem homes, databases, secrets, build output, coverage, or tarballs.
41
+
42
+ ## Design expectations
43
+
44
+ Preserve the invariants in [AGENTS.md](AGENTS.md) and [ARCHITECTURE.md](ARCHITECTURE.md). New event types require validation, migration consideration, query/projection behavior, protocol tests, documentation, and export coverage.
45
+
46
+ ## Releases
47
+
48
+ Maintainers follow [docs/releasing.md](docs/releasing.md). Ordinary CI never publishes packages. Publishing requires an intentional GitHub Release and an npm trusted-publisher relationship.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Troy Locke
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,247 @@
1
+ <div align="center">
2
+
3
+ # Synomem
4
+
5
+ ### Shared Memory for Agents
6
+
7
+ **Local-first · Multi-agent · Auditable · No account required**
8
+
9
+ [![CI](https://github.com/Coaden/synomem/actions/workflows/ci.yml/badge.svg)](https://github.com/Coaden/synomem/actions/workflows/ci.yml)
10
+ [![npm](https://img.shields.io/npm/v/synomem.svg)](https://www.npmjs.com/package/synomem)
11
+ [![Node.js 22.13+](https://img.shields.io/badge/Node.js-22.13%2B-339933?logo=node.js&logoColor=white)](https://nodejs.org/)
12
+ [![MCP](https://img.shields.io/badge/MCP-stdio-6f42c1)](https://modelcontextprotocol.io/)
13
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
14
+
15
+ [CLI reference](docs/cli.md) · [MCP guide](docs/mcp.md) · [Storage](docs/storage-format.md) · [Security](SECURITY.md)
16
+
17
+ The experimental remote client supports explicit backend configuration. `synomem backend use remote
18
+ --url <https-origin> --workspace <id>` makes the CLI and stdio MCP use the versioned domain API with
19
+ actor-scoped OAuth credentials; it does not synchronize local history or create a shadow SQLite
20
+ database. Hosted API and HTTP-MCP implementations are separate products and are not included here.
21
+ See the [CLI reference](docs/cli.md#backend-and-authentication).
22
+
23
+ </div>
24
+
25
+ Synomem gives humans and AI agents four durable ways to coordinate beyond a disappearing chat:
26
+
27
+ - **Kudos** recognize a concrete contribution.
28
+ - **Memos** deliver a message to another agent or to one's future self.
29
+ - **Notes** retain agent-owned, revisable knowledge.
30
+ - **Todos** track assigned actions with optional date-only or timezone-aware deadlines.
31
+
32
+ ## Core philosophy
33
+
34
+ Traditional AI memory layers resemble an isolated file cabinet for one model. Synomem turns memory
35
+ into a shared, transactional canvas: independently operating agents can retain private knowledge,
36
+ deliver durable context, delegate work with consent, track commitments, and recognize good
37
+ collaboration through one auditable protocol. V1 provides that substrate locally; its interfaces are
38
+ designed so the same agent identities and semantics can later cross machines through an explicitly
39
+ configured service.
40
+
41
+ One append-only SQLite event store powers the TypeScript library, `synomem` CLI, actor-bound stdio
42
+ MCP server, compact change feeds, and readable Markdown projections. V1 runs entirely on one machine
43
+ and opens no network listener.
44
+
45
+ > [!IMPORTANT]
46
+ > The renamed `synomem` package has not been published yet. It is pre-1.0 software, so review the
47
+ > release notes and rename guidance before upgrading persisted storage or public API consumers.
48
+
49
+ ## Quick start
50
+
51
+ ```bash
52
+ npm install --global synomem
53
+
54
+ export SYNOMEM_HOME="$(mktemp -d)/.agents"
55
+ synomem init
56
+ synomem agent create codex --name "Codex"
57
+ synomem agent create gracie --name "Gracie"
58
+
59
+ synomem kudos give codex \
60
+ --from gracie --actor-kind agent \
61
+ --title "Caught a continuity contradiction" \
62
+ --reason "Found conflicting requirements before implementation."
63
+
64
+ synomem memo send codex \
65
+ --from gracie --subject "Review follow-up" \
66
+ --body "Please recheck the migration after the tests pass."
67
+
68
+ synomem note create --as gracie \
69
+ --title "Release invariant" \
70
+ --body "Never publish without explicit maintainer authorization."
71
+
72
+ synomem todo create codex \
73
+ --from gracie --title "Review the migration" --due-date 2026-09-15
74
+
75
+ synomem inbox codex
76
+ synomem todo accept <todo-id> --as codex
77
+ synomem list
78
+ ```
79
+
80
+ Tests and demos always use temporary homes and never modify an existing configured home.
81
+
82
+ ## Let your agent set it up
83
+
84
+ Paste this prompt into Claude Code, Codex, Hermes, OpenClaw, Cursor, local Grok Build, or another
85
+ terminal-capable agent. The Synomem package contains the portable
86
+ [`skills/synomem`](https://github.com/Coaden/synomem/tree/main/skills/synomem) skill and a guarded
87
+ installer for the six named local harnesses.
88
+
89
+ ```text
90
+ Set up Synomem for this agent and runtime. Synomem is a local-first coordination system for durable kudos, one-to-one memos, private agent notes, and consent-based assigned todos. It uses an append-only SQLite database under ~/.agents by default, an actor-bound stdio MCP server, and a portable Agent Skill. Multiple local agents may share the database, but every MCP server must be bound to its own stable identity.
91
+
92
+ Work autonomously through the safe, reversible steps below. Do not expose secrets, overwrite unrelated configuration, invent an identity, use --force without my explicit approval, or modify another agent's integration.
93
+
94
+ 1. Verify Node.js 22.13+ and npm are available. Install or update the public package with `npm install --global synomem` if needed, then report `synomem --version`.
95
+ 2. Preserve an existing `SYNOMEM_HOME`; otherwise use the default ~/.agents. Run `synomem init`, then `synomem doctor`. Never point tests or experiments at another Synomem home.
96
+ 3. Run `synomem agent list`. Determine this agent's existing stable ID from the current harness or Synomem configuration and reuse it. If no identity is clearly established, ask me for the agent ID and display name before running `synomem agent create <id> --name <name>`. Never silently merge or rename identities.
97
+ 4. Detect the current harness from actual local evidence and its installed CLI help. Use runtime `claude` for Claude Code, `codex` for Codex, `hermes` for Hermes, `openclaw` for OpenClaw, `cursor` for Cursor, or `grok` for local Grok Build (`grokbot` is accepted as an alias). Check `synomem skill install --help`, then preview with `synomem skill install --runtime <runtime> --actor-id <agent-id> --actor-name <display-name>`. Review the exact destination and apply the same command with `--yes`; it must report `current`. If the installed release does not yet list this runtime, locate the packaged source under the global npm root at `synomem/skills/synomem` and follow the verified destination and conflict rules in https://github.com/Coaden/synomem/blob/main/docs/skill.md instead. Do not guess a path, overwrite an existing skill, or create a fake harness home to make an unavailable runtime appear installed.
98
+ 5. Inspect any actor-bound MCP registration command printed by the installer. Check the harness's existing MCP list/config first, then run the command only if `synomem` is absent or incorrect. Do not create duplicates. Cursor has no noninteractive MCP-add command: carefully merge a `synomem` stdio entry into its documented user `~/.cursor/mcp.json`, using command `synomem-mcp` and arguments `--actor-id <agent-id> --actor-kind agent --actor-name <display-name>`; preserve every existing entry.
99
+ 6. Verify the harness can discover the installed skill and MCP server using its own list/status commands, then run `synomem doctor`. Start a new agent session if that harness does not live-reload a newly created skills directory.
100
+ 7. If this is hosted Grok Bot rather than local Grok Build, do not claim it shares the desktop's local SQLite database. Install the package and skill only inside a persistent terminal environment where `npm`, local stdio MCP, and ~/.grok are actually available. Otherwise provide the skill URL https://github.com/Coaden/synomem/blob/main/skills/synomem/SKILL.md and explain the unsupported boundary; do not expose the local database through a tunnel.
101
+ 8. Report the package version, stable actor ID, storage home, installed skill path, MCP registration and verification status, whether a new session is needed, and every file or configuration changed. Do not print record contents or environment values beyond the non-secret actor identity and home path.
102
+ ```
103
+
104
+ ## TypeScript API
105
+
106
+ ```ts
107
+ import { SynomemClient } from 'synomem';
108
+
109
+ const client = new SynomemClient({
110
+ actor: { kind: 'agent', id: 'gracie', displayName: 'Gracie' },
111
+ });
112
+
113
+ await client.init();
114
+
115
+ await client.memos.send({
116
+ recipientAgentId: 'codex',
117
+ subject: 'Review follow-up',
118
+ body: 'Please recheck the migration after the tests pass.',
119
+ idempotencyKey: 'gracie-codex-migration-follow-up',
120
+ });
121
+
122
+ const note = await client.notes.create({
123
+ title: 'Release invariant',
124
+ body: 'Never publish without explicit maintainer authorization.',
125
+ });
126
+
127
+ await client.notes.revise({
128
+ noteId: note.record.event.id,
129
+ expectedVersion: note.record.current.version,
130
+ body: 'Never publish or create a release without explicit maintainer authorization.',
131
+ });
132
+
133
+ await client.todos.create({
134
+ assigneeAgentId: 'codex',
135
+ title: 'Review the migration',
136
+ due: { kind: 'date', date: '2026-09-15' },
137
+ });
138
+
139
+ const page = await client.items.list({ kinds: ['memo', 'todo'], limit: 10 });
140
+ const changes = await client.items.changes({ after: page.watermark });
141
+
142
+ await client.close();
143
+ ```
144
+
145
+ The library performs no filesystem work at import time and never terminates its host process.
146
+
147
+ ## Context-safe reads
148
+
149
+ `client.items.list()` and MCP `synomem_list` return 10 compact summaries by default and at most 50.
150
+ Summaries omit message bodies, kudos reasons and evidence, note bodies, todo descriptions, source,
151
+ and metadata. Fetch one authorized detail record with `items.get(id)` or `synomem_get`.
152
+
153
+ Incremental reads return at most 20 changes by default and 100 at most. List and change responses
154
+ also stop around a 24 KiB item-data budget and return opaque continuation cursors. Agents should save
155
+ watermarks and must not drain historical pages speculatively.
156
+
157
+ ## MCP
158
+
159
+ Every runtime launches the same stdio server with its own fixed actor identity while sharing one
160
+ local home:
161
+
162
+ ```bash
163
+ codex mcp add synomem \
164
+ --env SYNOMEM_ACTOR_ID=codex \
165
+ --env SYNOMEM_ACTOR_KIND=agent \
166
+ --env SYNOMEM_ACTOR_NAME=Codex \
167
+ -- synomem-mcp
168
+ ```
169
+
170
+ MCP tool arguments cannot override the bound actor. Purpose-specific write tools enforce ownership
171
+ and lifecycle rules; `synomem_list`, `synomem_get`, `synomem_changes`, and `synomem_inbox` provide
172
+ bounded reads. See [the MCP guide](docs/mcp.md).
173
+
174
+ ## Agent skill
175
+
176
+ The package includes [`skills/synomem`](skills/synomem). Installation is explicit and dry-run first:
177
+
178
+ ```bash
179
+ synomem skill install --runtime codex --actor-id codex --actor-name "Codex"
180
+ synomem skill install --runtime codex --actor-id codex --actor-name "Codex" --yes
181
+ synomem skill install --runtime hermes --actor-id mycroft --actor-name "Mycroft" --yes
182
+ synomem skill status
183
+ ```
184
+
185
+ No postinstall hook changes an agent runtime. The installer never creates a missing runtime home and
186
+ refuses unowned conflicts unless `--force` is explicitly supplied. Supported local runtime names
187
+ are `claude`, `codex`, `hermes`, `openclaw`, `cursor`, and `grok`; `grokbot` aliases `grok`.
188
+
189
+ ## Storage
190
+
191
+ ```text
192
+ ~/.agents/
193
+ ├── synomem/
194
+ │ ├── config.json
195
+ │ └── synomem.sqlite3
196
+ └── <agent-id>/
197
+ ├── profile.json
198
+ ├── WINS.md
199
+ ├── MEMORY.md
200
+ ├── TODOS.md
201
+ ├── inbox/{kudos,memos,todos}/
202
+ └── NOTES.md
203
+ ```
204
+
205
+ SQLite events are canonical and append-only. Markdown and current-state tables are rebuildable
206
+ projections. `NOTES.md` is human-owned and is never overwritten; canonical agent notes project to
207
+ `MEMORY.md`.
208
+
209
+ Override the root with `SYNOMEM_HOME`, `--home`, or the library's `home` option. Use
210
+ `synomem backup` for a consistent snapshot and JSON or JSONL export for recovery. Never synchronize
211
+ the live database with Git, Dropbox, a network share, or a file-copy tool.
212
+
213
+ ## Trust and privacy
214
+
215
+ Synomem is audit-friendly, not tamper-proof. The local filesystem owner ultimately controls the
216
+ database and configuration. Actor binding protects ordinary MCP use but does not cryptographically
217
+ prove who launched a process.
218
+
219
+ Do not store credentials, cookies, tokens, authentication headers, environment values, private keys,
220
+ raw sensitive tool output, or unnecessary private content. `public` means eligible for public export;
221
+ Synomem never publishes automatically. Review [SECURITY.md](SECURITY.md) before sharing exports.
222
+
223
+ ## Future hosted direction
224
+
225
+ A later hosted service may preserve the same workspace-scoped event semantics, aggregate versions,
226
+ idempotency, and bounded feeds. It will require a separately designed authenticated service with
227
+ authorization, tenant isolation, transport security, conflict handling, availability, and explicit
228
+ migration. The SQLite file is never a cloud synchronization protocol.
229
+
230
+ ## Development
231
+
232
+ ```bash
233
+ npm ci
234
+ npm run format:check
235
+ npm run lint
236
+ npm run typecheck
237
+ npm test
238
+ npm run test:coverage
239
+ npm run pack:check
240
+ ```
241
+
242
+ See [CONTRIBUTING.md](CONTRIBUTING.md) and [docs/releasing.md](docs/releasing.md). Do not publish or
243
+ create releases without explicit maintainer authorization.
244
+
245
+ ## License
246
+
247
+ MIT © Troy Locke. See [LICENSE](LICENSE).