wayfind 2.0.29 → 2.0.30

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/bin/distill.js CHANGED
@@ -164,14 +164,13 @@ async function mergeEntries(entries, llmConfig, tier) {
164
164
  const systemPrompt = MERGE_PROMPTS[tier] || MERGE_PROMPTS.daily;
165
165
  const userContent = parts.join('\n\n---\n\n');
166
166
 
167
- const result = await llm.chat({
167
+ const config = {
168
168
  provider: llmConfig.provider || 'anthropic',
169
169
  model: llmConfig.model || 'claude-haiku-4-5-20251001',
170
- apiKeyEnv: llmConfig.api_key_env || 'ANTHROPIC_API_KEY',
171
- system: systemPrompt,
172
- messages: [{ role: 'user', content: userContent }],
170
+ api_key_env: llmConfig.api_key_env || 'ANTHROPIC_API_KEY',
173
171
  max_tokens: 2000,
174
- });
172
+ };
173
+ const result = await llm.call(config, systemPrompt, userContent);
175
174
 
176
175
  // Extract title from first line or generate one
177
176
  const firstEntry = entries[0].entry;
@@ -0,0 +1,171 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const HOME = process.env.HOME || process.env.USERPROFILE;
6
+
7
+ /**
8
+ * Compare Claude Code auto-memory vs Wayfind global memory.
9
+ * Shows overlap, unique content in each, and freshness.
10
+ */
11
+ function compare() {
12
+ const autoMemoryRoot = path.join(HOME, '.claude', 'projects');
13
+ const wayfindMemory = path.join(HOME, '.claude', 'memory');
14
+
15
+ // Collect auto-memory entries
16
+ const autoEntries = [];
17
+ if (fs.existsSync(autoMemoryRoot)) {
18
+ for (const proj of fs.readdirSync(autoMemoryRoot)) {
19
+ const memDir = path.join(autoMemoryRoot, proj, 'memory');
20
+ if (!fs.existsSync(memDir)) continue;
21
+ for (const file of fs.readdirSync(memDir).filter(f => f.endsWith('.md') && f !== 'MEMORY.md')) {
22
+ const fp = path.join(memDir, file);
23
+ const content = fs.readFileSync(fp, 'utf8');
24
+ const typeMatch = content.match(/^type:\s*(.+)$/m);
25
+ const descMatch = content.match(/^description:\s*(.+)$/m);
26
+ const stat = fs.statSync(fp);
27
+ autoEntries.push({
28
+ project: proj,
29
+ file,
30
+ type: typeMatch ? typeMatch[1].trim() : 'unknown',
31
+ description: descMatch ? descMatch[1].trim() : '',
32
+ size: content.length,
33
+ modified: stat.mtime,
34
+ daysAgo: Math.floor((Date.now() - stat.mtime) / (1000 * 60 * 60 * 24)),
35
+ });
36
+ }
37
+ }
38
+ }
39
+
40
+ // Collect Wayfind global memory entries
41
+ const wayfindEntries = [];
42
+ if (fs.existsSync(wayfindMemory)) {
43
+ for (const file of fs.readdirSync(wayfindMemory).filter(f => f.endsWith('.md'))) {
44
+ const fp = path.join(wayfindMemory, file);
45
+ const content = fs.readFileSync(fp, 'utf8');
46
+ const stat = fs.statSync(fp);
47
+ wayfindEntries.push({
48
+ file,
49
+ size: content.length,
50
+ modified: stat.mtime,
51
+ daysAgo: Math.floor((Date.now() - stat.mtime) / (1000 * 60 * 60 * 24)),
52
+ });
53
+ }
54
+ }
55
+
56
+ // Journal stats
57
+ const journalDir = path.join(wayfindMemory, 'journal');
58
+ let journalCount = 0;
59
+ let journalSize = 0;
60
+ let latestJournal = null;
61
+ if (fs.existsSync(journalDir)) {
62
+ const journals = fs.readdirSync(journalDir).filter(f => f.endsWith('.md'));
63
+ journalCount = journals.length;
64
+ for (const j of journals) {
65
+ const fp = path.join(journalDir, j);
66
+ journalSize += fs.statSync(fp).size;
67
+ const stat = fs.statSync(fp);
68
+ if (!latestJournal || stat.mtime > latestJournal) latestJournal = stat.mtime;
69
+ }
70
+ }
71
+
72
+ // Report
73
+ console.log('');
74
+ console.log('=== Memory Systems Comparison ===');
75
+ console.log('');
76
+
77
+ console.log('Claude Code Auto-Memory (per-project):');
78
+ const byType = {};
79
+ for (const e of autoEntries) {
80
+ byType[e.type] = (byType[e.type] || 0) + 1;
81
+ }
82
+ console.log(` ${autoEntries.length} entries across ${new Set(autoEntries.map(e => e.project)).size} projects`);
83
+ for (const [type, count] of Object.entries(byType).sort((a, b) => b[1] - a[1])) {
84
+ console.log(` ${type}: ${count}`);
85
+ }
86
+ const recentAuto = autoEntries.filter(e => e.daysAgo <= 7);
87
+ const staleAuto = autoEntries.filter(e => e.daysAgo > 30);
88
+ console.log(` Fresh (≤7d): ${recentAuto.length} | Stale (>30d): ${staleAuto.length}`);
89
+ console.log('');
90
+
91
+ console.log('Wayfind Global Memory:');
92
+ console.log(` ${wayfindEntries.length} topic files`);
93
+ console.log(` ${journalCount} journal entries (${Math.round(journalSize / 1024)}KB)`);
94
+ const recentWf = wayfindEntries.filter(e => e.daysAgo <= 7);
95
+ const staleWf = wayfindEntries.filter(e => e.daysAgo > 30);
96
+ console.log(` Fresh (≤7d): ${recentWf.length} | Stale (>30d): ${staleWf.length}`);
97
+ if (latestJournal) {
98
+ const jDaysAgo = Math.floor((Date.now() - latestJournal) / (1000 * 60 * 60 * 24));
99
+ console.log(` Latest journal: ${jDaysAgo}d ago`);
100
+ }
101
+ console.log('');
102
+
103
+ // Overlap detection: look for similar topics
104
+ console.log('Potential Overlap (auto-memory projects with Wayfind topic files on same subject):');
105
+ let overlapCount = 0;
106
+ for (const auto of autoEntries) {
107
+ const keywords = auto.file.replace(/\.md$/, '').replace(/^(feedback|project|reference|user)_/, '').split(/[-_]/).filter(w => w.length > 2);
108
+ for (const wf of wayfindEntries) {
109
+ const wfWords = wf.file.replace(/\.md$/, '').split(/[-_]/).filter(w => w.length > 2);
110
+ const overlap = keywords.filter(k => wfWords.some(w => w.includes(k) || k.includes(w)));
111
+ if (overlap.length >= 2) {
112
+ console.log(` AUTO: ${auto.file} (${auto.project.slice(-30)}) <-> WF: ${wf.file}`);
113
+ overlapCount++;
114
+ }
115
+ }
116
+ }
117
+ if (overlapCount === 0) console.log(' None detected');
118
+ console.log('');
119
+
120
+ // Secret scan across both memory systems
121
+ const SECRET_PATTERNS = [
122
+ /xoxb-[0-9A-Za-z-]+/, // Slack bot token
123
+ /xapp-[0-9A-Za-z-]+/, // Slack app token
124
+ /ghp_[0-9A-Za-z]+/, // GitHub PAT
125
+ /gho_[0-9A-Za-z]+/, // GitHub OAuth
126
+ /sk-[0-9A-Za-z]{20,}/, // OpenAI / generic secret key
127
+ /pat-na1-[0-9a-f-]+/, // HubSpot PAT
128
+ /ntn_[0-9A-Za-z]+/, // Notion token
129
+ /dG9r[0-9A-Za-z+/=]{20,}/, // Base64 "tok:" prefix (Intercom-style)
130
+ /AKIA[0-9A-Z]{16}/, // AWS access key
131
+ /\b[A-Za-z0-9_]{10,}\.[A-Za-z0-9_-]{20,}/, // Azure function key pattern (xxx.yyy)
132
+ ];
133
+
134
+ console.log('Secret Scan:');
135
+ let secretsFound = 0;
136
+ const allFiles = [
137
+ ...autoEntries.map(e => ({
138
+ path: path.join(autoMemoryRoot, e.project, 'memory', e.file),
139
+ label: `auto:${e.project.slice(-25)}/${e.file}`,
140
+ })),
141
+ ...wayfindEntries.map(e => ({
142
+ path: path.join(wayfindMemory, e.file),
143
+ label: `wayfind:${e.file}`,
144
+ })),
145
+ ];
146
+ for (const { path: fp, label } of allFiles) {
147
+ try {
148
+ const content = fs.readFileSync(fp, 'utf8');
149
+ for (const pattern of SECRET_PATTERNS) {
150
+ const match = content.match(pattern);
151
+ if (match) {
152
+ // Skip if it's inside a code example or command template (has $ prefix or is in backtick-quoted env var reference)
153
+ const line = content.split('\n').find(l => l.includes(match[0])) || '';
154
+ if (line.includes('$') && !line.includes('`' + match[0])) continue;
155
+ console.log(` ⚠ ${label} — matches ${pattern.source.slice(0, 20)}...`);
156
+ secretsFound++;
157
+ break;
158
+ }
159
+ }
160
+ } catch { /* skip unreadable */ }
161
+ }
162
+ if (secretsFound === 0) {
163
+ console.log(' Clean — no secrets detected in memory files');
164
+ }
165
+ }
166
+
167
+ if (require.main === module) {
168
+ compare();
169
+ }
170
+
171
+ module.exports = { compare };
@@ -0,0 +1,41 @@
1
+ #!/bin/bash
2
+ # Daily memory systems comparison report — posts to Slack via bot token.
3
+ # Add to crontab: 43 8 * * * /home/greg/repos/greg/wayfind/bin/memory-report.sh
4
+ #
5
+ # Runs on host (needs access to ~/.claude/projects for auto-memory).
6
+ # Pulls SLACK_BOT_TOKEN from the wayfind container if not set locally.
7
+
8
+ set -euo pipefail
9
+ SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
10
+ CHANNEL="${SLACK_MEMORY_REPORT_CHANNEL:-C0AHV3UUW67}"
11
+ DATE=$(date +%Y-%m-%d)
12
+ PATH="$HOME/.npm-global/bin:$HOME/.local/bin:/usr/local/bin:/usr/bin:/bin:$PATH"
13
+
14
+ # Get Slack token from container if not in environment
15
+ if [ -z "${SLACK_BOT_TOKEN:-}" ]; then
16
+ SLACK_BOT_TOKEN=$(docker exec wayfind printenv SLACK_BOT_TOKEN 2>/dev/null || true)
17
+ fi
18
+ if [ -z "${SLACK_BOT_TOKEN:-}" ]; then
19
+ echo "[$DATE] No SLACK_BOT_TOKEN available — skipping report"
20
+ exit 0
21
+ fi
22
+
23
+ # Generate comparison
24
+ REPORT=$(node "$SCRIPT_DIR/memory-compare.js" 2>&1)
25
+
26
+ # Format for Slack
27
+ PAYLOAD=$(node -e "
28
+ const report = process.argv[1];
29
+ const date = process.argv[2];
30
+ const msg = ':brain: *Daily Memory Systems Report — ' + date + '*\n\`\`\`\n' + report.replace(/=== Memory Systems Comparison ===\n\n/, '') + '\n\`\`\`';
31
+ const body = JSON.stringify({ channel: process.argv[3], text: msg });
32
+ process.stdout.write(body);
33
+ " "$REPORT" "$DATE" "$CHANNEL")
34
+
35
+ # Post to Slack
36
+ curl -s -X POST https://slack.com/api/chat.postMessage \
37
+ -H "Authorization: Bearer $SLACK_BOT_TOKEN" \
38
+ -H "Content-Type: application/json" \
39
+ -d "$PAYLOAD" > /dev/null
40
+
41
+ echo "[$DATE] Memory report posted to Slack"
@@ -16,44 +16,7 @@ if (!HOME) {
16
16
 
17
17
  const WAYFIND_DIR = process.env.WAYFIND_DIR || path.join(HOME, '.claude', 'team-context');
18
18
 
19
- // --- Env var migration shim (v2.0.0) ---
20
- // Honor old MERIDIAN_* env vars with deprecation warning. Remove in v3.0.
21
- const ENV_VAR_MIGRATION = {
22
- MERIDIAN_TELEMETRY: 'TEAM_CONTEXT_TELEMETRY',
23
- MERIDIAN_AUTHOR: 'TEAM_CONTEXT_AUTHOR',
24
- MERIDIAN_TENANT_ID: 'TEAM_CONTEXT_TENANT_ID',
25
- MERIDIAN_TEAM_CONTEXT_DIR: 'TEAM_CONTEXT_DIR',
26
- MERIDIAN_JOURNALS_DIR: 'TEAM_CONTEXT_JOURNALS_DIR',
27
- MERIDIAN_SIGNALS_DIR: 'TEAM_CONTEXT_SIGNALS_DIR',
28
- MERIDIAN_SKIP_EXPORT: 'TEAM_CONTEXT_SKIP_EXPORT',
29
- MERIDIAN_EXCLUDE_REPOS: 'TEAM_CONTEXT_EXCLUDE_REPOS',
30
- MERIDIAN_SLACK_WEBHOOK: 'TEAM_CONTEXT_SLACK_WEBHOOK',
31
- MERIDIAN_LLM_MODEL: 'TEAM_CONTEXT_LLM_MODEL',
32
- MERIDIAN_DIGEST_SCHEDULE: 'TEAM_CONTEXT_DIGEST_SCHEDULE',
33
- MERIDIAN_SIGNAL_SCHEDULE: 'TEAM_CONTEXT_SIGNAL_SCHEDULE',
34
- MERIDIAN_STORAGE_BACKEND: 'TEAM_CONTEXT_STORAGE_BACKEND',
35
- MERIDIAN_MODE: 'TEAM_CONTEXT_MODE',
36
- MERIDIAN_REINDEX_SCHEDULE: 'TEAM_CONTEXT_REINDEX_SCHEDULE',
37
- MERIDIAN_ENCRYPTION_KEY: 'TEAM_CONTEXT_ENCRYPTION_KEY',
38
- MERIDIAN_SIMULATE: 'TEAM_CONTEXT_SIMULATE',
39
- MERIDIAN_SIM_FIXTURES: 'TEAM_CONTEXT_SIM_FIXTURES',
40
- MERIDIAN_VERSION: 'TEAM_CONTEXT_VERSION',
41
- };
42
- for (const [oldKey, newKey] of Object.entries(ENV_VAR_MIGRATION)) {
43
- if (process.env[oldKey] && !process.env[newKey]) {
44
- process.env[newKey] = process.env[oldKey];
45
- if (!process.env.TEAM_CONTEXT_SKIP_EXPORT) {
46
- console.warn(`⚠ ${oldKey} is deprecated — rename to ${newKey}`);
47
- }
48
- }
49
- }
50
-
51
- // Also migrate config directory: if old ~/.claude/meridian/ exists but new doesn't, use old
52
- const OLD_DIR = path.join(HOME, '.claude', 'meridian');
53
- const EFFECTIVE_DIR = (fs.existsSync(WAYFIND_DIR) || !fs.existsSync(OLD_DIR)) ? WAYFIND_DIR : OLD_DIR;
54
- if (EFFECTIVE_DIR === OLD_DIR) {
55
- console.warn('⚠ ~/.claude/meridian/ detected — rename to ~/.claude/team-context/');
56
- }
19
+ const EFFECTIVE_DIR = WAYFIND_DIR;
57
20
 
58
21
  // Auto-load .env from config dir BEFORE requiring modules
59
22
  // (modules like content-store read env vars at load time)
@@ -2884,7 +2847,7 @@ function runMigrateToPlugin(args) {
2884
2847
  }
2885
2848
 
2886
2849
  // Step 3: Remove old command files (plugin skills replace these)
2887
- const oldCommandFiles = ['init-memory.md', 'init-team.md', 'doctor.md', 'journal.md', 'standup.md', 'review-prs.md'];
2850
+ const oldCommandFiles = ['init-memory.md', 'init-team.md', 'init-folder.md', 'doctor.md', 'journal.md', 'standup.md', 'review-prs.md'];
2888
2851
  for (const file of oldCommandFiles) {
2889
2852
  const cmdPath = path.join(commandsDir, file);
2890
2853
  if (fs.existsSync(cmdPath)) {
@@ -4847,6 +4810,10 @@ const COMMANDS = {
4847
4810
  desc: 'Search indexed entries (journals + conversations, semantic or full-text)',
4848
4811
  run: (args) => runSearchJournals(args),
4849
4812
  },
4813
+ 'memory-compare': {
4814
+ desc: 'Compare Claude Code auto-memory vs Wayfind memory systems',
4815
+ run: () => require('./memory-compare').compare(),
4816
+ },
4850
4817
  insights: {
4851
4818
  desc: 'Show insights from indexed journal data',
4852
4819
  run: (args) => runInsights(args),
@@ -5065,6 +5032,7 @@ function showHelp() {
5065
5032
  console.log('');
5066
5033
  console.log('In a Claude Code session:');
5067
5034
  console.log(' /init-memory Set up memory for current repo');
5035
+ console.log(' /init-folder Set up memory for a non-repo folder');
5068
5036
  console.log(' /init-team Set up team context (journals, digests, Notion)');
5069
5037
  console.log(' /journal View your session journal digest');
5070
5038
  console.log(' /doctor Check installation health');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wayfind",
3
- "version": "2.0.29",
3
+ "version": "2.0.30",
4
4
  "description": "Team decision trail for AI-assisted development. The connective tissue between product, engineering, and strategy.",
5
5
  "bin": {
6
6
  "wayfind": "./bin/team-context.js"
@@ -11,7 +11,7 @@ set -euo pipefail
11
11
  # Skip export for worker agents in multi-agent swarms.
12
12
  # Set TEAM_CONTEXT_SKIP_EXPORT=1 when spawning worker agents so only the
13
13
  # orchestrator's decisions flow into the journal.
14
- if [ "${TEAM_CONTEXT_SKIP_EXPORT:-${MERIDIAN_SKIP_EXPORT:-}}" = "1" ]; then
14
+ if [ "${TEAM_CONTEXT_SKIP_EXPORT:-}" = "1" ]; then
15
15
  exit 0
16
16
  fi
17
17
 
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: init-folder
3
+ description: Initialize Wayfind for a non-repo folder (e.g., ~/admin, ~/). Creates .claude/personal-state.md, defensively updates .gitignore if one exists, and registers the folder in the global index. Safe to run multiple times (idempotent).
4
+ user-invocable: true
5
+ ---
6
+
7
+ # Initialize Wayfind for a Non-Repo Folder
8
+
9
+ Run these steps in order. Skip any step that's already done (this command is idempotent).
10
+
11
+ This command is for **non-repo working directories** — your home directory, an admin folder,
12
+ a scratch workspace, etc. For git repos, use `/wayfind:init-memory` instead.
13
+
14
+ ## Step 1: Detect Context
15
+
16
+ - Determine the current working directory (or ask the user which folder to initialize)
17
+ - Check if it's a git repo (`git rev-parse --show-toplevel 2>/dev/null`)
18
+ - If it IS a git repo, suggest: "This looks like a git repo. Did you mean to run `/wayfind:init-memory` instead? That sets up team-state.md for shared context too."
19
+ - If the user confirms they want init-folder anyway, proceed.
20
+ - Read `~/.claude/global-state.md` to check if this folder is already registered
21
+
22
+ ## Step 2: Create personal state file (if missing)
23
+
24
+ Non-repo folders only get **one** state file — there's no team-state.md because there's
25
+ no git repo to commit it to.
26
+
27
+ If `.claude/personal-state.md` does not exist, create it:
28
+
29
+ ```markdown
30
+ # [Folder Name] — Personal State
31
+
32
+ Last updated: [today's date]
33
+
34
+ (This file is local-only. It persists context across AI sessions in this folder.)
35
+
36
+ ## My Current Focus
37
+ <!-- Your current tasks and next steps for work in this folder -->
38
+
39
+ ## Personal Context
40
+ <!-- Working notes, decisions, things to remember -->
41
+
42
+ ## What I'm Watching
43
+ <!-- Open questions, things to follow up on -->
44
+ ```
45
+
46
+ Create the `.claude/` directory first if it doesn't exist.
47
+
48
+ ## Step 3: Defensive .gitignore update
49
+
50
+ Check if a `.gitignore` file exists in the folder root.
51
+
52
+ **If `.gitignore` exists:** Ensure `.claude/` is listed (the whole directory — unlike repos,
53
+ non-repo folders have no team-state.md to preserve). If it's missing, append it.
54
+
55
+ **If `.gitignore` does not exist:** Skip this step. Don't create one — this isn't a repo.
56
+
57
+ ## Step 4: Check CLAUDE.md
58
+
59
+ Read the folder's `CLAUDE.md` (if it exists).
60
+
61
+ **If it exists and does NOT contain "Session State Protocol":** Note to the user:
62
+ "Your `~/CLAUDE.md` (or global instructions) should include the session protocol.
63
+ If you're using Wayfind's standard `~/CLAUDE.md`, you're already covered."
64
+
65
+ **If it exists and DOES contain "Session State Protocol":** Skip — already configured.
66
+
67
+ **If it does not exist:** Do NOT create one. Note: "No CLAUDE.md in this folder.
68
+ Your `~/CLAUDE.md` global instructions handle the session protocol."
69
+
70
+ ## Step 5: Register in Global Index
71
+
72
+ Read `~/.claude/global-state.md`. Add the folder's state file to the State Files table
73
+ if missing:
74
+
75
+ ```
76
+ | `[full path]/.claude/personal-state.md` | Personal context for [folder name] (non-repo) |
77
+ ```
78
+
79
+ The Active Projects table is auto-generated by `wayfind status --write` — do NOT add
80
+ rows to it manually.
81
+
82
+ ## Step 6: Report
83
+
84
+ Tell the user:
85
+ - `.claude/personal-state.md` — created or already existed (local only)
86
+ - `.gitignore` — updated or not applicable
87
+ - `global-state.md` — folder registered or already listed
88
+
89
+ Then print:
90
+
91
+ **"This folder is now tracked by Wayfind. Context saved here will be available in future
92
+ sessions. For cross-repo context that should be available everywhere, save to
93
+ `~/.claude/memory/` instead."**
@@ -87,6 +87,14 @@ Create them if missing. If `prompts/` is new, add the README from `templates/pro
87
87
 
88
88
  Store the team context repo path for later steps.
89
89
 
90
+ ## Step 1a: Non-Repo Folder Setup (Optional)
91
+
92
+ After the team context repo is set up, ask:
93
+
94
+ **"Do you have a non-repo folder you use for admin or cross-cutting work? (e.g., your home directory) We can set that up too so context from those sessions is preserved."**
95
+
96
+ If yes, run `/wayfind:init-folder` in that directory (or guide them to run it later).
97
+
90
98
  ## Step 2: Slack Integration
91
99
 
92
100
  Ask: **"Do you want weekly digests posted to Slack? You'll need a Slack Incoming Webhook URL. If you have one, paste it. If not, I can walk you through creating one."**
@@ -35,4 +35,6 @@ the plugin's hooks. This skill tells you where state files live so you can load
35
35
  - Keep `global-state.md` under 80 lines. Detail goes in `~/.claude/memory/` files.
36
36
  - Per-repo state files stay focused on that repo only.
37
37
  - New cross-repo topics get new files in `~/.claude/memory/`, not appended to global-state.md.
38
+ - **NEVER write secrets, API keys, tokens, or credentials into memory or state files.** Store pointers to where secrets live, not the secrets themselves.
39
+ - Do NOT write Wayfind files to `~/.claude/projects/<project>/memory/` root — that's Claude Code's native auto-memory space.
38
40
  - Do NOT use external memory databases or CLI tools for state storage. Use plain markdown files only.
@@ -3,15 +3,17 @@
3
3
 
4
4
  **Memory system:** Hierarchical plain-markdown files. No CLI tools, no databases.
5
5
 
6
+ **Important:** Claude Code has its own auto-memory system that writes to `~/.claude/projects/<project>/memory/MEMORY.md`. Wayfind's memory files live in a separate `wayfind/` subfolder to avoid conflicts. Do NOT write Wayfind state files to the root memory directory — that's Claude Code's native auto-memory space.
7
+
6
8
  ### File Hierarchy
7
9
 
8
10
  ```
9
11
  ~/.claude/
10
12
  global-state.md # Thin index — ALWAYS load at session start
11
13
  state.md # Admin/non-repo work
12
- memory/ # Topic files — load on demand
14
+ memory/ # Cross-repo topic files — load on demand
13
15
  <topic>.md
14
- journal/YYYY-MM-DD.md # Daily log
16
+ journal/YYYY-MM-DD.md # Daily work log
15
17
 
16
18
  <repo>/.claude/
17
19
  team-state.md # Shared team context — committed to git
@@ -47,7 +49,9 @@ If work drifts from the stated goal, flag it: *"Quick check — we set out to [g
47
49
 
48
50
  ### Rules
49
51
 
52
+ - **NEVER write secrets, API keys, tokens, passwords, or credentials into memory or state files.** Store a pointer to where the secret lives (e.g., "API key is in `~/.config/myapp/.env`"), not the secret itself. Memory files are plain text, may be synced to git, and are readable by any tool with filesystem access.
50
53
  - Keep `global-state.md` under 80 lines. Detail goes in `~/.claude/memory/` files.
51
54
  - Per-repo `state.md` stays focused on that repo only.
52
55
  - New cross-repo topics get new files in `~/.claude/memory/`, not appended to global-state.md.
56
+ - Do NOT write Wayfind files to `~/.claude/projects/<project>/memory/` root — that's Claude Code's native auto-memory space.
53
57
  - Do NOT use external memory databases or CLI tools for state storage. Use plain markdown files only.
@@ -13,4 +13,6 @@
13
13
  3. Do NOT update `~/.claude/global-state.md` — its Active Projects table is rebuilt automatically by `wayfind status`.
14
14
  4. If significant new cross-repo context was created (patterns, strategies, decisions), create or update a file in `~/.claude/memory/` and add it to the Memory Files manifest in global-state.md
15
15
 
16
+ **NEVER write secrets, API keys, tokens, or credentials into memory or state files.** Store pointers to where secrets live, not the secrets themselves.
17
+ **Do NOT write Wayfind files to `~/.claude/projects/<project>/memory/` root** — that's Claude Code's native auto-memory space.
16
18
  **Do NOT use external memory databases or CLI tools for state storage.** Use plain markdown files only.
@@ -0,0 +1,91 @@
1
+ ---
2
+ description: Initialize Wayfind for a non-repo folder (e.g., ~/admin, ~/). Creates .claude/personal-state.md, defensively updates .gitignore if one exists, and registers the folder in the global index. Safe to run multiple times (idempotent).
3
+ ---
4
+
5
+ # Initialize Wayfind for a Non-Repo Folder
6
+
7
+ Run these steps in order. Skip any step that's already done (this command is idempotent).
8
+
9
+ This command is for **non-repo working directories** — your home directory, an admin folder,
10
+ a scratch workspace, etc. For git repos, use `/init-memory` instead.
11
+
12
+ ## Step 1: Detect Context
13
+
14
+ - Determine the current working directory (or ask the user which folder to initialize)
15
+ - Check if it's a git repo (`git rev-parse --show-toplevel 2>/dev/null`)
16
+ - If it IS a git repo, suggest: "This looks like a git repo. Did you mean to run `/init-memory` instead? That sets up team-state.md for shared context too."
17
+ - If the user confirms they want init-folder anyway, proceed.
18
+ - Read `~/.claude/global-state.md` to check if this folder is already registered
19
+
20
+ ## Step 2: Create personal state file (if missing)
21
+
22
+ Non-repo folders only get **one** state file — there's no team-state.md because there's
23
+ no git repo to commit it to.
24
+
25
+ If `.claude/personal-state.md` does not exist, create it:
26
+
27
+ ```markdown
28
+ # [Folder Name] — Personal State
29
+
30
+ Last updated: [today's date]
31
+
32
+ (This file is local-only. It persists context across AI sessions in this folder.)
33
+
34
+ ## My Current Focus
35
+ <!-- Your current tasks and next steps for work in this folder -->
36
+
37
+ ## Personal Context
38
+ <!-- Working notes, decisions, things to remember -->
39
+
40
+ ## What I'm Watching
41
+ <!-- Open questions, things to follow up on -->
42
+ ```
43
+
44
+ Create the `.claude/` directory first if it doesn't exist.
45
+
46
+ ## Step 3: Defensive .gitignore update
47
+
48
+ Check if a `.gitignore` file exists in the folder root.
49
+
50
+ **If `.gitignore` exists:** Ensure `.claude/` is listed (the whole directory — unlike repos,
51
+ non-repo folders have no team-state.md to preserve). If it's missing, append it.
52
+
53
+ **If `.gitignore` does not exist:** Skip this step. Don't create one — this isn't a repo.
54
+
55
+ ## Step 4: Check CLAUDE.md
56
+
57
+ Read the folder's `CLAUDE.md` (if it exists).
58
+
59
+ **If it exists and does NOT contain "Session State Protocol":** Note to the user:
60
+ "Your `~/CLAUDE.md` (or global instructions) should include the session protocol.
61
+ If you're using Wayfind's standard `~/CLAUDE.md`, you're already covered."
62
+
63
+ **If it exists and DOES contain "Session State Protocol":** Skip — already configured.
64
+
65
+ **If it does not exist:** Do NOT create one. Note: "No CLAUDE.md in this folder.
66
+ Your `~/CLAUDE.md` global instructions handle the session protocol."
67
+
68
+ ## Step 5: Register in Global Index
69
+
70
+ Read `~/.claude/global-state.md`. Add the folder's state file to the State Files table
71
+ if missing:
72
+
73
+ ```
74
+ | `[full path]/.claude/personal-state.md` | Personal context for [folder name] (non-repo) |
75
+ ```
76
+
77
+ The Active Projects table is auto-generated by `wayfind status --write` — do NOT add
78
+ rows to it manually.
79
+
80
+ ## Step 6: Report
81
+
82
+ Tell the user:
83
+ - `.claude/personal-state.md` — created or already existed (local only)
84
+ - `.gitignore` — updated or not applicable
85
+ - `global-state.md` — folder registered or already listed
86
+
87
+ Then print:
88
+
89
+ **"This folder is now tracked by Wayfind. Context saved here will be available in future
90
+ sessions. For cross-repo context that should be available everywhere, save to
91
+ `~/.claude/memory/` instead."**
@@ -142,6 +142,14 @@ Create `~/.claude/memory/wayfind-team-context.md` with:
142
142
  - <list of usernames with journal directories>
143
143
  ```
144
144
 
145
+ ## Step 1a: Non-Repo Folder Setup (Optional)
146
+
147
+ After the team context repo is set up, ask:
148
+
149
+ **"Do you have a non-repo folder you use for admin or cross-cutting work? (e.g., your home directory) We can set that up too so context from those sessions is preserved."**
150
+
151
+ If yes, run `/init-folder` in that directory (or guide them to run it later).
152
+
145
153
  ## Step 1b: Link and Distribute Context
146
154
 
147
155
  Once the team context repo exists, link it so Wayfind knows where to find shared
@@ -11,7 +11,7 @@ set -euo pipefail
11
11
  # Skip export for worker agents in multi-agent swarms.
12
12
  # Set TEAM_CONTEXT_SKIP_EXPORT=1 when spawning worker agents so only the
13
13
  # orchestrator's decisions flow into the journal.
14
- if [ "${TEAM_CONTEXT_SKIP_EXPORT:-${MERIDIAN_SKIP_EXPORT:-}}" = "1" ]; then
14
+ if [ "${TEAM_CONTEXT_SKIP_EXPORT:-}" = "1" ]; then
15
15
  exit 0
16
16
  fi
17
17