digital-brain 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.
- package/LICENSE +21 -0
- package/README.md +113 -0
- package/bin/digital-brain.js +209 -0
- package/docs/AUTOMATIONS.md +70 -0
- package/docs/PRIVACY.md +17 -0
- package/docs/ROADMAP.md +9 -0
- package/examples/sample-vault/04 People/Interpreted Relationships/Close Friend.md +29 -0
- package/examples/sample-vault/04 People/Interpreted Relationships/Mom.md +30 -0
- package/examples/sample-vault/04 People/Interpreted Relationships/Project Team.md +30 -0
- package/examples/sample-vault/06 AI Memory/Interpreted Relationship Memory.md +7 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Analysis/Interpreted/Close Friend.md +29 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Analysis/Interpreted/Mom.md +30 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Analysis/Interpreted/Project Team.md +30 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Analysis/Relationship Map.md +29 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Analysis/interpreted_relationship_models.json +109 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Analysis/relationship_profiles.json +68 -0
- package/examples/sample-vault/08 Sources/WhatsApp/Raw/2026-01-01.jsonl +6 -0
- package/examples/sample-vault/08 Sources/WhatsApp/relationship_overrides.json +7 -0
- package/lib/fs.js +32 -0
- package/package.json +43 -0
- package/scripts/digital_brain_relationship_extractor.py +165 -0
- package/scripts/digital_brain_relationship_interpreter.py +196 -0
- package/scripts/digital_brain_whatsapp_mac_sync.py +153 -0
- package/templates/vault/00 Home/How AI Should Use This Vault.md +11 -0
- package/templates/vault/00 Home/Start Here.md +11 -0
- package/templates/vault/01 Identity/Working Profile.md +11 -0
- package/templates/vault/04 People/Relationship Overrides.md +16 -0
- package/templates/vault/06 AI Memory/Interpreted Relationship Memory.md +4 -0
- package/templates/vault/06 AI Memory/What AI Should Remember.md +4 -0
- package/templates/vault/08 Sources/WhatsApp/Outbound/README.md +20 -0
- package/templates/vault/08 Sources/WhatsApp/relationship_overrides.example.json +8 -0
- package/templates/vault/AGENTS.md +19 -0
- package/templates/vault/CLAUDE.md +6 -0
- package/templates/vault/GEMINI.md +5 -0
- package/whatsapp-web/send.mjs +139 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rushill Shah
|
|
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,113 @@
|
|
|
1
|
+
# Digital Brain
|
|
2
|
+
|
|
3
|
+
Your private digital imprint for AI.
|
|
4
|
+
|
|
5
|
+
Digital Brain turns your local notes and message history into an editable memory vault that AI assistants can use to understand your people, patterns, tone, and context.
|
|
6
|
+
|
|
7
|
+
It is not a chatbot. It is not a cloud memory service. It is the local context layer that makes your existing AI tools feel less generic.
|
|
8
|
+
|
|
9
|
+
## Why
|
|
10
|
+
|
|
11
|
+
AI tools are powerful, but they usually start every personal question cold.
|
|
12
|
+
|
|
13
|
+
Digital Brain gives them a structured, local map of:
|
|
14
|
+
|
|
15
|
+
- who matters in your life
|
|
16
|
+
- how you communicate with different people
|
|
17
|
+
- which relationships are warm, operational, difficult, or high-context
|
|
18
|
+
- what tone to use when drafting replies
|
|
19
|
+
- what not to assume
|
|
20
|
+
|
|
21
|
+
## Install
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npx digital-brain init
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The installer asks a short setup quiz: history window, primary focus, refresh cadence, active time window, outbound mode, and AI adapter setup.
|
|
28
|
+
|
|
29
|
+
For local development:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npm install
|
|
33
|
+
node ./bin/digital-brain.js init ./Digital Brain\ Vault
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
## What It Creates
|
|
37
|
+
|
|
38
|
+
- An Obsidian-friendly Markdown vault.
|
|
39
|
+
- AI adapter files for Codex, Claude, and Gemini.
|
|
40
|
+
- WhatsApp Mac import tools.
|
|
41
|
+
- Relationship extraction and interpretation models.
|
|
42
|
+
- Optional WhatsApp Web outbound sender.
|
|
43
|
+
- A refresh script based on your install-time answers.
|
|
44
|
+
|
|
45
|
+
## What It Can Do
|
|
46
|
+
|
|
47
|
+
- Import recent WhatsApp history from the local macOS WhatsApp database.
|
|
48
|
+
- Build relationship profiles from message patterns.
|
|
49
|
+
- Infer provisional roles like parent, family group, work collaborator, close personal contact, or unlabeled contact.
|
|
50
|
+
- Generate "how to continue this relationship" notes.
|
|
51
|
+
- Create AI-readable memory files for future prompts.
|
|
52
|
+
- Draft WhatsApp sends by default, and only send with explicit `--yes`.
|
|
53
|
+
- Enforce an AI-disclosure guard after repeated AI-assisted sends.
|
|
54
|
+
|
|
55
|
+
## Core Commands
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
digital-brain init ./Digital Brain\ Vault
|
|
59
|
+
digital-brain sync-whatsapp --vault ./Digital Brain\ Vault --days 30
|
|
60
|
+
digital-brain extract --vault ./Digital Brain\ Vault --days 30
|
|
61
|
+
digital-brain interpret --vault ./Digital Brain\ Vault --days 30
|
|
62
|
+
digital-brain send-whatsapp --vault ./Digital Brain\ Vault --to "Name" --message "text"
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The sender drafts by default. Add `--yes` to actually send.
|
|
66
|
+
|
|
67
|
+
If Digital Brain has already sent two AI-assisted messages to the same chat in the last 24 hours, the next send must disclose that AI is helping unless you explicitly bypass the check.
|
|
68
|
+
|
|
69
|
+
## Automation
|
|
70
|
+
|
|
71
|
+
Each vault gets:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
Tools/digital-brain-refresh.sh
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Use it with Codex automations, local cron, launchd, or another scheduler. See [docs/AUTOMATIONS.md](docs/AUTOMATIONS.md).
|
|
78
|
+
|
|
79
|
+
## Example
|
|
80
|
+
|
|
81
|
+
Before Digital Brain:
|
|
82
|
+
|
|
83
|
+
> Help me reply to my mom.
|
|
84
|
+
|
|
85
|
+
Generic AI gives generic advice.
|
|
86
|
+
|
|
87
|
+
After Digital Brain:
|
|
88
|
+
|
|
89
|
+
> Help me reply to my mom.
|
|
90
|
+
|
|
91
|
+
Your AI can use local context: this person is your mother, the tone should be warm, the thread may be logistical, and the reply should not sound like a work update.
|
|
92
|
+
|
|
93
|
+
## Try Fake Data
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
npm run test:sample
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
This uses fake WhatsApp-style messages in `examples/sample-vault`.
|
|
100
|
+
|
|
101
|
+
## Privacy
|
|
102
|
+
|
|
103
|
+
Digital Brain is local-first. It does not upload messages or notes.
|
|
104
|
+
|
|
105
|
+
WhatsApp support reads the local macOS WhatsApp database when available. This is experimental and unofficial. Outbound messaging uses WhatsApp Web through `whatsapp-web.js`.
|
|
106
|
+
|
|
107
|
+
Relationship labels are working notes, not truth. You can edit them with `relationship_overrides.json`.
|
|
108
|
+
|
|
109
|
+
## Status
|
|
110
|
+
|
|
111
|
+
Alpha. Expect rough edges.
|
|
112
|
+
|
|
113
|
+
Do not use this for regulated, emergency, legal, medical, or safety-critical communication.
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import readline from "node:readline/promises";
|
|
7
|
+
import { fileURLToPath } from "node:url";
|
|
8
|
+
import { copyDir, ensureDir, packageRoot, resolveVault } from "../lib/fs.js";
|
|
9
|
+
|
|
10
|
+
const root = packageRoot(import.meta.url);
|
|
11
|
+
|
|
12
|
+
main().catch((error) => {
|
|
13
|
+
console.error(error.message);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
async function main() {
|
|
18
|
+
const [command = "help", ...argv] = process.argv.slice(2);
|
|
19
|
+
const args = parseArgs(argv);
|
|
20
|
+
|
|
21
|
+
if (command === "init") await init(argv, args);
|
|
22
|
+
else if (command === "doctor") doctor();
|
|
23
|
+
else if (command === "sync-whatsapp") runPython("digital_brain_whatsapp_mac_sync.py", argv);
|
|
24
|
+
else if (command === "extract") runPython("digital_brain_relationship_extractor.py", argv);
|
|
25
|
+
else if (command === "interpret") runPython("digital_brain_relationship_interpreter.py", argv);
|
|
26
|
+
else if (command === "send-whatsapp") runNode("whatsapp-web/send.mjs", argv);
|
|
27
|
+
else help();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async function init(argv, args) {
|
|
31
|
+
const positional = argv.filter((arg) => !arg.startsWith("--"));
|
|
32
|
+
const defaultVault = path.resolve(process.cwd(), "Digital Brain Vault");
|
|
33
|
+
let vault = positional[0] ? path.resolve(positional[0]) : args.yes ? defaultVault : "";
|
|
34
|
+
let selfName = args["self-name"] || "";
|
|
35
|
+
let connectAi = toBoolean(args["connect-ai"]);
|
|
36
|
+
let dataWindowDays = Number(args["data-window-days"] || 30);
|
|
37
|
+
let focus = args.focus || "";
|
|
38
|
+
let schedule = args.schedule || "manual";
|
|
39
|
+
let activeWindow = args["active-window"] || "08:00-12:00";
|
|
40
|
+
let timezone = args.timezone || Intl.DateTimeFormat().resolvedOptions().timeZone || "local";
|
|
41
|
+
let outboundMode = args["outbound-mode"] || "draft";
|
|
42
|
+
|
|
43
|
+
if (!args.yes) {
|
|
44
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
45
|
+
vault ||= path.resolve(await ask(rl, "Vault path", defaultVault));
|
|
46
|
+
selfName ||= await ask(rl, "Your name", "Me");
|
|
47
|
+
dataWindowDays = Number(await ask(rl, "How much history should Digital Brain import by default? Days", String(dataWindowDays)));
|
|
48
|
+
focus ||= await ask(rl, "What should it optimize for? relationship-memory / reply-help / work-context", "relationship-memory");
|
|
49
|
+
schedule = await ask(rl, "How often should refresh guidance run? manual / hourly / every-30-min / daily", schedule);
|
|
50
|
+
activeWindow = await ask(rl, "Active window for frequent refreshes", activeWindow);
|
|
51
|
+
outboundMode = await ask(rl, "WhatsApp outbound mode? disabled / draft / send-with-confirmation", outboundMode);
|
|
52
|
+
connectAi = /^y/i.test(await ask(rl, "Add global AI pointers for Codex/Claude/Gemini?", "y"));
|
|
53
|
+
rl.close();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
ensureDir(vault);
|
|
57
|
+
copyDir(path.join(root, "templates", "vault"), vault);
|
|
58
|
+
const config = {
|
|
59
|
+
selfName: selfName || "Me",
|
|
60
|
+
dataWindowDays,
|
|
61
|
+
focus: focus || "relationship-memory",
|
|
62
|
+
schedule,
|
|
63
|
+
activeWindow,
|
|
64
|
+
timezone,
|
|
65
|
+
outboundMode,
|
|
66
|
+
disclosureRule: {
|
|
67
|
+
enabled: true,
|
|
68
|
+
discloseAfterAiAssistedSends: 2,
|
|
69
|
+
windowHours: 24,
|
|
70
|
+
},
|
|
71
|
+
};
|
|
72
|
+
writeConfig(vault, config);
|
|
73
|
+
writeRefreshScript(vault, config);
|
|
74
|
+
|
|
75
|
+
if (connectAi) {
|
|
76
|
+
addGlobalPointer(path.join(os.homedir(), ".codex", "AGENTS.md"), vault, "Codex");
|
|
77
|
+
addGlobalPointer(path.join(os.homedir(), ".claude", "CLAUDE.md"), vault, "Claude");
|
|
78
|
+
addGlobalPointer(path.join(os.homedir(), ".gemini", "GEMINI.md"), vault, "Gemini");
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
console.log(`Digital Brain vault created: ${vault}`);
|
|
82
|
+
console.log(`Config: ${path.join(vault, "digital-brain.config.json")}`);
|
|
83
|
+
console.log(`Refresh script: ${path.join(vault, "Tools", "digital-brain-refresh.sh")}`);
|
|
84
|
+
console.log("Next:");
|
|
85
|
+
console.log(` digital-brain sync-whatsapp --vault "${vault}" --days ${dataWindowDays}`);
|
|
86
|
+
console.log(` digital-brain extract --vault "${vault}" --days ${dataWindowDays}`);
|
|
87
|
+
console.log(` digital-brain interpret --vault "${vault}" --days ${dataWindowDays}`);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function doctor() {
|
|
91
|
+
const checks = [
|
|
92
|
+
["node", process.version],
|
|
93
|
+
["python3", shell("python3", ["--version"])],
|
|
94
|
+
["sqlite3", shell("sqlite3", ["--version"])],
|
|
95
|
+
["ollama", shell("ollama", ["--version"], true)],
|
|
96
|
+
];
|
|
97
|
+
for (const [name, value] of checks) {
|
|
98
|
+
console.log(`${name}: ${value || "not found"}`);
|
|
99
|
+
}
|
|
100
|
+
const macDb = path.join(os.homedir(), "Library/Group Containers/group.net.whatsapp.WhatsApp.shared/ChatStorage.sqlite");
|
|
101
|
+
console.log(`WhatsApp Mac DB: ${fs.existsSync(macDb) ? macDb : "not found"}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function runPython(script, argv) {
|
|
105
|
+
const resolved = withVault(argv);
|
|
106
|
+
const result = spawnSync("python3", [path.join(root, "scripts", script), ...resolved], { stdio: "inherit" });
|
|
107
|
+
process.exit(result.status ?? 1);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function runNode(script, argv) {
|
|
111
|
+
const result = spawnSync(process.execPath, [path.join(root, script), ...argv], { stdio: "inherit" });
|
|
112
|
+
process.exit(result.status ?? 1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function withVault(argv) {
|
|
116
|
+
if (argv.includes("--vault") || argv.some((arg) => arg.startsWith("--vault="))) return argv;
|
|
117
|
+
return ["--vault", resolveVault(process.cwd()), ...argv];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function writeConfig(vault, config) {
|
|
121
|
+
fs.writeFileSync(path.join(vault, "digital-brain.config.json"), `${JSON.stringify(config, null, 2)}\n`);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function writeRefreshScript(vault, config) {
|
|
125
|
+
const toolsDir = path.join(vault, "Tools");
|
|
126
|
+
ensureDir(toolsDir);
|
|
127
|
+
const days = Number(config.dataWindowDays || 30);
|
|
128
|
+
const content = `#!/usr/bin/env bash
|
|
129
|
+
set -euo pipefail
|
|
130
|
+
|
|
131
|
+
VAULT="${vault.replace(/"/g, '\\"')}"
|
|
132
|
+
DAYS="${days}"
|
|
133
|
+
|
|
134
|
+
digital-brain sync-whatsapp --vault "$VAULT" --days "$DAYS" --markdown-mode month
|
|
135
|
+
digital-brain extract --vault "$VAULT" --days "$DAYS"
|
|
136
|
+
digital-brain interpret --vault "$VAULT" --days "$DAYS"
|
|
137
|
+
|
|
138
|
+
echo "Digital Brain refresh complete for $VAULT"
|
|
139
|
+
`;
|
|
140
|
+
const scriptPath = path.join(toolsDir, "digital-brain-refresh.sh");
|
|
141
|
+
fs.writeFileSync(scriptPath, content);
|
|
142
|
+
fs.chmodSync(scriptPath, 0o755);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function addGlobalPointer(file, vault, label) {
|
|
146
|
+
ensureDir(path.dirname(file));
|
|
147
|
+
const block = `
|
|
148
|
+
|
|
149
|
+
# Digital Brain
|
|
150
|
+
|
|
151
|
+
Digital Brain vault:
|
|
152
|
+
|
|
153
|
+
\`${vault}\`
|
|
154
|
+
|
|
155
|
+
Use it as local personal context when the user asks about preferences, relationships, communication style, or recurring context. Treat generated relationship notes as provisional.
|
|
156
|
+
`;
|
|
157
|
+
const existing = fs.existsSync(file) ? fs.readFileSync(file, "utf8") : "";
|
|
158
|
+
if (!existing.includes(vault)) fs.appendFileSync(file, block);
|
|
159
|
+
console.log(`${label} pointer: ${file}`);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async function ask(rl, label, fallback) {
|
|
163
|
+
const answer = await rl.question(`${label} (${fallback}): `);
|
|
164
|
+
return answer.trim() || fallback;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function shell(command, args, optional = false) {
|
|
168
|
+
const result = spawnSync(command, args, { encoding: "utf8" });
|
|
169
|
+
if (result.error && optional) return "";
|
|
170
|
+
if (result.error) return "not found";
|
|
171
|
+
return (result.stdout || result.stderr).trim().split("\n")[0];
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function parseArgs(argv) {
|
|
175
|
+
const out = {};
|
|
176
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
177
|
+
const arg = argv[i];
|
|
178
|
+
if (!arg.startsWith("--")) continue;
|
|
179
|
+
const key = arg.slice(2);
|
|
180
|
+
if (key.includes("=")) {
|
|
181
|
+
const [k, ...rest] = key.split("=");
|
|
182
|
+
out[k] = rest.join("=");
|
|
183
|
+
} else {
|
|
184
|
+
const next = argv[i + 1];
|
|
185
|
+
if (!next || next.startsWith("--")) out[key] = true;
|
|
186
|
+
else out[key] = argv[++i];
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
return out;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function toBoolean(value) {
|
|
193
|
+
if (value === undefined) return false;
|
|
194
|
+
if (value === true) return true;
|
|
195
|
+
return !["false", "0", "no", "off"].includes(String(value).toLowerCase());
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function help() {
|
|
199
|
+
console.log(`Digital Brain
|
|
200
|
+
|
|
201
|
+
Usage:
|
|
202
|
+
digital-brain init [vault]
|
|
203
|
+
digital-brain doctor
|
|
204
|
+
digital-brain sync-whatsapp --vault <path> --days 30
|
|
205
|
+
digital-brain extract --vault <path> --days 30
|
|
206
|
+
digital-brain interpret --vault <path> --days 30
|
|
207
|
+
digital-brain send-whatsapp --vault <path> --to "Name" --message "Text" [--yes]
|
|
208
|
+
`);
|
|
209
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Automations
|
|
2
|
+
|
|
3
|
+
Digital Brain can run manually, on your machine, or through an AI/workspace automation system.
|
|
4
|
+
|
|
5
|
+
The generated vault includes:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
Tools/digital-brain-refresh.sh
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
That script runs sync, extract, and interpret using the install-time config.
|
|
12
|
+
|
|
13
|
+
## Configurable At Install
|
|
14
|
+
|
|
15
|
+
`digital-brain init` asks:
|
|
16
|
+
|
|
17
|
+
- vault path
|
|
18
|
+
- your name
|
|
19
|
+
- history window in days
|
|
20
|
+
- primary focus: relationship memory, reply help, work context
|
|
21
|
+
- refresh cadence
|
|
22
|
+
- active time window
|
|
23
|
+
- WhatsApp outbound mode
|
|
24
|
+
- whether to add AI adapter pointers
|
|
25
|
+
|
|
26
|
+
The answers are saved in:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
digital-brain.config.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Codex App
|
|
33
|
+
|
|
34
|
+
Use a Codex cron automation pointed at the generated vault.
|
|
35
|
+
|
|
36
|
+
Prompt:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
Run `Tools/digital-brain-refresh.sh`. Verify completion and report only counts plus output paths. Do not print private message contents.
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Example schedule ideas:
|
|
43
|
+
|
|
44
|
+
- Every morning: `FREQ=DAILY;BYHOUR=8;BYMINUTE=0;BYSECOND=0`
|
|
45
|
+
- Every 30 minutes from 8-12: `FREQ=DAILY;BYHOUR=8,9,10,11;BYMINUTE=0,30;BYSECOND=0`
|
|
46
|
+
- Weekly: `FREQ=WEEKLY;BYDAY=MO;BYHOUR=9;BYMINUTE=0;BYSECOND=0`
|
|
47
|
+
|
|
48
|
+
## Local Cron
|
|
49
|
+
|
|
50
|
+
Run every 30 minutes from 8-12:
|
|
51
|
+
|
|
52
|
+
```cron
|
|
53
|
+
0,30 8-11 * * * /path/to/vault/Tools/digital-brain-refresh.sh >> /path/to/vault/08\ Sources/WhatsApp/.sync-state/cron.log 2>&1
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## macOS launchd
|
|
57
|
+
|
|
58
|
+
Use launchd if you want a native background job. Be aware macOS privacy permissions may block background access to app databases unless Terminal or the runner has Full Disk Access.
|
|
59
|
+
|
|
60
|
+
## Cloud
|
|
61
|
+
|
|
62
|
+
Cloud schedulers are useful for notes and non-sensitive sources, but WhatsApp Mac database sync requires the local Mac.
|
|
63
|
+
|
|
64
|
+
Recommended cloud pattern:
|
|
65
|
+
|
|
66
|
+
1. Keep WhatsApp ingestion local.
|
|
67
|
+
2. Sync only generated, reviewed memory summaries if you choose.
|
|
68
|
+
3. Run cloud jobs on sanitized vault summaries, not raw chats.
|
|
69
|
+
|
|
70
|
+
Do not upload raw WhatsApp exports to a cloud automation unless you explicitly want that privacy tradeoff.
|
package/docs/PRIVACY.md
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Privacy Model
|
|
2
|
+
|
|
3
|
+
Digital Brain is designed for local use.
|
|
4
|
+
|
|
5
|
+
- Messages are read from local files or local app databases.
|
|
6
|
+
- Relationship models are written as local Markdown and JSON.
|
|
7
|
+
- No cloud API is called by default.
|
|
8
|
+
- Ollama interpretation is local when enabled.
|
|
9
|
+
- WhatsApp sending uses a local WhatsApp Web session.
|
|
10
|
+
|
|
11
|
+
Things to be careful about:
|
|
12
|
+
|
|
13
|
+
- Do not commit a generated vault.
|
|
14
|
+
- Do not paste private message exports into GitHub issues.
|
|
15
|
+
- Do not enable outbound sending without understanding the risk.
|
|
16
|
+
- Treat relationship labels as editable working notes, not truth.
|
|
17
|
+
|
package/docs/ROADMAP.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Roadmap
|
|
2
|
+
|
|
3
|
+
- Local dashboard for relationship models.
|
|
4
|
+
- Reply copilot grounded in relationship memory.
|
|
5
|
+
- Manual correction UI for relationship roles.
|
|
6
|
+
- Safer outbound approval queue.
|
|
7
|
+
- Better importers beyond WhatsApp Mac.
|
|
8
|
+
- Packaged app after CLI validation.
|
|
9
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Close Friend
|
|
2
|
+
|
|
3
|
+
Generated: 2026-06-09T22:06:49.488719+00:00
|
|
4
|
+
Role: operational contact
|
|
5
|
+
Role confidence: low
|
|
6
|
+
Closeness: medium
|
|
7
|
+
Conversation difficulty: low
|
|
8
|
+
|
|
9
|
+
These are private working notes. Edit them where wrong.
|
|
10
|
+
|
|
11
|
+
## Role / Relationship Label
|
|
12
|
+
- operational contact (low confidence).
|
|
13
|
+
- Reason: logistics-heavy communication.
|
|
14
|
+
|
|
15
|
+
## Closeness And Importance
|
|
16
|
+
- Closeness: medium.
|
|
17
|
+
- Reciprocity: balanced.
|
|
18
|
+
- Conversation difficulty: low.
|
|
19
|
+
|
|
20
|
+
## Communication Pattern
|
|
21
|
+
- Messages: 2 (1 inbound, 1 outbound).
|
|
22
|
+
- Tags: direct-chat, light, warm, logistics-heavy.
|
|
23
|
+
|
|
24
|
+
## How To Continue This Relationship
|
|
25
|
+
- Keep tone neutral until the user labels this relationship.
|
|
26
|
+
- Track open loops, plans, dates, and commitments.
|
|
27
|
+
|
|
28
|
+
## What Not To Assume
|
|
29
|
+
- Do not expose private summaries unless asked.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Mom
|
|
2
|
+
|
|
3
|
+
Generated: 2026-06-09T22:06:49.488023+00:00
|
|
4
|
+
Role: mother
|
|
5
|
+
Role confidence: high
|
|
6
|
+
Closeness: medium
|
|
7
|
+
Conversation difficulty: low
|
|
8
|
+
|
|
9
|
+
These are private working notes. Edit them where wrong.
|
|
10
|
+
|
|
11
|
+
## Role / Relationship Label
|
|
12
|
+
- mother (high confidence).
|
|
13
|
+
- Reason: manual override.
|
|
14
|
+
|
|
15
|
+
## Closeness And Importance
|
|
16
|
+
- Closeness: medium.
|
|
17
|
+
- Reciprocity: balanced.
|
|
18
|
+
- Conversation difficulty: low.
|
|
19
|
+
|
|
20
|
+
## Communication Pattern
|
|
21
|
+
- Messages: 2 (1 inbound, 1 outbound).
|
|
22
|
+
- Tags: direct-chat, light, warm, logistics-heavy.
|
|
23
|
+
|
|
24
|
+
## How To Continue This Relationship
|
|
25
|
+
- Use warmer language than a work chat.
|
|
26
|
+
- Do not make the interaction purely transactional.
|
|
27
|
+
- Track open loops, plans, dates, and commitments.
|
|
28
|
+
|
|
29
|
+
## What Not To Assume
|
|
30
|
+
- Do not expose private summaries unless asked.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Project Team
|
|
2
|
+
|
|
3
|
+
Generated: 2026-06-09T22:06:49.488560+00:00
|
|
4
|
+
Role: work collaborator
|
|
5
|
+
Role confidence: medium
|
|
6
|
+
Closeness: low/unclear
|
|
7
|
+
Conversation difficulty: practical/low-emotional
|
|
8
|
+
|
|
9
|
+
These are private working notes. Edit them where wrong.
|
|
10
|
+
|
|
11
|
+
## Role / Relationship Label
|
|
12
|
+
- work collaborator (medium confidence).
|
|
13
|
+
- Reason: matched chat name.
|
|
14
|
+
|
|
15
|
+
## Closeness And Importance
|
|
16
|
+
- Closeness: low/unclear.
|
|
17
|
+
- Reciprocity: balanced.
|
|
18
|
+
- Conversation difficulty: practical/low-emotional.
|
|
19
|
+
|
|
20
|
+
## Communication Pattern
|
|
21
|
+
- Messages: 2 (1 inbound, 1 outbound).
|
|
22
|
+
- Tags: group-chat, light, logistics-heavy, question-heavy.
|
|
23
|
+
|
|
24
|
+
## How To Continue This Relationship
|
|
25
|
+
- Lead with context, next steps, and clear asks.
|
|
26
|
+
- Keep emotional interpretation light.
|
|
27
|
+
- Track open loops, plans, dates, and commitments.
|
|
28
|
+
|
|
29
|
+
## What Not To Assume
|
|
30
|
+
- Do not expose private summaries unless asked.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Interpreted Relationship Memory
|
|
2
|
+
|
|
3
|
+
Generated working notes. Treat as editable, not truth.
|
|
4
|
+
|
|
5
|
+
- [[Mom]]: mother (high), closeness medium, difficulty low
|
|
6
|
+
- [[Project Team]]: work collaborator (medium), closeness low/unclear, difficulty practical/low-emotional
|
|
7
|
+
- [[Close Friend]]: operational contact (low), closeness medium, difficulty low
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Close Friend
|
|
2
|
+
|
|
3
|
+
Generated: 2026-06-09T22:06:49.488719+00:00
|
|
4
|
+
Role: operational contact
|
|
5
|
+
Role confidence: low
|
|
6
|
+
Closeness: medium
|
|
7
|
+
Conversation difficulty: low
|
|
8
|
+
|
|
9
|
+
These are private working notes. Edit them where wrong.
|
|
10
|
+
|
|
11
|
+
## Role / Relationship Label
|
|
12
|
+
- operational contact (low confidence).
|
|
13
|
+
- Reason: logistics-heavy communication.
|
|
14
|
+
|
|
15
|
+
## Closeness And Importance
|
|
16
|
+
- Closeness: medium.
|
|
17
|
+
- Reciprocity: balanced.
|
|
18
|
+
- Conversation difficulty: low.
|
|
19
|
+
|
|
20
|
+
## Communication Pattern
|
|
21
|
+
- Messages: 2 (1 inbound, 1 outbound).
|
|
22
|
+
- Tags: direct-chat, light, warm, logistics-heavy.
|
|
23
|
+
|
|
24
|
+
## How To Continue This Relationship
|
|
25
|
+
- Keep tone neutral until the user labels this relationship.
|
|
26
|
+
- Track open loops, plans, dates, and commitments.
|
|
27
|
+
|
|
28
|
+
## What Not To Assume
|
|
29
|
+
- Do not expose private summaries unless asked.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Mom
|
|
2
|
+
|
|
3
|
+
Generated: 2026-06-09T22:06:49.488023+00:00
|
|
4
|
+
Role: mother
|
|
5
|
+
Role confidence: high
|
|
6
|
+
Closeness: medium
|
|
7
|
+
Conversation difficulty: low
|
|
8
|
+
|
|
9
|
+
These are private working notes. Edit them where wrong.
|
|
10
|
+
|
|
11
|
+
## Role / Relationship Label
|
|
12
|
+
- mother (high confidence).
|
|
13
|
+
- Reason: manual override.
|
|
14
|
+
|
|
15
|
+
## Closeness And Importance
|
|
16
|
+
- Closeness: medium.
|
|
17
|
+
- Reciprocity: balanced.
|
|
18
|
+
- Conversation difficulty: low.
|
|
19
|
+
|
|
20
|
+
## Communication Pattern
|
|
21
|
+
- Messages: 2 (1 inbound, 1 outbound).
|
|
22
|
+
- Tags: direct-chat, light, warm, logistics-heavy.
|
|
23
|
+
|
|
24
|
+
## How To Continue This Relationship
|
|
25
|
+
- Use warmer language than a work chat.
|
|
26
|
+
- Do not make the interaction purely transactional.
|
|
27
|
+
- Track open loops, plans, dates, and commitments.
|
|
28
|
+
|
|
29
|
+
## What Not To Assume
|
|
30
|
+
- Do not expose private summaries unless asked.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Project Team
|
|
2
|
+
|
|
3
|
+
Generated: 2026-06-09T22:06:49.488560+00:00
|
|
4
|
+
Role: work collaborator
|
|
5
|
+
Role confidence: medium
|
|
6
|
+
Closeness: low/unclear
|
|
7
|
+
Conversation difficulty: practical/low-emotional
|
|
8
|
+
|
|
9
|
+
These are private working notes. Edit them where wrong.
|
|
10
|
+
|
|
11
|
+
## Role / Relationship Label
|
|
12
|
+
- work collaborator (medium confidence).
|
|
13
|
+
- Reason: matched chat name.
|
|
14
|
+
|
|
15
|
+
## Closeness And Importance
|
|
16
|
+
- Closeness: low/unclear.
|
|
17
|
+
- Reciprocity: balanced.
|
|
18
|
+
- Conversation difficulty: practical/low-emotional.
|
|
19
|
+
|
|
20
|
+
## Communication Pattern
|
|
21
|
+
- Messages: 2 (1 inbound, 1 outbound).
|
|
22
|
+
- Tags: group-chat, light, logistics-heavy, question-heavy.
|
|
23
|
+
|
|
24
|
+
## How To Continue This Relationship
|
|
25
|
+
- Lead with context, next steps, and clear asks.
|
|
26
|
+
- Keep emotional interpretation light.
|
|
27
|
+
- Track open loops, plans, dates, and commitments.
|
|
28
|
+
|
|
29
|
+
## What Not To Assume
|
|
30
|
+
- Do not expose private summaries unless asked.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Relationship Map
|
|
2
|
+
|
|
3
|
+
Window: last 365 days
|
|
4
|
+
|
|
5
|
+
Generated signals. Treat as editable working notes.
|
|
6
|
+
|
|
7
|
+
## Mom
|
|
8
|
+
|
|
9
|
+
- Guess: warm personal relationship
|
|
10
|
+
- Messages: 2 (1 inbound, 1 outbound)
|
|
11
|
+
- Dates: 2026-01-01 to 2026-01-01
|
|
12
|
+
- Scores: sentiment 0.159, warmth 0.5, friction 0.0, operational 1.5
|
|
13
|
+
- Tags: direct-chat, light, warm, logistics-heavy
|
|
14
|
+
|
|
15
|
+
## Project Team
|
|
16
|
+
|
|
17
|
+
- Guess: group, likely social or mixed context
|
|
18
|
+
- Messages: 2 (1 inbound, 1 outbound)
|
|
19
|
+
- Dates: 2026-01-01 to 2026-01-01
|
|
20
|
+
- Scores: sentiment 0, warmth 0.0, friction 0.0, operational 3.0
|
|
21
|
+
- Tags: group-chat, light, logistics-heavy, question-heavy
|
|
22
|
+
|
|
23
|
+
## Close Friend
|
|
24
|
+
|
|
25
|
+
- Guess: warm personal relationship
|
|
26
|
+
- Messages: 2 (1 inbound, 1 outbound)
|
|
27
|
+
- Dates: 2026-01-01 to 2026-01-01
|
|
28
|
+
- Scores: sentiment 0.159, warmth 1.0, friction 0.0, operational 0.5
|
|
29
|
+
- Tags: direct-chat, light, warm, logistics-heavy
|