threadnote 0.3.7 → 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.
@@ -1,6 +1,6 @@
1
1
  # Agent Instructions
2
2
 
3
- Threadnote installs this as user-level agent guidance for Codex, Claude, and Cursor.
3
+ Threadnote installs this as user-level agent guidance for Codex, Claude, Cursor, and Copilot.
4
4
 
5
5
  ## Shared Context
6
6
 
@@ -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
 
@@ -20,9 +20,14 @@ At the start of a non-trivial task, recall relevant context before making change
20
20
 
21
21
  - the current repo and branch;
22
22
  - recent handoffs;
23
+ - durable feature memories for the branch, feature name, project/topic, or issue;
23
24
  - task-specific skills or workflow guidance;
24
25
  - user or team preferences that may affect the work.
25
26
 
27
+ When a recalled handoff describes an active branch or feature, do a second recall for durable memories about that
28
+ feature before coding. The handoff tells you the current work state; durable feature memories tell you the design,
29
+ decisions, invariants, interfaces, and gotchas that should survive beyond one session.
30
+
26
31
  Skip proactive recall for tiny one-shot questions where context would add noise.
27
32
 
28
33
  Search results are not the final payload. Treat returned `viking://` URIs as pointers: read the relevant URI, or list a
@@ -36,6 +41,12 @@ logs, or other sensitive data.
36
41
  Also remember durable workflow facts you discover during work when they would help future agents and are not already in
37
42
  canonical docs. Prefer updating checked-in docs for canonical repo rules.
38
43
 
44
+ During feature work on a branch, maintain durable feature knowledge in addition to handoffs. Store or update a durable
45
+ memory when you learn something future agents should know about the feature itself: the intended behavior, design
46
+ decisions, API contracts, data flow, migration semantics, edge cases, known limitations, or why an implementation choice
47
+ was made. Do not wait until the end of the branch; update the feature memory whenever a valuable change lands or a
48
+ decision becomes clear.
49
+
39
50
  Use lifecycle metadata when storing memories:
40
51
 
41
52
  - `kind: durable` for facts future agents should use by default.
@@ -46,6 +57,14 @@ Use lifecycle metadata when storing memories:
46
57
  Archived handoffs are provenance, not default working context. Read them only when current durable memories or active
47
58
  handoffs are insufficient.
48
59
 
60
+ For branch feature work, prefer two stable memories with the same project and topic:
61
+
62
+ - `kind: durable` for the feature knowledge that should remain useful after the current agent session.
63
+ - `kind: handoff` for current status, files touched, tests, blockers, and next step.
64
+
65
+ If a durable feature memory already exists, update it in place with the same project/topic or with `--replace <uri>` /
66
+ `replaceUri`. Avoid creating a new timestamped durable memory for every small progress note.
67
+
49
68
  ## Memory Compaction
50
69
 
51
70
  When working on the same active issue, prefer keeping one current-state memory updated instead of creating many small
@@ -56,7 +75,8 @@ progress memories. If an existing memory is clearly the current state for the is
56
75
  When the issue has a stable name, prefer project/topic storage over timestamped memories:
57
76
 
58
77
  ```bash
59
- threadnote remember --kind durable --project my-repo --topic test-workflow --text "..."
78
+ threadnote recall --query "my-repo active-bug durable feature knowledge"
79
+ threadnote remember --kind durable --project my-repo --topic active-bug --text "Feature knowledge: ..."
60
80
  threadnote handoff --project my-repo --topic active-bug --task "..." --tests "..."
61
81
  ```
62
82
 
@@ -73,11 +93,40 @@ them when it is safe:
73
93
 
74
94
  Never compact secrets, credentials, customer data, raw production logs, or checked-in canonical docs into memory.
75
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
+
76
124
  ## Handoff
77
125
 
78
126
  Before pausing, switching agents, or ending meaningful work with local changes, store a concise handoff. Include:
79
127
 
80
128
  - repo and branch;
129
+ - related durable feature memory URI or topic, when known;
81
130
  - files touched;
82
131
  - current status;
83
132
  - tests or checks run;
@@ -93,11 +142,16 @@ Use these only when MCP tools are not available:
93
142
  ```bash
94
143
  threadnote start
95
144
  threadnote recall --query "last handoff for this branch"
145
+ threadnote recall --query "durable feature knowledge for this branch"
96
146
  threadnote read viking://agent/threadnote/memories/.abstract.md
97
147
  threadnote list viking://agent/threadnote/memories --all --recursive
98
148
  threadnote remember --kind durable --project example --topic workflow --text "Durable engineering note..."
149
+ threadnote remember --kind durable --project example --topic active-issue --text "Feature knowledge..."
99
150
  threadnote remember --replace viking://user/example/memories/durable/projects/example/workflow.md --text "Updated durable engineering note..."
100
151
  threadnote archive viking://user/example/memories/handoffs/active/example/old-issue.md
101
152
  threadnote forget viking://user/example/memories/events/duplicate.md
102
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
103
157
  ```
package/docs/migration.md CHANGED
@@ -30,8 +30,8 @@ Developers should not need to run `recall`, `remember`, or `handoff` as a normal
30
30
 
31
31
  The intended workflow has three layers:
32
32
 
33
- - Agent-first: Codex, Claude, or another MCP-enabled agent calls OpenViking tools when the task calls for shared
34
- context.
33
+ - Agent-first: Codex, Claude, Copilot, or another MCP-enabled agent calls OpenViking tools when the task calls for
34
+ shared context.
35
35
  - Short CLI fallback: humans and scripts can run `threadnote recall`, `threadnote remember`, or
36
36
  `threadnote handoff` from any repo.
37
37
  - Checkout-local command: `npm run threadnote -- ...` is the bootstrap and debugging path before the short command shim
@@ -46,8 +46,8 @@ Create a handoff for the next agent before you stop.
46
46
  ```
47
47
 
48
48
  For better continuity, run `threadnote install` so it can add the agent-side guidance from `docs/agent-instructions.md`
49
- to user-level Codex, Claude, and Cursor instruction files. That guidance tells agents to recall context at task start,
50
- store durable memories when explicitly asked or when a reusable workflow fact is learned, and create handoffs
49
+ to user-level Codex, Claude, Cursor, and Copilot instruction files. That guidance tells agents to recall context at task
50
+ start, store durable memories when explicitly asked or when a reusable workflow fact is learned, and create handoffs
51
51
  automatically before stopping meaningful work.
52
52
 
53
53
  ## Migration Steps
@@ -141,6 +141,16 @@ paths.
141
141
 
142
142
  Cursor installs by updating the global `~/.cursor/mcp.json` file.
143
143
 
144
+ For GitHub Copilot in VS Code:
145
+
146
+ ```bash
147
+ threadnote mcp-install copilot
148
+ threadnote mcp-install copilot --apply
149
+ ```
150
+
151
+ Copilot installs by updating the VS Code user-profile `mcp.json` file. If VS Code uses a custom profile path, set
152
+ `THREADNOTE_COPILOT_MCP_CONFIG` to that `mcp.json` path before running `mcp-install copilot`.
153
+
144
154
  Later, if the checkout that installed the MCP adapter is deleted or moved, repair it from any fresh checkout:
145
155
 
146
156
  ```bash
@@ -162,16 +172,21 @@ Preferred developer behavior is conversational:
162
172
 
163
173
  ```text
164
174
  Recall anything relevant for this branch before you start.
165
- Remember this workflow note for future agents: ...
175
+ Remember this feature decision for future agents: ...
166
176
  Create a handoff now.
167
177
  ```
168
178
 
169
179
  Preferred agent behavior is automatic after `threadnote install` has updated the user-level instruction files:
170
180
 
171
- - On non-trivial task start, search OpenViking for recent handoffs and relevant repo guidance.
181
+ - On non-trivial task start, search OpenViking for recent handoffs, durable feature memories for the branch/topic, and
182
+ relevant repo guidance.
172
183
  - When the user says "remember", store the memory after checking that it contains no secret or customer data.
173
- - When continuing the same active issue, update the current-state memory with `remember --replace <uri>` or
174
- `handoff --replace <uri>` instead of creating another near-duplicate progress memory.
184
+ - When continuing the same active issue, keep two current-state records when useful: a durable feature memory for design,
185
+ decisions, interfaces, and gotchas, plus a handoff for status, tests, blockers, and next steps.
186
+ - When valuable feature knowledge changes, update the durable feature memory with the same project/topic or
187
+ `remember --replace <uri>` instead of burying that knowledge only in a handoff.
188
+ - When current status changes, update the active handoff with the same project/topic or `handoff --replace <uri>` instead
189
+ of creating another near-duplicate progress memory.
175
190
  - When recall surfaces clearly duplicate or stale memories, store one concise replacement memory and forget only the
176
191
  redundant originals.
177
192
  - Before pausing, switching agents, or finishing meaningful code changes, store a concise handoff with status, tests,
@@ -181,9 +196,10 @@ Manual CLI remains available for scripts and emergencies:
181
196
 
182
197
  ```bash
183
198
  threadnote recall --query "last handoff for this branch"
184
- threadnote remember --text "Durable engineering note..."
199
+ threadnote recall --query "durable feature knowledge for this branch"
200
+ threadnote remember --kind durable --project example --topic active-feature --text "Feature knowledge..."
185
201
  threadnote remember --replace viking://user/example/memories/events/current.md --text "Updated durable engineering note..."
186
- threadnote handoff --task "short task summary" --tests "checks run" --next-step "what the next agent should do"
202
+ threadnote handoff --project example --topic active-feature --task "short task summary" --tests "checks run" --next-step "what the next agent should do"
187
203
  ```
188
204
 
189
205
  ## Repo Paths
package/docs/rollout.md CHANGED
@@ -18,7 +18,7 @@ Start with a local-only pilot.
18
18
 
19
19
  - Install completes in under 10 minutes after prerequisites.
20
20
  - `doctor` reports clear actionable checks.
21
- - Codex, Claude, or Cursor can store and recall a shared handoff after MCP setup.
21
+ - Codex, Claude, Cursor, or Copilot can store and recall a shared handoff after MCP setup.
22
22
  - Seeding curated guidance does not import known secret patterns.
23
23
  - Fresh agents can recall repo testing guidance and discover relevant skills.
24
24
  - `uninstall --dry-run` previews removal, and `uninstall` leaves memories intact unless `--erase-memories` is explicit.
package/docs/security.md CHANGED
@@ -6,7 +6,8 @@
6
6
 
7
7
  - Credentials, access tokens, API keys, certificates, private keys, or shell history.
8
8
  - Customer data, production data, HIPAA data, or production logs without explicit approval and scrubbing.
9
- - Local auth files such as `~/.codex/auth.json`, `~/.claude/.credentials.json`, or Cursor account/session files.
9
+ - Local auth files such as `~/.codex/auth.json`, `~/.claude/.credentials.json`, Cursor account/session files, or VS Code
10
+ Copilot account/session files.
10
11
  - Local settings files that may contain secrets unless they go through redaction.
11
12
 
12
13
  ## Built-In Controls
@@ -14,9 +15,9 @@
14
15
  - `.threadnoteignore` excludes common secret and build-output paths.
15
16
  - `.mcp.json`, `config.toml`, and settings JSON are redacted before import.
16
17
  - Files are skipped if common secret patterns remain after redaction.
17
- - `mcp-install` requires `--apply` before it changes Codex, Claude, or Cursor config.
18
- - `install` updates user-level Codex, Claude, and Cursor instruction files through a managed Markdown block. Existing
19
- personal instructions outside that block are preserved.
18
+ - `mcp-install` requires `--apply` before it changes Codex, Claude, Cursor, or Copilot config.
19
+ - `install` updates user-level Codex, Claude, Cursor, and Copilot instruction files through managed Threadnote content.
20
+ Existing personal instructions outside managed blocks are preserved.
20
21
  - `uninstall` preserves local memories by default. `--erase-memories` is required before deleting `THREADNOTE_HOME`.
21
22
  - Config files created under `THREADNOTE_HOME` are written with user-only permissions.
22
23
 
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.
@@ -147,7 +147,7 @@ threadnote repair
147
147
  ```
148
148
 
149
149
  `repair` reinstalls the `threadnote` shim, repairs generated config files, starts OpenViking if needed, and rewrites
150
- Codex/Claude/Cursor MCP configs to point at the current checkout.
150
+ Codex/Claude/Cursor/Copilot MCP configs to point at the current checkout.
151
151
 
152
152
  ## MCP Install Is Only Printing Commands
153
153
 
@@ -166,6 +166,16 @@ threadnote mcp-install cursor --apply
166
166
  This updates the global `~/.cursor/mcp.json` file. Restart Cursor or open a fresh agent session after changing MCP
167
167
  config.
168
168
 
169
+ For GitHub Copilot in VS Code:
170
+
171
+ ```bash
172
+ threadnote mcp-install copilot --apply
173
+ ```
174
+
175
+ This updates the VS Code user-profile `mcp.json` file. Restart VS Code or run `MCP: List Servers` from the Command
176
+ Palette after changing MCP config. If VS Code uses a custom profile path, set `THREADNOTE_COPILOT_MCP_CONFIG` to that
177
+ `mcp.json` path before running the command.
178
+
169
179
  ## Cursor MCP Tool Says Query Is Missing
170
180
 
171
181
  If Cursor shows an error like `expected string, received undefined` for Threadnote `search`, the MCP server started but
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "threadnote",
3
- "version": "0.3.7",
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",