@our2ndbrain/cli 1.1.3 → 2026.4.4

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/src/lib/files.js CHANGED
@@ -8,6 +8,29 @@ const fs = require('fs-extra');
8
8
  const path = require('path');
9
9
  const { compareFiles, summarizeChanges, isBinaryFile, isLargeFile } = require('./diff');
10
10
 
11
+ const README_ALIAS_FILES = new Set(['AGENTS.md', 'CLAUDE.md']);
12
+
13
+ /**
14
+ * Resolve a template source file, falling back to README.md for symlink aliases
15
+ * that are not preserved by npm pack.
16
+ * @param {string} src - Preferred source file path
17
+ * @returns {Promise<string|null>} Resolved source path, or null if unavailable
18
+ */
19
+ async function resolveSourcePath(src) {
20
+ if (await fs.pathExists(src)) {
21
+ return src;
22
+ }
23
+
24
+ if (README_ALIAS_FILES.has(path.basename(src))) {
25
+ const readmePath = path.join(path.dirname(src), 'README.md');
26
+ if (await fs.pathExists(readmePath)) {
27
+ return readmePath;
28
+ }
29
+ }
30
+
31
+ return null;
32
+ }
33
+
11
34
  /**
12
35
  * Copy a file from source to destination
13
36
  * @param {string} src - Source file path
@@ -31,12 +54,11 @@ async function copyFiles(files, templateRoot, targetRoot, onFile) {
31
54
  const result = { copied: [], skipped: [], errors: [] };
32
55
 
33
56
  for (const file of files) {
34
- const src = path.join(templateRoot, file);
57
+ const src = await resolveSourcePath(path.join(templateRoot, file));
35
58
  const dest = path.join(targetRoot, file);
36
59
 
37
60
  try {
38
- // Check if source exists
39
- if (!await fs.pathExists(src)) {
61
+ if (!src) {
40
62
  result.skipped.push(file);
41
63
  if (onFile) onFile(file, 'skip', 'source not found');
42
64
  continue;
@@ -218,25 +240,31 @@ async function compareFilesWrapper(src, dest) {
218
240
  * @param {string} dest - Destination file path
219
241
  * @param {Object} options - Copy options
220
242
  * @param {boolean} [options.force] - Force copy even if equal
243
+ * @param {boolean} [options.dryRun] - Compare only, do not write destination
221
244
  * @returns {Promise<{copied: boolean, unchanged: boolean, error?: string, change?: any}>}
222
245
  */
223
246
  async function copyFileWithCompare(src, dest, options = {}) {
224
247
  try {
225
- // Check if source exists
226
- if (!await fs.pathExists(src)) {
248
+ const resolvedSrc = await resolveSourcePath(src);
249
+ if (!resolvedSrc) {
227
250
  return { copied: false, unchanged: false, error: 'source not found' };
228
251
  }
229
252
 
230
253
  // Compare files if destination exists
231
- const comparison = await compareFilesWrapper(src, dest);
254
+ const comparison = await compareFilesWrapper(resolvedSrc, dest);
232
255
 
233
256
  if (comparison.exists && comparison.equal && !options.force) {
234
257
  return { copied: false, unchanged: true };
235
258
  }
236
259
 
237
- // Perform the copy
238
- await fs.ensureDir(path.dirname(dest));
239
- await fs.copy(src, dest);
260
+ let previousDestContent = '';
261
+ if (comparison.exists && !comparison.binary && !comparison.large) {
262
+ try {
263
+ previousDestContent = await fs.readFile(dest, 'utf8');
264
+ } catch {
265
+ previousDestContent = '';
266
+ }
267
+ }
240
268
 
241
269
  // Generate change summary
242
270
  let change = null;
@@ -247,11 +275,8 @@ async function copyFileWithCompare(src, dest, options = {}) {
247
275
  change = { large: true };
248
276
  } else {
249
277
  try {
250
- const [srcContent, destContent] = await Promise.all([
251
- fs.readFile(src, 'utf8'),
252
- comparison.exists ? fs.readFile(dest, 'utf8') : '',
253
- ]);
254
- const summary = summarizeChanges(destContent, srcContent);
278
+ const srcContent = await fs.readFile(resolvedSrc, 'utf8');
279
+ const summary = summarizeChanges(previousDestContent, srcContent);
255
280
  change = { added: summary.added, removed: summary.removed };
256
281
  } catch {
257
282
  // If we can't read as text, mark as binary
@@ -260,6 +285,14 @@ async function copyFileWithCompare(src, dest, options = {}) {
260
285
  }
261
286
  }
262
287
 
288
+ if (options.dryRun) {
289
+ return { copied: false, unchanged: false, change };
290
+ }
291
+
292
+ // Perform the copy
293
+ await fs.ensureDir(path.dirname(dest));
294
+ await fs.copy(resolvedSrc, dest);
295
+
263
296
  return { copied: true, unchanged: false, change };
264
297
  } catch (err) {
265
298
  return { copied: false, unchanged: false, error: err.message };
@@ -335,6 +368,7 @@ module.exports = {
335
368
  createFile,
336
369
  isDirEmpty,
337
370
  compareFilesWrapper,
371
+ resolveSourcePath,
338
372
  copyFileWithCompare,
339
373
  copyFilesSmart,
340
374
  };
package/AGENTS.md DELETED
@@ -1,193 +0,0 @@
1
- # AGENTS.md
2
-
3
- > This is the project guide for AI assistants. When helping users operate this project, please follow these rules.
4
-
5
- ## Installing 2ndBrain CLI
6
-
7
- ```bash
8
- # Use npx to run directly (recommended)
9
- npx @our2ndbrain/cli@latest <command>
10
-
11
- # Or install globally
12
- npm install -g @our2ndbrain/cli
13
- 2ndbrain <command>
14
- ```
15
-
16
- ## Project Overview
17
-
18
- **2ndBrain** is a personal knowledge management system based on PARA + C-O-R-D + Append-and-Review, using Obsidian as the frontend tool.
19
-
20
- ## Directory Structure Conventions
21
-
22
- ```
23
- 2ndBrain/
24
- ├── 00_Dashboard/ # Dashboards: task aggregation entry point
25
- ├── 10_Inbox/ # Inbox: journals land here
26
- │ └── {MemberName}/ # One subdirectory per member
27
- ├── 20_Areas/ # Areas: long-term focus areas
28
- ├── 30_Projects/ # Projects: things with clear goals
29
- ├── 40_Resources/ # Resources: reference materials
30
- ├── 90_Archives/ # Archives: completed or inactive items
31
- └── 99_System/ # System: templates, scripts and config
32
- ├── Scripts/ # Automation scripts
33
- └── Templates/ # Note templates
34
- ```
35
-
36
- ## Core Rules
37
-
38
- ### 1. Task Format
39
-
40
- All tasks use Markdown checkbox format:
41
-
42
- ```markdown
43
- - [ ] Task description #tag 📅 2026-01-15
44
- ```
45
-
46
- ### 2. Tag Conventions
47
-
48
- | Tag | Purpose |
49
- |-----|---------|
50
- | `#next` | Next task to do |
51
- | `#waiting` | Waiting on others |
52
- | `#someday` | Later task |
53
- | `#read` / `#watch` / `#listen` | Read/watch/listen lists |
54
- | `📅 YYYY-MM-DD` | Due date |
55
-
56
- ### 3. Journal Heading Structure
57
-
58
- Use the following headings in journals to categorize content. Dashboards will auto-recognize them:
59
-
60
- - `## 💼 Works` - Work tasks
61
- - `## 💡 Thoughts` - Ideas and inspirations
62
- - `## 📚 Readings` - Reading list
63
-
64
- ### 4. File Placement Rules
65
-
66
- - **All new content** → First put in journals under `10_Inbox/{member}/`
67
- - **Clear goals** → `30_Projects/`
68
- - **Long-term maintenance** → `20_Areas/`
69
- - **Reference materials** → `40_Resources/`
70
- - **No longer active** → `90_Archives/`
71
-
72
- ## Common Operations
73
-
74
- ### Creating a New Member
75
-
76
- Use CLI command:
77
-
78
- ```bash
79
- npx @our2ndbrain/cli@latest member {MemberName}
80
- ```
81
-
82
- This creates:
83
- - `10_Inbox/{MemberName}/01_Tasks.md` - Personal task dashboard
84
- - `10_Inbox/{MemberName}/09_Done.md` - Personal completion record
85
- - `.obsidian/daily-notes.json` - Configures journal to save to that member directory
86
-
87
- > 💡 Use `--no-config` option for team collaboration to avoid overwriting other members' config.
88
-
89
- ## AI Assistant Notes
90
-
91
- 1. **Don't modify Dataview queries in dashboard files**
92
- - Global dashboards: `00_Dashboard/01_All_Tasks.md` and `09_All_Done.md`
93
- - Personal dashboards: `10_Inbox/{member}/01_Tasks.md` and `09_Done.md`
94
- - These are auto-generated dashboards. Only modify tasks in journals, dashboards will auto-update.
95
-
96
- 2. **Use template when creating journals**
97
- - Template located at `99_System/Templates/tpl_daily_note.md`
98
- - Journal naming format: `YYYY-MM-DD.md`
99
-
100
- 3. **After task completion**
101
- - Change `- [ ]` to `- [x]`
102
- - Tasks plugin will auto-add completion date `✅ YYYY-MM-DD`
103
-
104
- 4. **Follow user's language preference**
105
- - Adapt responses to user's language settings
106
- - Match the language used in the conversation
107
-
108
- ## Agent Collaboration Design
109
-
110
- AI assistants and humans **coexist collaboratively** in 2ndBrain. Agents can directly operate all directories (`20_Areas/`, `30_Projects/`, `40_Resources/`, etc.), only need a shared workspace to record work logs.
111
-
112
- ### Shared Workspace
113
-
114
- All Agents share the `10_Inbox/Agents/` directory (note: plural), using a single-file Journal mode:
115
-
116
- ```
117
- 10_Inbox/Agents/
118
- └── Journal.md # All Agents' work logs (append-and-review)
119
- ```
120
-
121
- ### Journal Format
122
-
123
- Uses **append-and-review** mode:
124
- - **Append**: New content appended to file end, separated by delimiters per entry
125
- - **Review**: Periodically review TODOs, check off when complete; valuable content can be output to other directories
126
-
127
- ```markdown
128
- # Agent Journal
129
-
130
- ---
131
- 2026-01-14 15:30 | Cursor
132
-
133
- Executed xxx task...
134
-
135
- - [ ] Discovered issue #next
136
-
137
- ---
138
- 2026-01-14 16:45 | Claude Desktop
139
-
140
- Optimized yyy...
141
-
142
- ## 💡 Improvement Suggestions
143
-
144
- - Suggest zzz
145
- ```
146
-
147
- ### Why This Design?
148
-
149
- | Feature | Reason |
150
- |---------|--------|
151
- | **Shared directory** | Agents aren't "people", don't need isolated personal spaces |
152
- | **Single file** | Read once for full context, highest efficiency |
153
- | **Append-and-Review** | Simple writing + periodic organization, follows C-O-R-D workflow |
154
- | **Timestamp + Agent name** | Know who did what when |
155
-
156
- ### Review Workflow
157
-
158
- Journal content can be output to other directories during review:
159
-
160
- | Content Type | Output Target |
161
- |-------------|---------------|
162
- | Completed TODOs | Check off `[x]` stay in place |
163
- | Discovered issues/solutions | → `30_Projects/` related projects |
164
- | Reusable experience | → `40_Resources/` or `20_Areas/` |
165
- | Error post-mortem | Keep in Journal as history |
166
-
167
- ### When to Write Journal
168
-
169
- - After executing complex tasks (migration, refactoring, batch modifications)
170
- - When discovering issues that need fixing
171
- - When having improvement suggestions
172
- - When encountering failures or anomalies
173
-
174
- ### Work Principles
175
-
176
- 1. **Prefer improving tools over bypassing them** - Manual operations are non-reproducible and error-prone. When encountering scenarios not supported by tools, improve the tool first then execute.
177
- 2. **Pay attention to naming consistency** - Tool design should consider naming differences to avoid sync failures due to inconsistent naming.
178
-
179
- ### Tasks in Journal
180
-
181
- Agents can write todo tasks in Journal, Dashboard dashboards will auto-recognize:
182
-
183
- ```markdown
184
- - [ ] Discovered xxx needs fixing #next
185
- - [ ] Suggest adding yyy feature #someday 📅 2026-01-30
186
- ```
187
-
188
- > 💡 **Note**: Tasks with `#someday` tag will appear in "Future Plans" section, regardless of whether they have a due date. This is the dedicated area for "later" tasks.
189
-
190
- ## Reference Links
191
-
192
- - [README.md](README.md) - Complete project documentation
193
- - [Template repository](https://github.com/Our2ndBrain/2ndBrain-Template) - Open source template
package/CLAUDE.md DELETED
@@ -1,153 +0,0 @@
1
- # CLAUDE.md
2
-
3
- This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
-
5
- ## Project Overview
6
-
7
- **2ndBrain** is a personal knowledge management system CLI tool published as `@our2ndbrain/cli`. It combines three methodologies:
8
- - **PARA**: Projects, Areas, Resources, Archives organizational structure
9
- - **C-O-R-D**: Collect → Organize → Review → Do workflow
10
- - **Append-and-Review**: Karpathy's note-taking approach (append first, organize during review)
11
-
12
- The CLI provides an Obsidian-based template with a Node.js CLI tool for setup and management. The tool is designed for both individual and team use, with Git integration for synchronization.
13
-
14
- ## CLI Commands
15
-
16
- ### Installation and Usage
17
- ```bash
18
- # Use npx directly (recommended)
19
- npx @our2ndbrain/cli@latest <command>
20
-
21
- # Or install globally
22
- npm install -g @our2ndbrain/cli
23
- 2ndbrain <command>
24
- ```
25
-
26
- ### Available Commands
27
- - `2ndbrain init [path]` - Initialize new project from template
28
- - `2ndbrain member <name> [path]` - Add new member directory
29
- - `2ndbrain update [path]` - Update framework files with diff preview
30
- - `2ndbrain remove [path]` - Remove framework files
31
-
32
- ### Command Options
33
- **init**: `-f, --force` (overwrite), `-t, --template <path>` (custom template)
34
- **member**: `-f, --force` (overwrite), `--no-config` (skip Obsidian config)
35
- **update**: `-d, --dry-run` (preview), `-t, --template <path>` (custom template)
36
- **remove**: `-d, --dry-run` (preview), `-f, --force` (skip confirmation)
37
-
38
- ### Publishing
39
- ```bash
40
- npm version <major|minor|patch> # Updates CHANGELOG.md via scripts/version.js
41
- # postversion hook runs: git push && git push --tags && npm publish
42
- ```
43
-
44
- ## Architecture
45
-
46
- ### Entry Points
47
- - `bin/2ndbrain.js` - CLI entry point (Commander.js)
48
- - `src/index.js` - Main module that exports commands
49
-
50
- ### Core Modules
51
-
52
- **src/lib/config.js** - Framework file definitions
53
- - `FRAMEWORK_FILES`: Files managed by init/update/remove (AGENTS.md, README.md, CHANGELOG.md, CLAUDE.md, dashboards, templates)
54
- - `FRAMEWORK_DIRS`: Directories created during init (00_Dashboard, 10_Inbox/Agents, 99_System)
55
- - `USER_DATA_DIRS`: Never touched by CLI (20_Areas, 30_Projects, 40_Resources, 90_Archives)
56
- - `COPY_DIRS`: Directories copied entirely (e.g., .obsidian with plugins)
57
- - `MARKER_FILE`: `AGENTS.md` - identifies a 2ndBrain project
58
-
59
- **src/lib/files.js** - File operations
60
- - `copyFiles()` - Basic file copying
61
- - `copyFilesSmart()` - Copy with comparison, dry-run support, change tracking
62
- - `removeFiles()` - File removal with tracking
63
- - `ensureDirs()` / `removeEmptyDirs()` - Directory management
64
-
65
- **src/lib/diff.js** - File comparison utilities
66
- - Uses `diff` npm package for line/word comparison
67
- - `compareFiles()` - Detects binary/large files, compares contents
68
- - `summarizeChanges()` - Returns added/removed line counts
69
- - `generateDiff()` / `formatDiffForTerminal()` - Unified diff with colors
70
- - Large file threshold: 100KB
71
-
72
- **src/lib/prompt.js** - Interactive prompts
73
- - `confirm()` - Yes/no prompts with defaults
74
- - `select()` - Multi-option selection
75
- - `confirmBatchUpdates()` - Bulk update confirmation
76
- - Special handling for binary/large files
77
-
78
- **src/commands/init.js** - Project initialization
79
- - Validates target directory (checks for existing 2ndBrain projects or non-empty dirs)
80
- - Creates framework and user data directories
81
- - Copies framework files and .obsidian config
82
- - Creates init-only files (e.g., 10_Inbox/Agents/Journal.md)
83
-
84
- **src/commands/member.js** - Member directory creation
85
- - Validates project is a 2ndBrain project
86
- - Creates `10_Inbox/{member}/` directory
87
- - Processes template files with `{{MEMBER_NAME}}` placeholder replacement
88
- - Updates `.obsidian/daily-notes.json` (unless `--no-config`)
89
-
90
- **src/commands/update.js** - Framework file updates
91
- - Compares template files with existing files
92
- - Shows diff with colored output for changes
93
- - Supports batch (all), review (individual), or skip modes
94
- - Also updates member dashboards using latest templates
95
-
96
- **src/commands/remove.js** - Framework file removal
97
- - Removes only framework files (never user data directories)
98
- - Cleans up empty directories
99
-
100
- ### Key Design Patterns
101
-
102
- **Smart File Management**: Files are compared before copying to avoid unnecessary writes. Binary and large files are detected and handled specially.
103
-
104
- **Template System**: Member files use `{{MEMBER_NAME}}` placeholder that gets replaced during `member` command execution.
105
-
106
- **Framework vs User Data Separation**:
107
- - Framework files: Managed by CLI, can be updated/removed
108
- - User data directories: Created during init, never modified by CLI
109
- - This allows users to keep their content while updating framework
110
-
111
- **Dry Run Mode**: Both `update` and `remove` support `--dry-run` to preview changes before applying.
112
-
113
- ## Directory Structure (PARA)
114
-
115
- ```
116
- 2ndBrain/
117
- ├── 00_Dashboard/ # Task aggregation dashboards (Dataview/Tasks queries)
118
- ├── 10_Inbox/ # Collection point (daily journals)
119
- │ ├── Agents/ # AI assistant shared workspace
120
- │ └── {MemberName}/ # Each member's personal directory
121
- ├── 20_Areas/ # Long-term focus areas
122
- ├── 30_Projects/ # Goal-oriented work
123
- ├── 40_Resources/ # Reference materials
124
- ├── 90_Archives/ # Completed/inactive content
125
- └── 99_System/ # Templates and scripts
126
- ```
127
-
128
- ## Task Format Convention
129
-
130
- Tasks use Markdown checkbox format with tags and dates:
131
- ```markdown
132
- - [ ] Task description #tag 📅 YYYY-MM-DD
133
- ```
134
-
135
- Tags: `#next` (do next), `#waiting` (waiting on others), `#someday` (later), `#read`/`#watch`/`#listen` (consume lists)
136
-
137
- ## Dependencies
138
-
139
- - `commander` - CLI framework
140
- - `chalk` - Terminal colors
141
- - `fs-extra` - Enhanced file system operations
142
- - `diff` - File comparison/diff generation
143
-
144
- ## Node.js Requirement
145
-
146
- Node.js >= 16.0.0 (specified in package.json `engines`)
147
-
148
- ## Important Notes
149
-
150
- - The CLI is published as an npm package, so template files are bundled via `package.json` `files` field
151
- - `.obsidian/` directory is included in the package to provide pre-configured plugins
152
- - `AGENTS.md` serves as both documentation and the marker file for identifying 2ndBrain projects
153
- - Member directories are excluded from automatic updates (must be re-run manually if needed)