memhouse 0.18.12 → 0.20.1
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/AGENTS.md +22 -151
- package/CHANGELOG.md +263 -29
- package/LICENSE +202 -22
- package/LICENSES/agentlytics-MIT.txt +21 -0
- package/LICENSES/memhouse-MIT-until-0.18.11.txt +22 -0
- package/LICENSES/models.dev-MIT.txt +22 -0
- package/NOTICE +28 -0
- package/README.md +42 -20
- package/SECURITY.md +21 -8
- package/bin/memhouse.js +2223 -311
- package/docs/README.md +11 -9
- package/docs/guides/admin-password.md +37 -10
- package/docs/guides/configuration.md +13 -6
- package/docs/guides/daemons.md +64 -3
- package/docs/guides/import-claude-ai.md +204 -0
- package/docs/guides/install.md +11 -6
- package/docs/guides/invite.md +21 -7
- package/docs/guides/operate.md +114 -7
- package/docs/guides/search-and-resume.md +72 -3
- package/docs/guides/share.md +91 -52
- package/docs/guides/storage.md +44 -4
- package/docs/guides/troubleshooting.md +121 -14
- package/docs/guides/uninstall.md +4 -3
- package/docs/guides/update.md +16 -0
- package/docs/guides/upgrade-to-0.20.md +188 -0
- package/docs/releases/README.md +2 -1
- package/docs/releases/v0.18.10.md +5 -5
- package/docs/releases/v0.18.11.md +3 -3
- package/docs/releases/v0.20.0.md +627 -0
- package/docs/releases/v0.20.1.md +114 -0
- package/docs/tutorials/01-first-house.md +10 -7
- package/docs/tutorials/02-join-a-house.md +24 -15
- package/docs/tutorials/03-share-your-memory.md +40 -31
- package/editors/antigravity.js +1 -80
- package/editors/base.js +463 -9
- package/editors/bridge.js +119 -0
- package/editors/claude.js +273 -105
- package/editors/codex.js +278 -52
- package/editors/copilot.js +1 -70
- package/editors/cursor.js +1 -75
- package/editors/derive-fingerprints.json +18 -0
- package/editors/harness-paths.js +69 -0
- package/editors/index.js +1 -20
- package/editors/normalise/agy.js +910 -0
- package/editors/normalise/copilot-cli.js +321 -0
- package/editors/normalise/cursor-agent.js +852 -0
- package/editors/normalise/cursor.js +474 -0
- package/editors/normalise/devin.js +575 -0
- package/editors/normalise/gemini-cli.js +602 -0
- package/editors/normalise/goose.js +673 -0
- package/editors/normalise/opencode.js +633 -0
- package/editors/normalise/vscode.js +549 -0
- package/editors/normalise/zed.js +473 -0
- package/editors/opencode-v4.js +119 -0
- package/editors/scope.js +14 -3
- package/editors/sessions-log.js +349 -0
- package/editors/sqlite.js +28 -1
- package/editors/vscode.js +1 -72
- package/editors/windsurf.js +1 -143
- package/examples/01-local-one-machine/README.md +24 -19
- package/examples/01-local-one-machine/run.sh +1 -1
- package/examples/02-existing-clickhouse/README.md +30 -22
- package/examples/02-existing-clickhouse/run.sh +5 -4
- package/examples/03-team-house/README.md +44 -37
- package/examples/03-team-house/run.sh +35 -18
- package/examples/04-self-hosted-team/README.md +29 -14
- package/examples/04-self-hosted-team/compose.yml +5 -2
- package/examples/04-self-hosted-team/smoke.sh +26 -12
- package/examples/README.md +8 -4
- package/examples/fixtures/README.md +4 -1
- package/examples/fixtures/make-sessions.js +8 -5
- package/memhouse/admin-secret.js +89 -24
- package/memhouse/argv-secrets.js +64 -0
- package/memhouse/channel.js +49 -9
- package/memhouse/codex-plugin.js +194 -0
- package/memhouse/delivery/AGENT-INSTALL-PROMPT.md +2 -1
- package/memhouse/delivery/AGENT-INSTALL.md +22 -11
- package/memhouse/delivery/INVITATION.md.tpl +44 -45
- package/memhouse/delivery/PROMPT.md +53 -5
- package/memhouse/delivery/UPGRADE.md.tpl +1 -1
- package/memhouse/delivery/codex/AGENTS-BLOCK.md +11 -0
- package/memhouse/delivery/codex/SKILL.md +50 -0
- package/memhouse/delivery/kernel-install.md +17 -9
- package/memhouse/delivery/plugin/.claude-plugin/plugin.json +2 -2
- package/memhouse/delivery/plugin/reference/HOUSE.md +168 -41
- package/memhouse/delivery/plugin/skills/access/SKILL.md +13 -5
- package/memhouse/delivery/plugin/skills/admin/SKILL.md +14 -6
- package/memhouse/delivery/plugin/skills/house/SKILL.md +25 -8
- package/memhouse/delivery/plugin/skills/recall/SKILL.md +66 -8
- package/memhouse/delivery/plugin/skills/sql/SKILL.md +66 -7
- package/memhouse/deploy.js +1 -1
- package/memhouse/flags.js +35 -18
- package/memhouse/help.js +37 -0
- package/memhouse/host.js +82 -2
- package/memhouse/house/HOUSE.md +2 -2
- package/memhouse/house/convert-profile.js +638 -0
- package/memhouse/house/convert-v3.js +742 -0
- package/memhouse/house/doctor-v3.js +324 -0
- package/memhouse/house/host-alias.js +85 -0
- package/memhouse/house/house.js +3 -3
- package/memhouse/house/migrate.js +2 -2
- package/memhouse/house/profile-dedupe.js +183 -0
- package/memhouse/house/profile-edges.js +554 -0
- package/memhouse/house/profile-house.js +430 -0
- package/memhouse/house/profile-rollup.js +190 -0
- package/memhouse/house/q-cli.js +863 -0
- package/memhouse/house/queries-v3.js +1013 -0
- package/memhouse/house/reconcile-v3.js +192 -0
- package/memhouse/house/records-to-profile.js +174 -0
- package/memhouse/house/records-to-rows.js +169 -0
- package/memhouse/house/relocate.js +2 -1
- package/memhouse/house/schema-choice.js +121 -0
- package/memhouse/house/schema-profile.js +290 -0
- package/memhouse/house/schema-profile.sql.tpl +398 -0
- package/memhouse/house/schema-v3.js +267 -0
- package/memhouse/house/schema-v3.sql.tpl +213 -0
- package/memhouse/import/claude-ai.js +420 -0
- package/memhouse/import/import.js +372 -0
- package/memhouse/import/pyjson.js +206 -0
- package/memhouse/import/records.js +64 -0
- package/memhouse/import/writer-profile.js +192 -0
- package/memhouse/import/writer-v3.js +240 -0
- package/memhouse/import/zip.js +112 -0
- package/memhouse/invitation.js +102 -0
- package/memhouse/invitefile.js +5 -2
- package/memhouse/plugin-copies.js +176 -0
- package/memhouse/provision.js +7 -2
- package/memhouse/release-hint.js +24 -0
- package/memhouse/resume.js +4 -4
- package/memhouse/server/api-v3.js +632 -0
- package/memhouse/server/dashboard-auth.js +181 -0
- package/memhouse/server/dashboard-port.js +91 -0
- package/memhouse/server/queries.js +30 -0
- package/memhouse/server/server.js +118 -20
- package/memhouse/service.js +1 -1
- package/memhouse/share.js +687 -1
- package/memhouse/shipper/adapter-capture.js +756 -0
- package/memhouse/shipper/capture.js +2571 -0
- package/memhouse/shipper/dedupe-profile.js +237 -0
- package/memhouse/shipper/dedupe-v3.js +1027 -0
- package/memhouse/shipper/forks.js +233 -0
- package/memhouse/shipper/log-adapter.js +219 -0
- package/memhouse/shipper/maintenance.js +49 -0
- package/memhouse/shipper/normalise-run.js +148 -0
- package/memhouse/shipper/passlog.js +68 -5
- package/memhouse/shipper/profile-capture.js +903 -0
- package/memhouse/shipper/ship.js +91 -8
- package/memhouse/shipper/snapshots.js +193 -0
- package/memhouse/shipper/source-roots.js +111 -0
- package/memhouse/version-notice.js +66 -0
- package/package.json +14 -7
- package/public/THIRD_PARTY_NOTICES.txt +2 -2
- package/public/assets/index-CcNnhfM3.js +78 -0
- package/public/index.html +1 -1
- package/ui/package-lock.json +56 -37
- package/ui/package.json +1 -0
- package/ui/src/App.jsx +29 -14
- package/ui/src/components/ChatSidebar.jsx +69 -12
- package/ui/src/lib/api.js +76 -0
- package/ui/src/lib/dashboard-token.js +41 -0
- package/ui/src/main.jsx +22 -5
- package/ui/src/pages/Dashboard.jsx +22 -36
- package/ui/third-party-notices.js +119 -0
- package/ui/vite.config.js +5 -1
- package/docs/releases/v0.18.12.md +0 -59
- package/memhouse/COMPETITION.md +0 -221
- package/memhouse/DESIGN.md +0 -222
- package/memhouse/RESUME-AND-UPDATE.md +0 -182
- package/public/assets/index-CnWzrjF3.js +0 -78
|
@@ -8,7 +8,7 @@ import ActivityHeatmap from '../components/ActivityHeatmap'
|
|
|
8
8
|
import DateRangePicker from '../components/DateRangePicker'
|
|
9
9
|
import { editorColor, editorLabel, formatNumber, formatCost, dateRangeToApiParams } from '../lib/constants'
|
|
10
10
|
import EditorIcon from '../components/EditorIcon'
|
|
11
|
-
import {
|
|
11
|
+
import { fetchLanding } from '../lib/api'
|
|
12
12
|
import ChatSidebar from '../components/ChatSidebar'
|
|
13
13
|
import AnimatedLoader from '../components/AnimatedLoader'
|
|
14
14
|
import ShareModal from '../components/ShareModal'
|
|
@@ -26,7 +26,7 @@ const MODE_COLORS = {
|
|
|
26
26
|
copilot: '#f59e0b', thread: '#ec4899', opencode: '#f43f5e', claude: '#f97316',
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
export default function Dashboard({ overview }) {
|
|
29
|
+
export default function Dashboard({ overview, refreshKey = 0 }) {
|
|
30
30
|
const navigate = useNavigate()
|
|
31
31
|
const [dailyData, setDailyData] = useState(null)
|
|
32
32
|
const [filteredData, setFilteredData] = useState(null)
|
|
@@ -37,6 +37,7 @@ export default function Dashboard({ overview }) {
|
|
|
37
37
|
const [costs, setCosts] = useState(null)
|
|
38
38
|
const [shareOpen, setShareOpen] = useState(false)
|
|
39
39
|
const [largeContextChats, setLargeContextChats] = useState(null)
|
|
40
|
+
const [largeContextTotal, setLargeContextTotal] = useState(null)
|
|
40
41
|
const [selectedChatId, setSelectedChatId] = useState(null)
|
|
41
42
|
const txtColor = dark ? '#888' : '#555'
|
|
42
43
|
const txtDim = dark ? '#555' : '#999'
|
|
@@ -56,40 +57,25 @@ export default function Dashboard({ overview }) {
|
|
|
56
57
|
}
|
|
57
58
|
const noLegend = { legend: { display: false }, tooltip: { bodyFont: { family: MONO, size: 10 }, titleFont: { family: MONO, size: 10 } } }
|
|
58
59
|
|
|
60
|
+
// ONE request for the whole page (/api/landing). It used to be five — overview, daily
|
|
61
|
+
// activity, dashboard stats, costs and a 500-session chat list priced only to find the ten
|
|
62
|
+
// largest — 33–34 SQL statements behind them. `refreshKey` moves when Live sees the house
|
|
63
|
+
// version change or Refetch completes.
|
|
59
64
|
useEffect(() => {
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (hasDates) fetchOverviewApi(dateParams).then(setFilteredData)
|
|
75
|
-
else setFilteredData(null)
|
|
76
|
-
fetchDailyActivity(dateParams).then(setDailyData)
|
|
77
|
-
fetchDashboardStats(dateParams).then(setStats)
|
|
78
|
-
fetchCosts(dateParams).then(setCosts)
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
Promise.all([
|
|
82
|
-
fetchOverviewApi({ editor: selectedEditor, ...dateParams }),
|
|
83
|
-
fetchDailyActivity({ editor: selectedEditor, ...dateParams }),
|
|
84
|
-
fetchDashboardStats({ editor: selectedEditor, ...dateParams }),
|
|
85
|
-
fetchCosts({ editor: selectedEditor, ...dateParams }),
|
|
86
|
-
]).then(([ov, daily, st, c]) => {
|
|
87
|
-
setFilteredData(ov)
|
|
88
|
-
setDailyData(daily)
|
|
89
|
-
setStats(st)
|
|
90
|
-
setCosts(c)
|
|
91
|
-
})
|
|
92
|
-
}, [selectedEditor, dateRange])
|
|
65
|
+
const params = { ...dateRangeToApiParams(dateRange) }
|
|
66
|
+
if (selectedEditor) params.editor = selectedEditor
|
|
67
|
+
let cancelled = false
|
|
68
|
+
fetchLanding(params).then(r => {
|
|
69
|
+
if (cancelled) return
|
|
70
|
+
setFilteredData(r.overview)
|
|
71
|
+
setDailyData(r.daily)
|
|
72
|
+
setStats(r.stats)
|
|
73
|
+
setCosts(r.costs)
|
|
74
|
+
setLargeContextChats(r.largeContext.chats)
|
|
75
|
+
setLargeContextTotal(r.largeContext.total)
|
|
76
|
+
}).catch(() => {})
|
|
77
|
+
return () => { cancelled = true }
|
|
78
|
+
}, [selectedEditor, dateRange, refreshKey])
|
|
93
79
|
|
|
94
80
|
if (!overview) return <AnimatedLoader label="Loading dashboard..." />
|
|
95
81
|
|
|
@@ -500,7 +486,7 @@ export default function Dashboard({ overview }) {
|
|
|
500
486
|
<span className="inline-flex items-center gap-1">
|
|
501
487
|
<AlertTriangle size={10} className="text-amber-400" />
|
|
502
488
|
large context
|
|
503
|
-
<span style={{ color: 'var(--c-text3)' }}>({largeContextChats.length})</span>
|
|
489
|
+
<span style={{ color: 'var(--c-text3)' }}>({largeContextTotal ?? largeContextChats.length})</span>
|
|
504
490
|
</span>
|
|
505
491
|
</SectionTitle>
|
|
506
492
|
<div className="space-y-1">
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/* global process */
|
|
2
|
+
// Writes THIRD_PARTY_NOTICES.txt beside the built dashboard (public/), listing every
|
|
3
|
+
// third-party package whose code ends up in the bundle, with its license text.
|
|
4
|
+
//
|
|
5
|
+
// Why: the bundle carries React, chart.js, lucide, react-markdown and others, all under
|
|
6
|
+
// licenses (MIT, ISC, …) whose one condition is that the notice travels with every copy.
|
|
7
|
+
// Vite strips their license comments when it minifies, so the published package shipped
|
|
8
|
+
// those copies with no notice at all. This plugin reads the bundle's own module graph, so
|
|
9
|
+
// the list is exactly what was bundled, never a hand-kept list that drifts.
|
|
10
|
+
//
|
|
11
|
+
// No dependency of its own on purpose: it reads each package's package.json and license
|
|
12
|
+
// file straight off node_modules.
|
|
13
|
+
import fs from 'node:fs'
|
|
14
|
+
import path from 'node:path'
|
|
15
|
+
|
|
16
|
+
const LICENSE_FILE = /^(licen[sc]e|copying|notice)([.-].*)?$/i
|
|
17
|
+
|
|
18
|
+
// Bundled packages that genuinely ship no license file, each with its declared license
|
|
19
|
+
// and why it may be listed without a text. Any other package without one fails the build.
|
|
20
|
+
// Empty today: every bundled package ships its license file.
|
|
21
|
+
// 'name': { license: 'MIT', reason: 'one line: why there is no file, and what was checked' },
|
|
22
|
+
export const NO_LICENSE_FILE = {}
|
|
23
|
+
|
|
24
|
+
// '/abs/ui/node_modules/react-dom/cjs/x.js' -> { name: 'react-dom', dir: '/abs/ui/node_modules/react-dom' }
|
|
25
|
+
// The LAST node_modules segment wins, so a nested copy is attributed to itself.
|
|
26
|
+
export function packageOf(id) {
|
|
27
|
+
const clean = String(id).replace(/^\0/, '').split('?')[0].split(path.sep).join('/')
|
|
28
|
+
const i = clean.lastIndexOf('/node_modules/')
|
|
29
|
+
if (i < 0) return null
|
|
30
|
+
const parts = clean.slice(i + '/node_modules/'.length).split('/')
|
|
31
|
+
const name = parts[0].startsWith('@') ? `${parts[0]}/${parts[1]}` : parts[0]
|
|
32
|
+
if (!name || name.startsWith('.')) return null
|
|
33
|
+
return { name, dir: clean.slice(0, i + '/node_modules/'.length) + name }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readPackage(dir) {
|
|
37
|
+
let pkg = {}
|
|
38
|
+
try { pkg = JSON.parse(fs.readFileSync(path.join(dir, 'package.json'), 'utf-8')) } catch { /* no manifest */ }
|
|
39
|
+
let files = []
|
|
40
|
+
try { files = fs.readdirSync(dir).filter((f) => LICENSE_FILE.test(f)).sort() } catch { /* unreadable dir */ }
|
|
41
|
+
const texts = files.map((f) => {
|
|
42
|
+
try { return { file: f, text: fs.readFileSync(path.join(dir, f), 'utf-8').trim() } } catch { return null }
|
|
43
|
+
}).filter(Boolean)
|
|
44
|
+
const license = typeof pkg.license === 'string' ? pkg.license
|
|
45
|
+
: (pkg.license && pkg.license.type) || (Array.isArray(pkg.licenses) ? pkg.licenses.map((l) => l.type || l).join(' OR ') : '')
|
|
46
|
+
const repo = typeof pkg.repository === 'string' ? pkg.repository : (pkg.repository && pkg.repository.url) || pkg.homepage || ''
|
|
47
|
+
return { version: pkg.version || '', license: license || 'UNKNOWN', repo, texts }
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* @param {object} [o]
|
|
52
|
+
* @param {string} [o.fileName] where the notices land, relative to outDir
|
|
53
|
+
* @param {string[]} [o.extra] packages that reach the bundle without showing up as a JS
|
|
54
|
+
* module: tailwindcss (its preflight CSS is in the stylesheet),
|
|
55
|
+
* react-router-dom (it only re-exports react-router, so the
|
|
56
|
+
* graph holds react-router's modules, not its own)
|
|
57
|
+
* @param {string} [o.root] where to resolve `extra` from (the ui/ directory)
|
|
58
|
+
*/
|
|
59
|
+
export default function thirdPartyNotices({ fileName = 'THIRD_PARTY_NOTICES.txt', extra = [], root = process.cwd() } = {}) {
|
|
60
|
+
return {
|
|
61
|
+
name: 'memhouse-third-party-notices',
|
|
62
|
+
apply: 'build',
|
|
63
|
+
generateBundle(_options, bundle) {
|
|
64
|
+
// Keyed by INSTALL DIRECTORY, not by name: two versions of one package can both be
|
|
65
|
+
// bundled (a nested copy beside the top-level one), and each carries its own license.
|
|
66
|
+
const found = new Map() // dir -> name
|
|
67
|
+
for (const out of Object.values(bundle)) {
|
|
68
|
+
if (out.type !== 'chunk') continue
|
|
69
|
+
for (const id of Object.keys(out.modules || {})) {
|
|
70
|
+
const p = packageOf(id)
|
|
71
|
+
if (p && !found.has(p.dir)) found.set(p.dir, p.name)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
for (const name of extra) {
|
|
75
|
+
const dir = path.join(root, 'node_modules', name).split(path.sep).join('/')
|
|
76
|
+
if (!found.has(dir) && fs.existsSync(dir)) found.set(dir, name)
|
|
77
|
+
}
|
|
78
|
+
// One entry per name@version; two install dirs holding the same version are one notice.
|
|
79
|
+
const entries = new Map()
|
|
80
|
+
for (const [dir, name] of found) {
|
|
81
|
+
const info = readPackage(dir)
|
|
82
|
+
const key = `${name}@${info.version}`
|
|
83
|
+
if (!entries.has(key)) entries.set(key, { name, ...info })
|
|
84
|
+
}
|
|
85
|
+
const list = [...entries.values()].sort((a, b) => (a.name === b.name
|
|
86
|
+
? a.version.localeCompare(b.version, undefined, { numeric: true })
|
|
87
|
+
: (a.name < b.name ? -1 : 1)))
|
|
88
|
+
// A bundled package whose license text cannot be shipped fails the build. A notice
|
|
89
|
+
// file that silently omits one is the defect this plugin exists to prevent. The only
|
|
90
|
+
// exceptions are packages that genuinely ship no license file, named in
|
|
91
|
+
// NO_LICENSE_FILE with their declared license and the reason.
|
|
92
|
+
const missing = list.filter((e) => !e.texts.length && !NO_LICENSE_FILE[e.name])
|
|
93
|
+
if (missing.length) {
|
|
94
|
+
this.error(`bundled without a license text: ${missing.map((e) => `${e.name}@${e.version} (declares ${e.license})`).join(', ')}. `
|
|
95
|
+
+ 'Add the license text, or list the package in NO_LICENSE_FILE (ui/third-party-notices.js) with its declared license and why.')
|
|
96
|
+
}
|
|
97
|
+
const blocks = list.map((e) => {
|
|
98
|
+
const allowed = NO_LICENSE_FILE[e.name]
|
|
99
|
+
const head = `${e.name}${e.version ? ` ${e.version}` : ''} — ${e.license}${e.repo ? `\n${e.repo}` : ''}`
|
|
100
|
+
const body = e.texts.length
|
|
101
|
+
? e.texts.map((t) => (e.texts.length > 1 ? `[${t.file}]\n${t.text}` : t.text)).join('\n\n')
|
|
102
|
+
: `(this package ships no license file; declared license: ${allowed.license}. ${allowed.reason})`
|
|
103
|
+
return `${'='.repeat(72)}\n${head}\n${'-'.repeat(72)}\n${body}\n`
|
|
104
|
+
})
|
|
105
|
+
const source = [
|
|
106
|
+
'memhouse dashboard — third-party software included in this directory (public/)',
|
|
107
|
+
'',
|
|
108
|
+
'The built dashboard bundles the packages below. Each is listed with its version,',
|
|
109
|
+
'its declared license, and the license text it ships. Generated at build time by',
|
|
110
|
+
'ui/third-party-notices.js from the bundle\'s module graph.',
|
|
111
|
+
'',
|
|
112
|
+
`${list.length} packages.`,
|
|
113
|
+
'',
|
|
114
|
+
...blocks,
|
|
115
|
+
].join('\n')
|
|
116
|
+
this.emitFile({ type: 'asset', fileName, source })
|
|
117
|
+
},
|
|
118
|
+
}
|
|
119
|
+
}
|
package/ui/vite.config.js
CHANGED
|
@@ -12,10 +12,14 @@ export default defineConfig({
|
|
|
12
12
|
outDir: '../public',
|
|
13
13
|
emptyOutDir: true,
|
|
14
14
|
},
|
|
15
|
+
// The dev server proxies /api to the memhouse dashboard (127.0.0.1:MEMHOUSE_PORT, default 4640).
|
|
16
|
+
// The dashboard needs its token: open the dev server with the URL `memhouse dashboard` prints in
|
|
17
|
+
// a terminal, on this origin (http://localhost:5173/#token=…); the page sends it as a Bearer
|
|
18
|
+
// header, which this proxy passes on.
|
|
15
19
|
server: {
|
|
16
20
|
proxy: {
|
|
17
21
|
'/relay': 'http://localhost:4638',
|
|
18
|
-
'/api': process.env.RELAY ? 'http://localhost:4638' :
|
|
22
|
+
'/api': process.env.RELAY ? 'http://localhost:4638' : `http://127.0.0.1:${process.env.MEMHOUSE_PORT || 4640}`,
|
|
19
23
|
},
|
|
20
24
|
},
|
|
21
25
|
})
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
# memhouse 0.18.12 — 2026-10-29
|
|
2
|
-
|
|
3
|
-
A patch release on the 0.18 line. It does one thing for users:
|
|
4
|
-
|
|
5
|
-
- **The `/mem` skills pre-approve read-only commands only.** Each skill's `allowed-tools`
|
|
6
|
-
now lists the memhouse read commands it teaches, instead of `Bash` as a whole.
|
|
7
|
-
|
|
8
|
-
No drill was run for this patch release. Its one user-facing change is held by
|
|
9
|
-
`misc/skill-allowlist-test.js`, which runs in `npm test`.
|
|
10
|
-
|
|
11
|
-
## Upgrade
|
|
12
|
-
|
|
13
|
-
```bash
|
|
14
|
-
memhouse update # refreshes the /mem skills wherever they are installed
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Then reload the skills in Claude Code with `/reload-plugins`, or restart the session.
|
|
18
|
-
|
|
19
|
-
If you upgraded with `npm install -g memhouse` instead, run `memhouse plugins install claude`
|
|
20
|
-
once, so the installed skills match the package.
|
|
21
|
-
|
|
22
|
-
Nothing else changes: same house layout, same schema, same daemons.
|
|
23
|
-
|
|
24
|
-
## Changed
|
|
25
|
-
|
|
26
|
-
### Skills: allowed tools restricted to read-only commands
|
|
27
|
-
|
|
28
|
-
Each `/mem` skill's `allowed-tools` names the memhouse read commands it uses:
|
|
29
|
-
|
|
30
|
-
| skill | runs without a prompt |
|
|
31
|
-
|---|---|
|
|
32
|
-
| `/mem:house` | `memhouse instance`, `whoami`, `status`, `stats`, `doctor`, and `share --list` (with or without `--json`) |
|
|
33
|
-
| `/mem:recall` | `memhouse search`, `resume`, `sessions-query`, `status`, `whoami` |
|
|
34
|
-
| `/mem:sql` | `memhouse sessions-query`, `stats`, `status`, `whoami` |
|
|
35
|
-
| `/mem:access` | `memhouse whoami`, `status`, and `share --list` (with or without `--json`) |
|
|
36
|
-
| `/mem:admin` | `memhouse whoami`, `status`, `instance` |
|
|
37
|
-
|
|
38
|
-
Any other command goes through Claude Code's normal permission prompt, as does a read
|
|
39
|
-
command with another command chained to it. Expect a prompt where a skill used to run a
|
|
40
|
-
command without one; approve it as you would any other command.
|
|
41
|
-
|
|
42
|
-
## Repository and tests
|
|
43
|
-
|
|
44
|
-
These do not change the installed package's behaviour:
|
|
45
|
-
|
|
46
|
-
- `misc/skill-allowlist-test.js` keeps every skill's `allowed-tools` to read-only memhouse
|
|
47
|
-
commands. It joins `npm test`.
|
|
48
|
-
- The test tooling's deploy targets (lab address, test machine, engine checkout) are read
|
|
49
|
-
from an untracked `deploy/targets.env`. `deploy/targets.example.env` shows the shape.
|
|
50
|
-
- Test fixtures, examples, drill records and docs use stand-in names, hosts and paths.
|
|
51
|
-
`misc/env-guard-test.js` checks tracked files for real environment values, and it joins
|
|
52
|
-
`npm test`.
|
|
53
|
-
- Security reports go through GitHub's private vulnerability reporting (`SECURITY.md`).
|
|
54
|
-
- The 0.18 line is now cut from the `release/0.18` branch. `AGENTS.md` and
|
|
55
|
-
`misc/publish-guard.js` say so.
|
|
56
|
-
|
|
57
|
-
## Deferred
|
|
58
|
-
|
|
59
|
-
Nothing new. Later work ships on the current line's next release.
|
package/memhouse/COMPETITION.md
DELETED
|
@@ -1,221 +0,0 @@
|
|
|
1
|
-
# memhouse — the competition
|
|
2
|
-
|
|
3
|
-
Companion to `DESIGN.md`. That file states **the four bets**; this one grades each
|
|
4
|
-
bet against the field as it actually stands.
|
|
5
|
-
|
|
6
|
-
**Surveyed 2026-08-07.** Every star/fork/date figure was pulled from the GitHub API
|
|
7
|
-
on that date and is a decaying fact — re-run before citing. Claims that could not be
|
|
8
|
-
verified are marked *unverified* rather than asserted. X/Twitter was not reachable
|
|
9
|
-
(HTTP 402 to the fetch tool), so nothing here reflects it.
|
|
10
|
-
|
|
11
|
-
The finding, in one line: **three of the four bets are already occupied by shipping
|
|
12
|
-
competitors, most of them free and further along. Bet 3 is the one that holds.**
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## The field splits four ways
|
|
17
|
-
|
|
18
|
-
The space shares vocabulary but not architecture. Distinguishing the camps is the
|
|
19
|
-
whole analysis, because most "agent memory" products are not competitors at all.
|
|
20
|
-
|
|
21
|
-
| Camp | What it means | Where memory comes from | Competes with us? |
|
|
22
|
-
|---|---|---|---|
|
|
23
|
-
| **Transcript readers** | Index the JSONL/SQLite stores the agents already wrote | Passive — reads disk | **Yes, directly** |
|
|
24
|
-
| **Hook capturers** | Install lifecycle hooks, compress with an LLM, re-inject | Passive, but must live inside the agent | Yes, on the same users |
|
|
25
|
-
| **Memory SDKs** | Developer calls `add()` / `search()` | Active — the developer writes it | No — different product |
|
|
26
|
-
| **Observability** | OTel/proxy traces of model calls | Passive, at the API layer | Only on analytics |
|
|
27
|
-
|
|
28
|
-
memhouse is a transcript reader with the observability camp's analytics attached.
|
|
29
|
-
That combination is the most defensible thing about the product's *shape*; the
|
|
30
|
-
individual pieces are not scarce.
|
|
31
|
-
|
|
32
|
-
---
|
|
33
|
-
|
|
34
|
-
## The four bets, graded
|
|
35
|
-
|
|
36
|
-
### Bet 1 — Parse on the client. **Occupied. Not differentiated.**
|
|
37
|
-
|
|
38
|
-
The reasoning in `DESIGN.md` is sound and the conclusion is correct — sqlite-backed
|
|
39
|
-
editors do force client-side parsing. But it is no longer a distinguishing choice.
|
|
40
|
-
At least five projects crack the same on-disk stores today, and one of them cracks
|
|
41
|
-
formats we do not touch (encrypted Protobuf sidecars for Antigravity CLI, Markdown
|
|
42
|
-
for aider).
|
|
43
|
-
|
|
44
|
-
Editor coverage — the number we lead the README with — is mid-pack:
|
|
45
|
-
|
|
46
|
-
| Project | Editors | Note |
|
|
47
|
-
|---|---:|---|
|
|
48
|
-
| AgentsView | **50+** | each with documented on-disk paths |
|
|
49
|
-
| lean-ctx | 30+ | claimed |
|
|
50
|
-
| CCHV | 28 | each with documented paths |
|
|
51
|
-
| **memhouse** | **17** | |
|
|
52
|
-
| deja-vu | 17 | different 17 — has Cline, aider, Qwen Code, Kimi Code, Roo Code |
|
|
53
|
-
| coding_agent_session_search | 11+ | |
|
|
54
|
-
| ctx | 8 | |
|
|
55
|
-
| Conare | 7 | |
|
|
56
|
-
| Contextify | 2 | Claude Code + Codex CLI only |
|
|
57
|
-
|
|
58
|
-
deja-vu's tagline is our pitch verbatim: *"it indexes the sessions your coding agents
|
|
59
|
-
already wrote to disk, months of history from before you installed it, across
|
|
60
|
-
seventeen harnesses."*
|
|
61
|
-
|
|
62
|
-
### Bet 2 — Typed common schema. **Occupied on outcome, distinct on method.**
|
|
63
|
-
|
|
64
|
-
Everyone arrives at structured storage; the axis that still separates us is **when
|
|
65
|
-
the extraction happens and what survives it**.
|
|
66
|
-
|
|
67
|
-
- **SQLite + FTS5 is the category default**, reached independently by AgentsView,
|
|
68
|
-
Agent Sessions, claude-code-chat-explorer, claude-mem, ccrecall and mnemo.
|
|
69
|
-
- **ClickHouse for editor transcripts is unclaimed.** The only other ClickHouse-based
|
|
70
|
-
agent memory found is `clickmem` (57 stars) and it is embedded chDB, single-user,
|
|
71
|
-
so it inherits none of the multi-member properties. Langfuse is ClickHouse-backed,
|
|
72
|
-
MIT and self-hostable — but ingests API traces, not editor stores.
|
|
73
|
-
- **Verbatim-with-no-LLM-on-the-write-path has one serious co-traveller**:
|
|
74
|
-
MemPalace (58k stars in four months) sells exactly that — *"verbatim storage,
|
|
75
|
-
zero API calls."* We are not alone on this axis, but the company is good.
|
|
76
|
-
|
|
77
|
-
Honest caveat: at single-team scale SQLite demonstrably suffices. ClickHouse is a
|
|
78
|
-
bet on a scale we have not yet had to prove.
|
|
79
|
-
|
|
80
|
-
### Bet 3 — Kernel-installable agency, own-only by absent grant. **This one holds.**
|
|
81
|
-
|
|
82
|
-
This is the finding worth acting on. Every competitor's multi-user story is a
|
|
83
|
-
**shared pool** or **metadata scoping**. Not one enforces isolation at the
|
|
84
|
-
datastore's own permission layer.
|
|
85
|
-
|
|
86
|
-
| Product | Team mechanism | Isolation |
|
|
87
|
-
|---|---|---|
|
|
88
|
-
| AgentsView | `pg push` / `pg serve` to shared PostgreSQL | **None.** Connection string is the whole boundary; `machine_name` is a label, not a fence |
|
|
89
|
-
| memsearch (Zilliz) | Docker + shared Milvus, documented "for team environments" | **None documented** — no RBAC, no per-user namespacing |
|
|
90
|
-
| mem0 | `user_id` + `agent_id` + `run_id` filters | Metadata filtering, not enforcement |
|
|
91
|
-
| Industry pattern | `tenant_id` column + row-level security | Policy layer, revocable by whoever owns the policy |
|
|
92
|
-
| Contextify | Cloud workspace, per-project opt-in | Real, but proprietary, cloud-first, 2 editors |
|
|
93
|
-
| **memhouse** | three `GRANT SELECT` on the member's own rooms | **A member cannot name another member's rooms.** `WITH GRANT OPTION` on `SELECT` and not on `ALL` makes sharing read-only by construction and operator-free |
|
|
94
|
-
|
|
95
|
-
Bet 3 is not a niche preference. It is a category-wide blind spot, and it is the
|
|
96
|
-
only thing in this document that nobody else is attempting.
|
|
97
|
-
|
|
98
|
-
### Bet 4 — Borrowed UI, zero fork. **Occupied. Not differentiated.**
|
|
99
|
-
|
|
100
|
-
Analytics over the same files is a crowded, mature niche: ccusage (17.8k stars),
|
|
101
|
-
CodexBar (19.8k). Agent Sessions beats us on the analytics *idea* with a per-session
|
|
102
|
-
"Quota Meter / Session Runway" priced per model against 5-hour and weekly windows.
|
|
103
|
-
AgentsView ships cache-aware, LiteLLM-priced cost reporting plus a REST usage API.
|
|
104
|
-
|
|
105
|
-
Zero-fork was the right call for build cost. It buys no position.
|
|
106
|
-
|
|
107
|
-
---
|
|
108
|
-
|
|
109
|
-
## The field, ranked by how directly it competes
|
|
110
|
-
|
|
111
|
-
| # | Project | What it is | Source | Store | Team | Editors | Licence | Signal (2026-08-07) |
|
|
112
|
-
|---|---|---|---|---|---|---:|---|---|
|
|
113
|
-
| 1 | **AgentsView** | Go binary + Tauri app + Docker image | reads disk | SQLite/FTS5, opt. DuckDB, opt. **PostgreSQL** | shared pool, free | 50+ | MIT | **4,723★**, 574 forks, 100 contributors, six months old, MCP server, semantic search |
|
|
114
|
-
| 2 | **claude-mem** | npm plugin + MCP + web viewer | **hooks** | SQLite + Chroma, opt. cloud | none | ~8 | Apache-2.0 | **89,967★**, 7,831 forks, **62,940 npm dl/mo**. The category's centre of gravity |
|
|
115
|
-
| 3 | **MemPalace** | local-first memory, verbatim | mixed, mining transcripts | pluggable | none | — | MIT | **58,182★ in four months**, 696 open issues, contested benchmarks |
|
|
116
|
-
| 4 | **deja-vu** | zero-dep Go binary, CLI + MCP + hook | reads disk | `records.bin`, no server | none — personal SSH sync | 17 | MIT | 593★, HN 131 pts, redacts secrets at index |
|
|
117
|
-
| 5 | **Contextify** | macOS app + CLI, cloud **and** self-hosted | reads disk | local + optional cloud | **real**: seats, roles, per-project opt-in | 2 | proprietary / FSL | $8–15/seat/mo; self-host $132/seat/yr |
|
|
118
|
-
| 6 | **ctx** | Rust CLI, event-level provenance | reads disk | local SQLite | **ctx cloud**, hosted, private beta | 8 | Apache-2.0 | 1,013★ |
|
|
119
|
-
| 7 | **SpecStory** | IDE extensions + CLI | **writes its own** | local + cloud | team rollups | 9 | Apache-2.0 | 1,296★; **Team $300/mo**; "Lore" mines history into installable skills |
|
|
120
|
-
| 8 | **Conare** | CLI + hosted, MCP | reads disk | vendor cloud | shared memory, audit logs, SSO | 7 | proprietary | **Team $500/mo** |
|
|
121
|
-
| 9 | **memsearch** | Markdown + Milvus shadow index | Stop hooks | Markdown truth + Milvus | Docker, no isolation | 4 | MIT | 2,431★, Zilliz-backed |
|
|
122
|
-
| 10 | **CCHV** | Tauri app + **headless server** | reads disk | provider files + cache | server mode w/ accounts | 28 | MIT | 2,020★, 45 contributors |
|
|
123
|
-
| 11 | **Agent Sessions** | native macOS app | reads disk | SQLite/FTS5 | none | 10 | MIT | 762★; best-in-class quota metering; resume + write-back restore |
|
|
124
|
-
| 12 | **ContextPool** | CLI + MCP | reads disk | local + repo dir | shared pool, $7.99/mo | 4 | mixed | 188 PH upvotes |
|
|
125
|
-
|
|
126
|
-
Adjacent and **not** competitors, but they own the vocabulary and the capital:
|
|
127
|
-
mem0 (62.8k★, $24M), cognee (29.8k★), graphiti (29.6k★), supermemory (28.8k★),
|
|
128
|
-
letta (24.1k★, $10M seed), memori (15.7k★), OpenViking (28.1k★, ByteDance),
|
|
129
|
-
Hindsight (19.2k★, $3.6M seed). All of them require the developer to write the
|
|
130
|
-
memory. None ingest agent sessions.
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
## What they do better
|
|
135
|
-
|
|
136
|
-
- **Distribution.** memhouse: 0 stars, 655 npm downloads/month, no HN or search
|
|
137
|
-
presence. claude-mem: 89,967 stars and 62,940 downloads/month, free, no company.
|
|
138
|
-
This dominates every other consideration in the document.
|
|
139
|
-
- **Automatic recall.** deja-vu installs a SessionStart hook; claude-mem injects into
|
|
140
|
-
future sessions; ContextPool loads at session start; SpecStory converts history
|
|
141
|
-
into *installed skills*. Our skills must be chosen. One independent analysis of 270
|
|
142
|
-
real sessions found **only 4.8% involved an explicit history query** — a pull-only
|
|
143
|
-
model gets invoked rarely.
|
|
144
|
-
- **Install weight — still the heaviest in the category, but half the tax is paid.**
|
|
145
|
-
AgentsView, deja-vu and ctx are single dependency-free binaries via Homebrew, Docker,
|
|
146
|
-
`go install` or curl. We are Node and need a ClickHouse to point at.
|
|
147
|
-
**Resolved 2026-08-16:** the native-dependency half is gone. `better-sqlite3` was
|
|
148
|
-
replaced by `node:sqlite`, so `npm i -g memhouse` with no flags is now a complete,
|
|
149
|
-
fully working install — no `--allow-scripts`, no build step, and no five-adapters-
|
|
150
|
-
silently-read-nothing failure mode. What remains of the tax is the runtime (Node,
|
|
151
|
-
not a static binary), the ClickHouse dependency, and the `EACCES`/`sudo` prefix
|
|
152
|
-
triage, which was never about the flag and is not fixable from our side.
|
|
153
|
-
- **Semantic search.** AgentsView (opt-in index), claude-mem (Chroma),
|
|
154
|
-
claude-history (local embedding model). We are FTS-only. Contested rather than
|
|
155
|
-
settled — deja-vu made the same choice and was criticised for it on HN.
|
|
156
|
-
- **Secret redaction at ingest.** deja-vu redacts credential patterns on index *and*
|
|
157
|
-
on sync export. Whether we do is *unverified* — and it matters more here than
|
|
158
|
-
elsewhere, because Claude Code caches unredacted secrets in transcripts
|
|
159
|
-
(anthropics/claude-code#43675) and we ship those rows to a shared server.
|
|
160
|
-
- **Resume and write-back.** Agent Sessions copies resume commands for six CLIs and
|
|
161
|
-
restores into the archive; claude-history resumes *and forks* worktree-aware. We
|
|
162
|
-
read but do not hand the pilot back in.
|
|
163
|
-
- **Price ceiling.** AgentsView gives the whole stack away under MIT. That caps what
|
|
164
|
-
a self-hosted OSS competitor can charge for.
|
|
165
|
-
|
|
166
|
-
---
|
|
167
|
-
|
|
168
|
-
## Unclaimed ground
|
|
169
|
-
|
|
170
|
-
Two positions nobody occupies, both reachable from where we already are.
|
|
171
|
-
|
|
172
|
-
**1. Evidence and claims as two layers.** The sharpest architectural critique found
|
|
173
|
-
anywhere in the survey, and no product in the field claims to do it: keep the capture
|
|
174
|
-
log and the memory layer distinct. The capture log is chronological evidence; memory
|
|
175
|
-
is a set of derived, revisable claims. Each claim cites the exact spans supporting
|
|
176
|
-
it, records when it was inferred, and marks itself current, disputed or superseded —
|
|
177
|
-
and deletion follows that lineage. This is available **only** to a system that keeps
|
|
178
|
-
verbatim transcripts with provenance. Every extract-only competitor has discarded the
|
|
179
|
-
evidence by the time the claim is written. We and MemPalace are the two systems
|
|
180
|
-
positioned to build it. Neither has.
|
|
181
|
-
|
|
182
|
-
**2. The 30-day deletion window.** Claude Code deletes JSONL transcripts after 30
|
|
183
|
-
days. Contextify was built because of it; vibe-replay documents it; **nobody markets
|
|
184
|
-
on it.** A durable server-side store is the strongest possible answer, and we are
|
|
185
|
-
better positioned than any local-index tool. This is free ground.
|
|
186
|
-
|
|
187
|
-
---
|
|
188
|
-
|
|
189
|
-
## Three cautions
|
|
190
|
-
|
|
191
|
-
**Do not compete on benchmark scores.** The benchmarks are broken. An independent
|
|
192
|
-
LOCOMO audit found 99 score-corrupting errors in 1,540 questions (6.4%), and the
|
|
193
|
-
standard LLM judge accepted 62.81% of adversarially-generated wrong-but-topical
|
|
194
|
-
answers. Nine vendors claim mutually incompatible SOTA on it. MemPalace's claimed
|
|
195
|
-
100% was reverse-engineered publicly to 98.4%, achieved with `top-k=50` — which
|
|
196
|
-
exceeds the session count. deja-vu's 84.9% hit@1 carries the same asterisk. Entering
|
|
197
|
-
this contest means measuring the field against itself.
|
|
198
|
-
|
|
199
|
-
**Stars are not traction, and are farmed in this category.** `mindverse/Second-Me`
|
|
200
|
-
holds 15,648 stars and has been dead for ten months. MemPalace took 58k stars in four
|
|
201
|
-
months while accumulating 2,183 issues, one titled *"in short: This sucks shit."*
|
|
202
|
-
Screenpipe reportedly mails its stargazers.
|
|
203
|
-
|
|
204
|
-
**The free incumbent sets the floor.** claude-mem is Apache-2.0, free, no cloud tier,
|
|
205
|
-
no company, one dominant author. Any paid or heavier-install offering is measured
|
|
206
|
-
against that baseline, not against a vendor's price list.
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
## Net position
|
|
211
|
-
|
|
212
|
-
Not differentiated on parse-on-client, editor breadth, self-hosting, analytics, or
|
|
213
|
-
agent-facing skills — all matched or beaten, most comprehensively by AgentsView
|
|
214
|
-
(MIT, free, 50+ editors, 4,723 stars, six months old).
|
|
215
|
-
|
|
216
|
-
Two things hold: **grant-enforced per-member isolation**, which nobody attempts, and
|
|
217
|
-
**verbatim transcripts with provenance**, which is the prerequisite for the
|
|
218
|
-
evidence/claims separation the field has identified but not built.
|
|
219
|
-
|
|
220
|
-
The liabilities are zero distribution and the heaviest install in the category.
|
|
221
|
-
Both are fixable; neither is fixed by adding another editor adapter.
|