threadnote 0.3.8 → 0.4.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.
@@ -8,9 +8,9 @@ Use OpenViking through Threadnote as a shared local context and memory layer. Re
8
8
  follow the nearest `AGENTS.md`, `CLAUDE.md`, or other checked-in instruction file first.
9
9
 
10
10
  When OpenViking MCP tools are available, use them directly. Prefer Threadnote-named MCP tools when present:
11
- `recall_context`, `read_context`, `list_context`, and `remember_context`. Always pass JSON arguments to MCP tools, for
12
- example `recall_context({"query":"current repo latest handoff"})`. Older Threadnote MCP adapters may expose
13
- `search`, `read`, `list`, and `store` instead.
11
+ `recall_context`, `read_context`, `list_context`, `remember_context`, and `share_publish`. Always pass JSON arguments to
12
+ MCP tools, for example `recall_context({"query":"current repo latest handoff"})`. Older Threadnote MCP adapters may
13
+ expose `search`, `read`, `list`, and `store` instead.
14
14
 
15
15
  If MCP is unavailable, use the `threadnote` CLI fallback.
16
16
 
@@ -93,6 +93,34 @@ them when it is safe:
93
93
 
94
94
  Never compact secrets, credentials, customer data, raw production logs, or checked-in canonical docs into memory.
95
95
 
96
+ ## Sharing memories with teammates
97
+
98
+ Threadnote can publish a curated subset of durable memories into a team git repo so other engineers' agents can pull them.
99
+ The mechanism lives under the `viking://user/<you>/memories/shared/<team>/...` subtree; only memories that are explicitly
100
+ published leave the machine. Personal handoffs, preferences, and unpublished durable notes always stay local.
101
+
102
+ Publish a durable memory when its content is useful to other engineers working on the same project (intended behavior,
103
+ design decisions, API contracts, gotchas) and is safe to share. Do NOT publish:
104
+
105
+ - handoffs or anything carrying machine-local paths, branch state, or in-flight task context;
106
+ - memories under `memories/preferences/`;
107
+ - anything mentioning secrets, customer data, raw logs, or material a teammate's git history shouldn't carry.
108
+
109
+ The MCP tool `share_publish` runs the same scrubber as the CLI and refuses to publish memories containing common secret
110
+ patterns (PEM private keys, `sk-...`, `gh[pousr]_...`, `Bearer ...`, `AKIA...`, `xox[abprs]-...`). It is a destructive
111
+ operation: it removes the personal copy after the shared copy is committed.
112
+
113
+ When a teammate's memory needs to come into your own working set, run `threadnote share sync` (no MCP equivalent yet) to
114
+ pull and reindex.
115
+
116
+ ```
117
+ # MCP call shape
118
+ share_publish({"uri":"viking://user/you/memories/durable/projects/foo/bar.md"})
119
+ share_publish({"uri":"viking://user/you/memories/durable/projects/foo/bar.md","team":"friends","push":false})
120
+ ```
121
+
122
+ Before publishing, confirm with the user unless they have already instructed you to share durable memories autonomously.
123
+
96
124
  ## Handoff
97
125
 
98
126
  Before pausing, switching agents, or ending meaningful work with local changes, store a concise handoff. Include:
@@ -123,4 +151,7 @@ threadnote remember --replace viking://user/example/memories/durable/projects/ex
123
151
  threadnote archive viking://user/example/memories/handoffs/active/example/old-issue.md
124
152
  threadnote forget viking://user/example/memories/events/duplicate.md
125
153
  threadnote handoff --project example --topic active-issue --task "short task summary" --tests "checks run" --next-step "what to do next"
154
+ threadnote share init git@github.com:org/team-memories.git
155
+ threadnote share publish viking://user/example/memories/durable/projects/foo/bar.md
156
+ threadnote share sync
126
157
  ```
package/docs/share.md ADDED
@@ -0,0 +1,151 @@
1
+ # Sharing memories with teammates
2
+
3
+ `threadnote share` lets a small team keep a curated set of durable memories in a
4
+ git repository so every member's local agent can recall them. Personal handoffs,
5
+ preferences, and unpublished durable notes stay local; only memories you
6
+ explicitly publish leave your machine.
7
+
8
+ ## Model in one screen
9
+
10
+ - A **team** is a configured shared repo. Each team has a name (default:
11
+ `default`), a git remote, a local working tree, and a separate gitdir.
12
+ - The working tree lives inside the OpenViking data tree at
13
+ `~/.openviking/data/viking/<account>/user/<you>/memories/shared/<team>/`. That
14
+ means files appearing in the worktree are also addressable as
15
+ `viking://user/<you>/memories/shared/<team>/...` and show up in normal
16
+ `recall`.
17
+ - The gitdir lives outside the OV data tree at
18
+ `~/.openviking/share/teams/<team>.gitdir/` so OpenViking never sees git
19
+ internals.
20
+ - Team configuration is recorded in `~/.openviking/share/teams.json` (mode
21
+ `0600`).
22
+
23
+ ## Workflow
24
+
25
+ ### One-time setup
26
+
27
+ ```bash
28
+ # Create the repo first on GitHub/GitLab/etc. and copy its SSH URL.
29
+ threadnote share init git@github.com:org/team-memories.git
30
+ # Optional: add a second team
31
+ threadnote share init --team friends git@github.com:you/friends-memories.git
32
+ # Switch the default with init --set-default <name> or by running publish/sync
33
+ # with an explicit --team.
34
+ ```
35
+
36
+ `share init` clones the remote into your local memory tree and ingests any
37
+ existing markdown memories into OpenViking.
38
+
39
+ ### See what's configured
40
+
41
+ ```bash
42
+ threadnote share list
43
+ threadnote share status # default team
44
+ threadnote share status --team friends
45
+ ```
46
+
47
+ ### Share a memory
48
+
49
+ ```bash
50
+ # 1. Identify the personal URI you want to publish (use recall/list as usual).
51
+ # 2. Publish:
52
+ threadnote share publish viking://user/you/memories/durable/projects/foo/bar.md
53
+ # Optional flags: --team <name>, --message "...", --no-push, --dry-run.
54
+ ```
55
+
56
+ `share publish` moves the memory from your personal namespace into the team's
57
+ shared subtree, commits with the message
58
+ `share: publish <relative-path>`, and pushes. The memory's recall path becomes
59
+ `viking://user/you/memories/shared/<team>/durable/projects/foo/bar.md`.
60
+
61
+ ### Pull teammates' updates
62
+
63
+ ```bash
64
+ threadnote share sync # default team
65
+ threadnote share sync --team friends # other team
66
+ threadnote share sync --no-push # pull only
67
+ ```
68
+
69
+ `share sync` will auto-commit any uncommitted edits in the worktree, fetch and
70
+ rebase from the remote, reindex pulled markdown files into OpenViking (so
71
+ `recall` finds them immediately), and push. Pass `--no-auto-commit` to refuse
72
+ syncing when the worktree is dirty.
73
+
74
+ ### Take a memory back
75
+
76
+ ```bash
77
+ threadnote share unpublish viking://user/you/memories/shared/default/durable/projects/foo/bar.md
78
+ ```
79
+
80
+ The memory is rewritten back into your personal namespace and removed from the
81
+ shared repo.
82
+
83
+ ### Stop sharing for a team
84
+
85
+ ```bash
86
+ threadnote share remove --team friends # deletes worktree + gitdir
87
+ threadnote share remove --team friends --keep-files
88
+ ```
89
+
90
+ `share remove` without `--keep-files` deletes the local checkout. Push any
91
+ unpushed commits first (`threadnote share sync` or `git -C <worktree> push`),
92
+ otherwise unpublished work is lost.
93
+
94
+ ## Privacy & safety rules
95
+
96
+ - Only memories you actively publish leave your machine. `share init` will
97
+ refuse to clone over a non-empty worktree.
98
+ - `share publish` runs a best-effort scrubber over the memory text. It refuses
99
+ to publish if it matches any of:
100
+ - PEM private key headers (`-----BEGIN ... PRIVATE KEY-----`)
101
+ - OpenAI / Anthropic-style `sk-...` keys (16+ chars). Note: this also matches
102
+ any URL slug or random string starting with `sk-`; if you hit a false
103
+ positive on legitimate content, edit the memory to break the pattern.
104
+ - GitHub classic tokens (`gh[pousr]_...`)
105
+ - GitHub fine-grained PATs (`github_pat_...`)
106
+ - GitLab PATs (`glpat-...`)
107
+ - HTTP `Bearer ...` tokens (20+ chars)
108
+ - Bare JWTs (three base64url segments starting `eyJ...`) — catches a leaked
109
+ token even when the surrounding `Authorization: Bearer ` prefix has been
110
+ stripped. JWE tokens in legitimate documentation can collide; edit the
111
+ memory if the false positive is unavoidable.
112
+ - AWS access keys (`AKIA...`)
113
+ - Slack tokens (`xoxa`, `xoxb`, `xoxc`, `xoxd`, `xoxe`, `xoxp`, `xoxr`,
114
+ `xoxs`, with optional `-N-` segment markers — covers bot, user,
115
+ configuration, legacy cookie, refresh, app, and similar shapes)
116
+ - The scrubber complements but does not replace human review. Strip the value,
117
+ then retry.
118
+ - Only the `durable/` kind is shareable. `handoffs/`, `preferences/`,
119
+ `incidents/`, and other lifecycle kinds stay local by construction — both
120
+ the initial ingest (`share init`) and the sync-pull reindex (`share sync`)
121
+ skip any file outside `durable/`.
122
+ - `share publish` deletes the personal copy after publishing. If you want to
123
+ keep both, copy the memory to a new URI first (`ov read` then
124
+ `threadnote remember`).
125
+ - `share publish` refuses to overwrite an existing shared memory at the same
126
+ URI; forget the existing shared copy first or pick a different topic name.
127
+
128
+ ## Conflict resolution
129
+
130
+ `share sync` uses `git pull --rebase` against the remote. When git can't merge
131
+ cleanly:
132
+
133
+ 1. The pull command reports the conflict and leaves the worktree in a
134
+ rebase-in-progress state.
135
+ 2. Resolve the conflicts manually in the worktree (it's a normal git checkout).
136
+ 3. Run `git rebase --continue` (or `--abort`) yourself.
137
+ 4. Re-run `threadnote share sync` to finish the reindex and push.
138
+
139
+ Two publishes touching the same `<topic>.md` from different machines will
140
+ collide; coordinate ownership per-topic, or use distinct topics.
141
+
142
+ ## Cross-machine identity notes
143
+
144
+ Each user clones into their own user-namespaced path. A memory authored on
145
+ machine A as `viking://user/alice/memories/shared/team/durable/projects/foo/bar.md`
146
+ shows up on machine B as
147
+ `viking://user/bob/memories/shared/team/durable/projects/foo/bar.md`. The file
148
+ content (including any `supersedes:` URIs that reference the original author) is
149
+ identical, but explicit URI cross-references will point at the author's
150
+ namespace. For now, prefer narrative references ("see the foo memory under
151
+ shared/team") over URI links in shared content.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadnote",
3
- "version": "0.3.8",
3
+ "version": "0.4.0",
4
4
  "type": "commonjs",
5
5
  "main": "dist/threadnote.cjs",
6
6
  "description": "Shared local context and handoffs for development agents",