@webinson/peer 0.4.23 → 0.4.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -27,6 +27,7 @@ In a Claude Code thread:
27
27
  thread goes, on top of Claude Code's own memory. It saves only the turns from the moment it was chosen.
28
28
  - **Inactive** (not shared): Claude Code's own memory alone; PeerMemory stays off.
29
29
  - **Use Jellyfish** (shared): no memory at all, neither PeerMemory nor Claude Code's own (`MEMORY.md`).
30
+ The agent cannot read, search or change Claude Code's memory files with a tool either.
30
31
  `CLAUDE.md` instructions stay. Claude Code puts `MEMORY.md` into a thread's first message, so a thread meant to
31
32
  hold none starts with `/peer` (or `/peer jellyfish`): a first message with work in it already carries it.
32
33
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "peer-thread-mark",
3
- "version": "0.4.23",
3
+ "version": "0.4.24",
4
4
  "description": "Marks a Claude Code thread shared with Peer (/peer) with a band above the prompt, with /peer stop and /peer start; panes for /peer-list, /peer-thread and /peer-all (search your memories)",
5
5
  "license": "MIT",
6
6
  "types": "./types/index.d.ts"
@@ -276,6 +276,9 @@ async function applyMemory($: EngineInterface) {
276
276
  // What OpenViking's recall and Peer's team memory add to a prompt, left out where the thread keeps OpenViking off.
277
277
  const OPENVIKING_BLOCK = /<openviking-context|<teammates-project-knowledge/
278
278
  const OPENVIKING_TOOL = 'mcp__plugin_openviking-memory_'
279
+ // Claude Code's own memory files, in a tool's input however it is written: a path, a glob, a shell command that
280
+ // changes into ~/.claude first or looks for MEMORY.md there. A call that names both is held back.
281
+ const usesMemoryFiles = (input: string) => /\.claude(?=[\\/"'\s]|$)/.test(input) && /memory/i.test(input)
279
282
 
280
283
  // The memory badge's color: an explicit value, as a surface may not know a theme key; it reads on light and dark.
281
284
  const SAVED_COLOR = '#8b5cf6'
@@ -711,6 +714,11 @@ export const register: Register = on => {
711
714
  if (e.tool.startsWith(OPENVIKING_TOOL) && (await memoryUse($)) !== 'openviking') {
712
715
  return { deny: 'PeerMemory is off in this thread. Use Elephant turns it on.' }
713
716
  }
717
+ // Jellyfish keeps Claude Code's memory files out of the context, and an agent that knows where they live
718
+ // (~/.claude/projects/<project>/memory) does not read, search or write them with a tool either.
719
+ if (usesMemoryFiles(JSON.stringify(e)) && (await memoryUse($)) === 'none') {
720
+ return { deny: "Jellyfish: this thread uses no memory, Claude Code's memory files included. Use Elephant or Inactive brings them back." }
721
+ }
714
722
  return next(e)
715
723
  })
716
724
 
@@ -77,12 +77,24 @@ test('Elephant turns OpenViking on, Inactive keeps Claude Code memory alone, Jel
77
77
  await search()
78
78
  expect(toolRuns).toBe(1)
79
79
  expect((await $.prompt.section({ name: 'memory', text: 'how memory works' })).text).toBeNull()
80
+ // Nor its memory files, read, searched or changed with a tool; other files under ~/.claude still are.
81
+ const denied = async (input: object) => {
82
+ const before = toolRuns
83
+ const result = (await $.tool.call(input as never)) as { deny?: string }
84
+ return toolRuns === before && Boolean(result?.deny)
85
+ }
86
+ expect(await denied({ tool: 'Read', file_path: '/home/.claude/projects/p/memory/peer-proof.md' })).toBe(true)
87
+ expect(await denied({ tool: 'Bash', command: 'cd ~/.claude && cat projects/p/memory/MEMORY.md' })).toBe(true)
88
+ expect(await denied({ tool: 'Grep', pattern: '12/13', path: '/home/.claude/projects' , glob: '**/memory/*.md' })).toBe(true)
89
+ expect(await denied({ tool: 'Read', file_path: '/home/.claude/settings.json' })).toBe(false)
90
+ expect(await denied({ tool: 'Read', file_path: '/repo/.claude-plugin/memory.json' })).toBe(false)
80
91
  const kept = (await context()).blocks.find(b => b.name === 'claudeMd')?.text ?? ''
81
92
  expect(kept).toContain('Be brief.')
82
93
  expect(kept).not.toContain('a fact')
83
94
 
84
95
  // Pressing the lit Jellyfish stops sharing: Inactive, OpenViking still off, Claude Code's own memory back.
85
96
  await band.press({ key: 'jellyfish' } as never)
97
+ expect(await denied({ tool: 'Read', file_path: '/home/.claude/projects/p/memory/peer-proof.md' })).toBe(false)
86
98
  expect(env.OPENVIKING_MEMORY_ENABLED).toBe('0')
87
99
  expect(await recalled()).toEqual(['kept'])
88
100
  expect((await $.prompt.section({ name: 'memory', text: 'how memory works' })).text).toBe('how memory works')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webinson/peer",
3
- "version": "0.4.23",
3
+ "version": "0.4.24",
4
4
  "description": "Share chosen Claude Code and Codex threads with your team: who has agents running and on what.",
5
5
  "license": "MIT",
6
6
  "type": "module",