beecork 1.3.7 → 1.3.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/channels/command-handler.js +23 -21
- package/dist/cli/setup.js +3 -3
- package/dist/index.js +12 -8
- package/dist/mcp/server.js +9 -9
- package/dist/pipe/brain.js +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -24,8 +24,8 @@ Message Claude Code from Telegram at 2am — it wakes up, does the work, message
|
|
|
24
24
|
- **Virtual tabs** — Persistent Claude Code sessions with context that survives restarts.
|
|
25
25
|
- **Task scheduling** — Tell Claude Code to set up recurring tasks via MCP tools — it wakes up, runs the task, reports back.
|
|
26
26
|
- **Memory** — Cross-session memory so Claude Code never loses context.
|
|
27
|
-
- **MCP server** — 38 tools Claude Code can call to manage tabs, memory, cron jobs, watchers, media,
|
|
28
|
-
- **Smart routing** — Pipe brain routes messages to the right tab, tracks goals, learns from your usage.
|
|
27
|
+
- **MCP server** — 38 tools Claude Code can call to manage tabs, memory, cron jobs, watchers, media, folders, and more.
|
|
28
|
+
- **Smart routing** — Pipe brain routes messages to the right folder and tab, tracks goals, learns from your usage.
|
|
29
29
|
- **Background service** — Runs as a launchd (macOS), systemd (Linux), or Task Scheduler (Windows) service. Starts on login, runs silently.
|
|
30
30
|
|
|
31
31
|
## Quick Start
|
|
@@ -89,7 +89,7 @@ beecork mcp list # List MCP server configs
|
|
|
89
89
|
beecork media setup # Configure media generators
|
|
90
90
|
beecork activity # View activity summary
|
|
91
91
|
beecork history # Show activity timeline
|
|
92
|
-
beecork
|
|
92
|
+
beecork folders # List discovered folders
|
|
93
93
|
beecork machines # List registered machines
|
|
94
94
|
beecork templates # List tab templates
|
|
95
95
|
beecork store search <q> # Search community extensions
|
|
@@ -147,44 +147,46 @@ export async function handleSharedCommand(ctx, tabManager) {
|
|
|
147
147
|
}).join('\n\n');
|
|
148
148
|
return { handled: true, response: `🖥 ${machines.length} machine(s):\n\n${list}` };
|
|
149
149
|
}
|
|
150
|
-
// /projects
|
|
151
|
-
if (text === '/projects' || text.startsWith('/projects@')) {
|
|
150
|
+
// /folders (also accept legacy /projects)
|
|
151
|
+
if (text === '/folders' || text === '/projects' || text.startsWith('/folders@') || text.startsWith('/projects@')) {
|
|
152
152
|
const { listProjects } = await import('../projects/index.js');
|
|
153
153
|
const projects = listProjects();
|
|
154
154
|
if (projects.length === 0)
|
|
155
|
-
return { handled: true, response: 'No
|
|
155
|
+
return { handled: true, response: 'No folders found. Create one with /newfolder <name>' };
|
|
156
156
|
const userProjects = projects.filter((p) => p.type === 'user-project');
|
|
157
157
|
const categories = projects.filter((p) => p.type === 'category');
|
|
158
|
-
let msg = '
|
|
158
|
+
let msg = '📁 Folders:\n';
|
|
159
159
|
if (userProjects.length > 0)
|
|
160
160
|
msg += userProjects.map((p) => ` • ${p.name} — ${p.path}`).join('\n');
|
|
161
161
|
if (categories.length > 0) {
|
|
162
|
-
msg += '\n\n
|
|
162
|
+
msg += '\n\n📂 Categories:\n';
|
|
163
163
|
msg += categories.map((p) => ` • ${p.name}`).join('\n');
|
|
164
164
|
}
|
|
165
165
|
return { handled: true, response: msg };
|
|
166
166
|
}
|
|
167
|
-
// /project <name>
|
|
168
|
-
if (text.startsWith('/project ') && !text.startsWith('/projects')) {
|
|
169
|
-
const
|
|
167
|
+
// /folder <name> (also accept legacy /project <name>)
|
|
168
|
+
if ((text.startsWith('/folder ') && !text.startsWith('/folders')) || (text.startsWith('/project ') && !text.startsWith('/projects'))) {
|
|
169
|
+
const prefix = text.startsWith('/folder ') ? '/folder ' : '/project ';
|
|
170
|
+
const name = text.slice(prefix.length).trim();
|
|
170
171
|
const { getProject, setUserContext } = await import('../projects/index.js');
|
|
171
172
|
const project = getProject(name);
|
|
172
173
|
if (!project)
|
|
173
|
-
return { handled: true, response: `
|
|
174
|
+
return { handled: true, response: `Folder "${name}" not found. Use /folders to list or /newfolder to create.` };
|
|
174
175
|
setUserContext(userId, project.name, project.name);
|
|
175
|
-
return { handled: true, response: `Switched to
|
|
176
|
+
return { handled: true, response: `Switched to folder: ${project.name}\nPath: ${project.path}\n\nNext messages will work in this folder.` };
|
|
176
177
|
}
|
|
177
|
-
// /
|
|
178
|
-
if (text.startsWith('/newproject ')) {
|
|
179
|
-
const
|
|
178
|
+
// /newfolder <name> [path] (also accept legacy /newproject)
|
|
179
|
+
if (text.startsWith('/newfolder ') || text.startsWith('/newproject ')) {
|
|
180
|
+
const prefix = text.startsWith('/newfolder ') ? '/newfolder ' : '/newproject ';
|
|
181
|
+
const parts = text.slice(prefix.length).trim().split(/\s+/);
|
|
180
182
|
const name = parts[0];
|
|
181
183
|
const customPath = parts[1] || undefined;
|
|
182
184
|
if (!name)
|
|
183
|
-
return { handled: true, response: 'Usage: /
|
|
185
|
+
return { handled: true, response: 'Usage: /newfolder <name> [path]' };
|
|
184
186
|
const { createProject, setUserContext } = await import('../projects/index.js');
|
|
185
187
|
const project = createProject(name, customPath);
|
|
186
188
|
setUserContext(userId, project.name, project.name);
|
|
187
|
-
return { handled: true, response: `✓
|
|
189
|
+
return { handled: true, response: `✓ Folder "${name}" created at ${project.path}\nSwitched to this folder.` };
|
|
188
190
|
}
|
|
189
191
|
// /close <tab>
|
|
190
192
|
if (text.startsWith('/close ')) {
|
|
@@ -197,16 +199,16 @@ export async function handleSharedCommand(ctx, tabManager) {
|
|
|
197
199
|
const closed = closeTab(tabNameToClose);
|
|
198
200
|
return { handled: true, response: closed ? `Tab "${tabNameToClose}" permanently closed. History deleted.` : `Tab "${tabNameToClose}" not found.` };
|
|
199
201
|
}
|
|
200
|
-
// /fresh <
|
|
202
|
+
// /fresh <folder>
|
|
201
203
|
if (text.startsWith('/fresh ')) {
|
|
202
|
-
const
|
|
204
|
+
const folderName = text.slice(7).trim();
|
|
203
205
|
const { getProject, setUserContext } = await import('../projects/index.js');
|
|
204
|
-
const project = getProject(
|
|
206
|
+
const project = getProject(folderName);
|
|
205
207
|
if (!project)
|
|
206
|
-
return { handled: true, response: `
|
|
207
|
-
const freshTabName = `${
|
|
208
|
+
return { handled: true, response: `Folder "${folderName}" not found.` };
|
|
209
|
+
const freshTabName = `${folderName}-${Date.now().toString(36).slice(-4)}`;
|
|
208
210
|
setUserContext(userId, project.name, freshTabName);
|
|
209
|
-
return { handled: true, response: `Fresh start in "${
|
|
211
|
+
return { handled: true, response: `Fresh start in "${folderName}" (tab: ${freshTabName})\nSend your message now.` };
|
|
210
212
|
}
|
|
211
213
|
return { handled: false };
|
|
212
214
|
}
|
package/dist/cli/setup.js
CHANGED
|
@@ -202,9 +202,9 @@ export async function setupWizard() {
|
|
|
202
202
|
console.log(' beecork dashboard — open web control panel');
|
|
203
203
|
console.log(' beecork quickstart — full getting-started checklist');
|
|
204
204
|
console.log('');
|
|
205
|
-
console.log(' ★ Recommended: Smart
|
|
206
|
-
console.log(' If you work
|
|
207
|
-
console.log('
|
|
205
|
+
console.log(' ★ Recommended: Smart folder routing');
|
|
206
|
+
console.log(' If you work in multiple folders, Beecork can auto-detect which');
|
|
207
|
+
console.log(' folder you mean and route messages to the right tab.');
|
|
208
208
|
console.log(' Run: beecork pipe setup');
|
|
209
209
|
console.log('');
|
|
210
210
|
console.log(' Add more channels:');
|
package/dist/index.js
CHANGED
|
@@ -170,8 +170,8 @@ program
|
|
|
170
170
|
const ask = (q, def) => new Promise(r => rl.question(def ? `${q} [${def}]: ` : `${q}: `, a => r(a.trim() || def || '')));
|
|
171
171
|
console.log('\nWhatsApp Setup\n');
|
|
172
172
|
console.log(' WhatsApp connects via QR code scanning (like WhatsApp Web).');
|
|
173
|
-
console.log('
|
|
174
|
-
console.log(' Scan it with your phone to
|
|
173
|
+
console.log(' After setup, run "beecork start" and the QR code will appear');
|
|
174
|
+
console.log(' in your terminal. Scan it with your phone to pair.\n');
|
|
175
175
|
const number = await ask('Your WhatsApp phone number (e.g., 14155551234)');
|
|
176
176
|
if (!number) {
|
|
177
177
|
console.log('No number provided. Cancelled.');
|
|
@@ -188,7 +188,10 @@ program
|
|
|
188
188
|
allowedNumbers: [number],
|
|
189
189
|
};
|
|
190
190
|
saveConfig(config);
|
|
191
|
-
console.log('\n✓ WhatsApp configured.
|
|
191
|
+
console.log('\n✓ WhatsApp configured.');
|
|
192
|
+
console.log(' Next: run "beecork start" — the QR code will appear in your terminal.');
|
|
193
|
+
console.log(' Scan it with your phone to pair. Once paired, press Ctrl+C and');
|
|
194
|
+
console.log(' run "beecork start" again for background operation.\n');
|
|
192
195
|
rl.close();
|
|
193
196
|
});
|
|
194
197
|
program
|
|
@@ -394,18 +397,19 @@ program
|
|
|
394
397
|
console.log('');
|
|
395
398
|
});
|
|
396
399
|
program
|
|
397
|
-
.command('
|
|
398
|
-
.
|
|
400
|
+
.command('folders')
|
|
401
|
+
.alias('projects')
|
|
402
|
+
.description('List all discovered folders')
|
|
399
403
|
.action(async () => {
|
|
400
404
|
const { listProjects } = await import('./projects/index.js');
|
|
401
405
|
const projects = listProjects();
|
|
402
406
|
if (projects.length === 0) {
|
|
403
|
-
console.log('No
|
|
407
|
+
console.log('No folders found. Start the daemon to discover folders.');
|
|
404
408
|
return;
|
|
405
409
|
}
|
|
406
|
-
console.log(`\n${projects.length}
|
|
410
|
+
console.log(`\n${projects.length} folder(s):\n`);
|
|
407
411
|
for (const p of projects) {
|
|
408
|
-
const icon = p.type === 'category' ? '
|
|
412
|
+
const icon = p.type === 'category' ? '📂' : '📁';
|
|
409
413
|
console.log(` ${icon} ${p.name} — ${p.path}`);
|
|
410
414
|
}
|
|
411
415
|
console.log('');
|
package/dist/mcp/server.js
CHANGED
|
@@ -81,7 +81,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
81
81
|
type: 'object',
|
|
82
82
|
properties: {
|
|
83
83
|
content: { type: 'string', description: 'The fact or information to remember' },
|
|
84
|
-
scope: { type: 'string', enum: ['global', 'project', 'tab', 'auto'], description: 'Where to store: global (about the user), project (about this
|
|
84
|
+
scope: { type: 'string', enum: ['global', 'project', 'tab', 'auto'], description: 'Where to store: global (about the user), project (about this folder), tab (about this conversation), or auto (Claude decides)' },
|
|
85
85
|
category: { type: 'string', description: 'For global scope: people, preferences, routines, or general' },
|
|
86
86
|
},
|
|
87
87
|
required: ['content'],
|
|
@@ -324,7 +324,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
324
324
|
},
|
|
325
325
|
{
|
|
326
326
|
name: 'beecork_machines',
|
|
327
|
-
description: 'List registered machines and their
|
|
327
|
+
description: 'List registered machines and their folder paths. Shows which machine handles which folders.',
|
|
328
328
|
inputSchema: { type: 'object', properties: {} },
|
|
329
329
|
},
|
|
330
330
|
{
|
|
@@ -352,11 +352,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
352
352
|
},
|
|
353
353
|
{
|
|
354
354
|
name: 'beecork_project_create',
|
|
355
|
-
description: '
|
|
355
|
+
description: 'Register a new folder in the workspace',
|
|
356
356
|
inputSchema: {
|
|
357
357
|
type: 'object',
|
|
358
358
|
properties: {
|
|
359
|
-
name: { type: 'string', description: '
|
|
359
|
+
name: { type: 'string', description: 'Folder name' },
|
|
360
360
|
path: { type: 'string', description: 'Optional: custom path. Defaults to workspace root.' },
|
|
361
361
|
},
|
|
362
362
|
required: ['name'],
|
|
@@ -364,7 +364,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
364
364
|
},
|
|
365
365
|
{
|
|
366
366
|
name: 'beecork_project_list',
|
|
367
|
-
description: 'List all known
|
|
367
|
+
description: 'List all known folders and categories',
|
|
368
368
|
inputSchema: { type: 'object', properties: {} },
|
|
369
369
|
},
|
|
370
370
|
{
|
|
@@ -425,11 +425,11 @@ server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
|
425
425
|
},
|
|
426
426
|
{
|
|
427
427
|
name: 'beecork_knowledge',
|
|
428
|
-
description: 'List all knowledge Beecork has about the current context (global +
|
|
428
|
+
description: 'List all knowledge Beecork has about the current context (global + folder + tab)',
|
|
429
429
|
inputSchema: {
|
|
430
430
|
type: 'object',
|
|
431
431
|
properties: {
|
|
432
|
-
scope: { type: 'string', enum: ['global', 'project', 'tab', 'all'], description: 'Which layer to show (default: all)' },
|
|
432
|
+
scope: { type: 'string', enum: ['global', 'project', 'tab', 'all'], description: 'Which layer to show: global, project (folder), tab, or all (default: all)' },
|
|
433
433
|
},
|
|
434
434
|
},
|
|
435
435
|
},
|
|
@@ -793,13 +793,13 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
|
793
793
|
const { name, path: customPath } = args;
|
|
794
794
|
const { createProject } = await import('../projects/index.js');
|
|
795
795
|
const project = createProject(name, customPath);
|
|
796
|
-
return ok(`
|
|
796
|
+
return ok(`Folder "${name}" registered at ${project.path}`);
|
|
797
797
|
}
|
|
798
798
|
case 'beecork_project_list': {
|
|
799
799
|
const { listProjects } = await import('../projects/index.js');
|
|
800
800
|
const projects = listProjects();
|
|
801
801
|
if (projects.length === 0)
|
|
802
|
-
return ok('No
|
|
802
|
+
return ok('No folders discovered. Create one with beecork_project_create.');
|
|
803
803
|
const lines = projects.map(p => `${p.type === 'category' ? '📁' : '📦'} ${p.name} — ${p.path}`);
|
|
804
804
|
return ok(lines.join('\n'));
|
|
805
805
|
}
|
package/dist/pipe/brain.js
CHANGED
|
@@ -25,13 +25,13 @@ export class PipeBrain {
|
|
|
25
25
|
const route = await this.route(message, decisions);
|
|
26
26
|
// Step 2: Ensure the tab exists with the right working directory
|
|
27
27
|
if (route.projectPath) {
|
|
28
|
-
this.tabManager.ensureTab(route.tabName);
|
|
28
|
+
this.tabManager.ensureTab(route.tabName, route.projectPath);
|
|
29
29
|
this.memory.updateProjectLastUsed(route.projectPath);
|
|
30
30
|
}
|
|
31
31
|
// Step 3: Send to Claude Code
|
|
32
32
|
let result;
|
|
33
33
|
try {
|
|
34
|
-
result = await this.tabManager.sendMessage(route.tabName, message, { skipExtraction: true });
|
|
34
|
+
result = await this.tabManager.sendMessage(route.tabName, message, { skipExtraction: true, projectPath: route.projectPath ?? undefined });
|
|
35
35
|
}
|
|
36
36
|
catch (err) {
|
|
37
37
|
return {
|