@lernstoff/cli 0.1.0-beta.1 → 0.1.0-beta.3

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/dist/bin.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env node
2
+ import { createRequire } from "node:module";
2
3
  import { closeSync, copyFileSync, existsSync, mkdirSync, openSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
3
4
  import { basename, dirname, join, resolve } from "node:path";
4
5
  import { execSync, spawn } from "node:child_process";
@@ -646,6 +647,14 @@ async function lintCmd(vaultPath, options = {}) {
646
647
  return result;
647
648
  }
648
649
  // src/bin.ts
650
+ const require = createRequire(import.meta.url);
651
+ const CLI_VERSION = (() => {
652
+ try {
653
+ return require("../package.json").version || "0.0.0";
654
+ } catch {
655
+ return "0.0.0";
656
+ }
657
+ })();
649
658
  function parseArgs(args) {
650
659
  const flags = {};
651
660
  const positional = [];
@@ -667,6 +676,10 @@ function parseArgs(args) {
667
676
  }
668
677
  async function main() {
669
678
  const { flags, positional } = parseArgs(process.argv.slice(2));
679
+ if (flags.version || flags.v || positional[0] === "--version" || positional[0] === "-v") {
680
+ console.log(CLI_VERSION);
681
+ return;
682
+ }
670
683
  const vaultPath = resolve(typeof flags.vault === "string" ? flags.vault : process.cwd());
671
684
  const command = positional[0] || "help";
672
685
  const subCommand = positional[1];
@@ -874,7 +887,7 @@ async function main() {
874
887
  }
875
888
  break;
876
889
  default: console.log(`
877
- 🧠 lernstoff-wiki (v0.1.0-beta.1) - Headless Cognitive Selective Note-Taking Engine
890
+ 🧠 lernstoff-wiki (v${CLI_VERSION}) - Headless Cognitive Selective Note-Taking Engine
878
891
 
879
892
  Usage:
880
893
  lernstoff init [--vault <path>]
package/dist/bin.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.mjs","names":[],"sources":["../src/daemon-pid.ts","../src/stdio-proxy.ts","../src/service-manager.ts","../src/agent-installer.ts","../src/cognitive-cmds.ts","../src/bin.ts"],"sourcesContent":["import { existsSync, readFileSync, unlinkSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport { LERNSTOFF_DIR } from \"@lernstoff/core\";\n\n/**\n * Check if a process ID is currently running in the OS.\n */\nexport function isPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read the full command line of a process by PID across macOS, Linux, and Windows.\n */\nexport function readProcessCmdline(pid: number): string | null {\n try {\n if (process.platform === \"win32\") {\n const output = execSync(`wmic process where ProcessId=${pid} get CommandLine /value`, {\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 1000,\n }).toString(\"utf-8\");\n const match = output.match(/CommandLine=(.*)/i);\n return match ? match[1]!.trim() : null;\n } else {\n const output = execSync(`ps -p ${pid} -o command=`, {\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 1000,\n }).toString(\"utf-8\");\n return output.trim();\n }\n } catch {\n return null;\n }\n}\n\n/**\n * Verifies process identity to prevent false positives from recycled PIDs.\n * Modeled on qmd/src/cli/mcp-pid.ts#L74-L86.\n */\nexport function looksLikeLernstoffDaemon(cmdline: string): boolean {\n const lower = cmdline.toLowerCase();\n return (\n lower.includes(\"lernstoff\") ||\n lower.includes(\"daemon-server\") ||\n lower.includes(\"@lernstoff/cli\") ||\n lower.includes(\"lernstoff-wiki\")\n );\n}\n\nexport interface RunningDaemonInfo {\n pid: number;\n port: number;\n}\n\n/**\n * Inspects <vault>/.lernstoff/daemon.pid and daemon.port to check if the daemon is alive.\n * If the process is dead or stale, cleans up the files and returns null.\n */\nexport function getRunningDaemonInfo(vaultPath: string): RunningDaemonInfo | null {\n const resolved = resolve(vaultPath);\n const lernstoffDir = join(resolved, LERNSTOFF_DIR);\n const pidFile = join(lernstoffDir, \"daemon.pid\");\n const portFile = join(lernstoffDir, \"daemon.port\");\n\n if (!existsSync(pidFile)) {\n return null;\n }\n\n let pid: number;\n try {\n pid = parseInt(readFileSync(pidFile, \"utf-8\").trim(), 10);\n } catch {\n return null;\n }\n\n if (!isPidAlive(pid)) {\n // Stale PID file, clean up\n try {\n unlinkSync(pidFile);\n } catch {}\n try {\n if (existsSync(portFile)) unlinkSync(portFile);\n } catch {}\n return null;\n }\n\n const cmdline = readProcessCmdline(pid);\n if (cmdline && !looksLikeLernstoffDaemon(cmdline)) {\n // Process ID was recycled by another unrelated process\n try {\n unlinkSync(pidFile);\n } catch {}\n try {\n if (existsSync(portFile)) unlinkSync(portFile);\n } catch {}\n return null;\n }\n\n let port = 8188;\n if (existsSync(portFile)) {\n try {\n port = parseInt(readFileSync(portFile, \"utf-8\").trim(), 10) || 8188;\n } catch {}\n }\n\n return { pid, port };\n}\n\n/**\n * Gracefully kill a running daemon process.\n */\nexport function killDaemonProcess(pid: number, timeoutMs = 3000): boolean {\n if (!isPidAlive(pid)) return true;\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {\n return !isPidAlive(pid);\n }\n\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (!isPidAlive(pid)) return true;\n try {\n execSync(\"sleep 0.05\");\n } catch {}\n }\n\n // Force kill if SIGTERM didn't succeed\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {}\n\n return !isPidAlive(pid);\n}\n","import { createInterface } from \"node:readline\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/server/stdio\";\nimport { createLernstoffMcpServer } from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\n/**\n * Runs MCP over stdio.\n * If the Vault's background daemon is already running, proxies JSON-RPC over HTTP\n * with zero memory footprint; otherwise boots an in-process MCP server instance.\n */\nexport async function runMcpStdio(vaultPath: string): Promise<void> {\n const daemonInfo = getRunningDaemonInfo(vaultPath);\n\n if (daemonInfo) {\n // Mode A: Stdio-to-HTTP Proxy (0 Memory Overhead)\n const daemonUrl = `http://127.0.0.1:${daemonInfo.port}/mcp`;\n\n const rl = createInterface({\n input: process.stdin,\n terminal: false,\n });\n\n rl.on(\"line\", async (line) => {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n try {\n const res = await fetch(daemonUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: trimmed,\n });\n\n const contentType = res.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"json\")) {\n const bodyText = await res.text();\n if (bodyText) {\n process.stdout.write(`${bodyText}\\n`);\n }\n } else {\n // Streamable response\n const reader = res.body?.getReader();\n if (reader) {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n process.stdout.write(value);\n }\n }\n }\n } catch (err: any) {\n const errorRpc = {\n jsonrpc: \"2.0\",\n id: null,\n error: {\n code: -32603,\n message: `Daemon proxy error: ${err.message}`,\n },\n };\n process.stdout.write(`${JSON.stringify(errorRpc)}\\n`);\n }\n });\n\n return;\n }\n\n // Mode B: Direct in-process Stdio MCP Server\n const server = createLernstoffMcpServer({ vaultPath });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","import { existsSync, writeFileSync, unlinkSync, mkdirSync } from \"node:fs\";\nimport { join, resolve, basename } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { execSync } from \"node:child_process\";\nimport { VaultOps } from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\nexport interface ServiceStatus {\n installed: boolean;\n running: boolean;\n servicePath?: string;\n platform: string;\n pid?: number;\n port?: number;\n}\n\nexport class ServiceManager {\n public static getServiceSlug(vaultPath: string): string {\n const name = basename(resolve(vaultPath));\n return VaultOps.slugify(name || \"default\");\n }\n\n public static getLaunchdPlistPath(vaultPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n return join(homedir(), \"Library/LaunchAgents\", `ai.lernstoff.wiki.${slug}.plist`);\n }\n\n public static getSystemdServicePath(vaultPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n return join(homedir(), \".config/systemd/user\", `lernstoff-wiki@${slug}.service`);\n }\n\n public static generateLaunchdPlist(vaultPath: string, cliPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n const absVault = resolve(vaultPath);\n const logPath = join(absVault, \".lernstoff\", \"daemon.log\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>ai.lernstoff.wiki.${slug}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${process.execPath}</string>\n <string>${cliPath}</string>\n <string>server</string>\n <string>start</string>\n <string>--foreground</string>\n <string>--vault</string>\n <string>${absVault}</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>${logPath}</string>\n <key>StandardErrorPath</key>\n <string>${logPath}</string>\n <key>WorkingDirectory</key>\n <string>${absVault}</string>\n</dict>\n</plist>\n`;\n }\n\n public static generateSystemdService(vaultPath: string, cliPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n const absVault = resolve(vaultPath);\n const logPath = join(absVault, \".lernstoff\", \"daemon.log\");\n\n return `[Unit]\nDescription=Lernstoff Wiki Headless Cognitive Engine (${slug})\nAfter=network.target\n\n[Service]\nType=simple\nWorkingDirectory=${absVault}\nExecStart=${process.execPath} ${cliPath} server start --foreground --vault ${absVault}\nRestart=always\nRestartSec=5\nStandardOutput=append:${logPath}\nStandardError=append:${logPath}\n\n[Install]\nWantedBy=default.target\n`;\n }\n\n /**\n * Install OS boot auto-start service for the target Vault.\n */\n public static async installService(\n vaultPath: string,\n cliPath = process.argv[1] || \"lernstoff\",\n ): Promise<{ success: boolean; servicePath: string; platform: string }> {\n const absVault = resolve(vaultPath);\n const platform = process.platform;\n\n if (platform === \"darwin\") {\n const plistPath = ServiceManager.getLaunchdPlistPath(absVault);\n mkdirSync(join(homedir(), \"Library/LaunchAgents\"), { recursive: true });\n const plistXml = ServiceManager.generateLaunchdPlist(absVault, cliPath);\n writeFileSync(plistPath, plistXml, \"utf-8\");\n\n try {\n execSync(`launchctl load \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch {\n // May already be loaded or in dry-run\n }\n\n return { success: true, servicePath: plistPath, platform: \"darwin\" };\n }\n\n if (platform === \"linux\") {\n const servicePath = ServiceManager.getSystemdServicePath(absVault);\n mkdirSync(join(homedir(), \".config/systemd/user\"), { recursive: true });\n const serviceUnit = ServiceManager.generateSystemdService(absVault, cliPath);\n writeFileSync(servicePath, serviceUnit, \"utf-8\");\n\n try {\n execSync(\"systemctl --user daemon-reload\", { stdio: \"ignore\" });\n execSync(`systemctl --user enable --now \"${basename(servicePath)}\"`, { stdio: \"ignore\" });\n } catch {}\n\n return { success: true, servicePath, platform: \"linux\" };\n }\n\n // Windows or other fallback\n const fallbackPath = join(absVault, \".lernstoff\", \"autostart.cmd\");\n writeFileSync(\n fallbackPath,\n `@echo off\\n\"${process.execPath}\" \"${cliPath}\" server start --foreground --vault \"${absVault}\"\\n`,\n \"utf-8\",\n );\n return { success: true, servicePath: fallbackPath, platform: \"win32\" };\n }\n\n /**\n * Uninstall and deregister the OS boot auto-start service.\n */\n public static async uninstallService(\n vaultPath: string,\n ): Promise<{ success: boolean; servicePath?: string }> {\n const absVault = resolve(vaultPath);\n const platform = process.platform;\n\n if (platform === \"darwin\") {\n const plistPath = ServiceManager.getLaunchdPlistPath(absVault);\n if (existsSync(plistPath)) {\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch {}\n try {\n unlinkSync(plistPath);\n } catch {}\n return { success: true, servicePath: plistPath };\n }\n } else if (platform === \"linux\") {\n const servicePath = ServiceManager.getSystemdServicePath(absVault);\n if (existsSync(servicePath)) {\n try {\n execSync(`systemctl --user stop \"${basename(servicePath)}\"`, { stdio: \"ignore\" });\n execSync(`systemctl --user disable \"${basename(servicePath)}\"`, { stdio: \"ignore\" });\n } catch {}\n try {\n unlinkSync(servicePath);\n } catch {}\n return { success: true, servicePath };\n }\n }\n\n return { success: true };\n }\n\n /**\n * Get service registration status and current running daemon info.\n */\n public static async getServiceStatus(vaultPath: string): Promise<ServiceStatus> {\n const absVault = resolve(vaultPath);\n const platform = process.platform;\n let installed = false;\n let servicePath: string | undefined;\n\n if (platform === \"darwin\") {\n servicePath = ServiceManager.getLaunchdPlistPath(absVault);\n installed = existsSync(servicePath);\n } else if (platform === \"linux\") {\n servicePath = ServiceManager.getSystemdServicePath(absVault);\n installed = existsSync(servicePath);\n }\n\n const daemonInfo = getRunningDaemonInfo(absVault);\n\n return {\n installed,\n running: !!daemonInfo,\n servicePath: installed ? servicePath : undefined,\n platform,\n pid: daemonInfo?.pid,\n port: daemonInfo?.port,\n };\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, resolve, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { QmdBridge, LERNSTOFF_DIR } from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\nexport const DEFAULT_SKILL_MD = `---\nname: lernstoff-wiki\ndescription: Headless Cognitive Selective Note-Taking Protocol for AI Agents and Obsidian. Use when reading documentation, analyzing papers, researching concepts, managing curiosity inquiry trees, verifying cognitive deltas, and creating evergreen proposition notes.\n---\n\n# lernstoff-wiki Cognitive Selective Note-Taking Protocol\n\nWhen pair-programming, exploring codebases, reading papers, or synthesizing architecture decisions, follow this 4-step selective note-taking protocol to avoid information hoarding (\"Collector's Fallacy\") and keep the Obsidian Vault high-signal.\n\n## Protocol Workflow\n1. Step 1: Probe Cognitive Delta (lernstoff_probe_delta) - NEVER write notes directly to disk.\n2. Step 2: Socratic 4-Question Defense (Q1: Delta, Q2: Belief update, Q3: >= 2 outbound links, Q4: Proposition-as-Title).\n3. Step 3: Crystallize Proposition Note (lernstoff_crystallize_note).\n4. Step 4: Fast Scratchpad Consolidation (lernstoff_consolidate_scratchpad).\n`;\n\nexport interface InstallAgentOptions {\n target: \"all\" | \"claude\" | \"cursor\" | \"antigravity\";\n vaultPath: string;\n}\n\nexport interface DoctorReport {\n nodeVersion: string;\n platform: string;\n arch: string;\n vaultPath: string;\n vaultInitialized: boolean;\n daemonRunning: boolean;\n daemonPid?: number;\n daemonPort?: number;\n sqlitePresent: boolean;\n configValid: boolean;\n models: Record<string, string>;\n}\n\nexport class AgentInstaller {\n public static getMcpConfig(vaultPath: string): { command: string; args: string[] } {\n return {\n command: \"lernstoff\",\n args: [\"mcp\", \"--vault\", resolve(vaultPath)],\n };\n }\n\n public static installSkill(\n target: \"all\" | \"claude\" | \"cursor\" | \"antigravity\",\n vaultPath: string,\n ): string[] {\n const absVault = resolve(vaultPath);\n const installedPaths: string[] = [];\n\n // Resolve SKILL.md template from repo if available, else fallback to embedded\n let skillContent = DEFAULT_SKILL_MD;\n const localSkill = join(absVault, \"skills/lernstoff-wiki/SKILL.md\");\n if (existsSync(localSkill)) {\n try {\n skillContent = readFileSync(localSkill, \"utf-8\");\n } catch {}\n }\n\n const targets: Record<string, string[]> = {\n claude: [join(homedir(), \".claude/skills/lernstoff-wiki/SKILL.md\")],\n antigravity: [join(homedir(), \".gemini/config/skills/lernstoff-wiki/SKILL.md\")],\n cursor: [\n join(absVault, \".cursor/skills/lernstoff-wiki/SKILL.md\"),\n join(homedir(), \".cursor/skills/lernstoff-wiki/SKILL.md\"),\n ],\n };\n\n const keys = target === \"all\" ? Object.keys(targets) : [target];\n for (const key of keys) {\n const paths = targets[key] || [];\n for (const p of paths) {\n try {\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, skillContent, \"utf-8\");\n installedPaths.push(p);\n } catch {}\n }\n }\n\n return installedPaths;\n }\n\n public static installMcp(\n target: \"all\" | \"claude\" | \"cursor\" | \"antigravity\",\n vaultPath: string,\n ): string[] {\n const absVault = resolve(vaultPath);\n const mcpEntry = AgentInstaller.getMcpConfig(absVault);\n const configuredFiles: string[] = [];\n\n const configFiles: Record<string, string[]> = {\n claude: [join(homedir(), \".claude.json\"), join(absVault, \".mcp.json\")],\n cursor: [join(absVault, \".cursor/mcp.json\"), join(homedir(), \".cursor/mcp.json\")],\n antigravity: [join(homedir(), \".gemini/antigravity/mcp_config.json\")],\n };\n\n const keys = target === \"all\" ? Object.keys(configFiles) : [target];\n for (const key of keys) {\n const files = configFiles[key] || [];\n for (const file of files) {\n try {\n mkdirSync(dirname(file), { recursive: true });\n let json: any = {};\n if (existsSync(file)) {\n try {\n json = JSON.parse(readFileSync(file, \"utf-8\"));\n } catch {\n json = {};\n }\n }\n\n if (!json.mcpServers) json.mcpServers = {};\n json.mcpServers[\"lernstoff\"] = mcpEntry;\n\n writeFileSync(file, JSON.stringify(json, null, 2), \"utf-8\");\n configuredFiles.push(file);\n } catch {}\n }\n }\n\n return configuredFiles;\n }\n\n public static async runDoctor(options: {\n vaultPath: string;\n pullModels?: boolean;\n cleanup?: boolean;\n }): Promise<DoctorReport> {\n const absVault = resolve(options.vaultPath);\n const lernstoffDir = join(absVault, LERNSTOFF_DIR);\n const configFile = join(lernstoffDir, \"config.json\");\n const sqliteFile = join(lernstoffDir, \"index.sqlite\");\n\n const vaultInitialized = existsSync(configFile);\n const sqlitePresent = existsSync(sqliteFile);\n const daemonInfo = getRunningDaemonInfo(absVault);\n\n let models: Record<string, string> = {};\n if (vaultInitialized) {\n try {\n const conf = JSON.parse(readFileSync(configFile, \"utf-8\"));\n models = conf.models || {};\n } catch {}\n }\n\n if (options.cleanup && sqlitePresent) {\n try {\n const bridge = new QmdBridge({ vaultPath: absVault });\n const store = await bridge.getStore();\n // Trigger SQLite vacuum and cleanup if supported by store\n if (typeof (store as any).cleanup === \"function\") {\n await (store as any).cleanup();\n }\n await bridge.close();\n } catch {}\n }\n\n if (options.pullModels) {\n // In offline/test environments, verify model paths exist or trigger download\n }\n\n return {\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n vaultPath: absVault,\n vaultInitialized,\n daemonRunning: !!daemonInfo,\n daemonPid: daemonInfo?.pid,\n daemonPort: daemonInfo?.port,\n sqlitePresent,\n configValid: vaultInitialized,\n models,\n };\n }\n}\n","import { resolve, join } from \"node:path\";\nimport { readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport {\n VaultOps,\n QmdBridge,\n loadConfig,\n parseScratchpad,\n formatScratchpad,\n type ScratchpadEntry,\n} from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\n/**\n * Builds editor URI (e.g. obsidian://open?path={path}) for terminal hyperlinks.\n * Modeled on qmd/src/cli/qmd.ts#L2660-L2675.\n */\nexport function buildEditorUri(template: string, absPath: string, line = 1, col = 1): string {\n return template\n .replace(\"{path}\", encodeURIComponent(absPath))\n .replace(\"{line}\", String(line))\n .replace(\"{col}\", String(col));\n}\n\n/**\n * OSC-8 terminal hyperlink format.\n */\nexport function termLink(\n text: string,\n url: string,\n isTTY: boolean = !!process.stdout.isTTY,\n): string {\n if (!isTTY) return text;\n return `\\x1b]8;;${url}\\x07${text}\\x1b]8;;\\x07`;\n}\n\nexport async function searchCmd(\n vaultPath: string,\n query: string,\n options: { lex?: boolean; vec?: boolean; ppr?: boolean; limit?: number; json?: boolean } = {},\n): Promise<any> {\n const absVault = resolve(vaultPath);\n const config = loadConfig(absVault);\n const limit = options.limit || 5;\n\n let daemonInfo = getRunningDaemonInfo(absVault);\n let searchResult: any;\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/search`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n queries: [{ type: options.lex ? \"lex\" : \"vec\", query }],\n limit,\n }),\n });\n searchResult = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const bridge = new QmdBridge({ vaultPath: absVault, config });\n try {\n searchResult = await bridge.search({\n queries: [{ type: options.lex ? \"lex\" : \"vec\", query }],\n limit,\n });\n } finally {\n await bridge.close();\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(searchResult, null, 2));\n return searchResult;\n }\n\n const hits = Array.isArray(searchResult) ? searchResult : searchResult.directHits || [];\n if (hits.length === 0) {\n console.log(`No results found for \"${query}\".`);\n return hits;\n }\n\n console.log(`\\nšŸ” Found ${hits.length} note(s) for \"${query}\":\\n`);\n for (const hit of hits) {\n const filePath = hit.displayPath || hit.file || \"\";\n const fullPath = join(absVault, filePath);\n const link = termLink(filePath, buildEditorUri(config.paths.editorUriTemplate, fullPath));\n const title = hit.title || filePath;\n const score = hit.score !== undefined ? ` (score: ${(hit.score * 100).toFixed(1)}%)` : \"\";\n console.log(` • ${title}${score}`);\n console.log(` ${link}\\n`);\n }\n\n return searchResult;\n}\n\nexport async function inquiryCmd(\n vaultPath: string,\n action: \"list\" | \"add\" | \"close\" | \"reopen\",\n textOrId?: string,\n options: { json?: boolean } = {},\n): Promise<any> {\n const absVault = resolve(vaultPath);\n let daemonInfo = getRunningDaemonInfo(absVault);\n let result: any;\n\n const payload: any = { action };\n if (action === \"add\") payload.question = textOrId;\n if (action === \"close\" || action === \"reopen\") payload.id = textOrId;\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/inquiries`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n result = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const ops = new VaultOps(absVault);\n result = await ops.manageInquiries(payload);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return result;\n }\n\n if (action === \"list\" && Array.isArray(result)) {\n console.log(`\\n🧠 Active Inquiry Tree (${result.length} questions):\\n`);\n for (const inq of result) {\n const statusIcon = inq.status === \"OPEN\" ? \"🟢\" : \"⚪\";\n console.log(` ${statusIcon} [${inq.id || \"#\"}] ${inq.question}`);\n if (inq.supportingNoteCount > 0) {\n console.log(` ↳ ${inq.supportingNoteCount} supporting proposition note(s)`);\n }\n }\n console.log(\"\");\n } else {\n console.log(`Inquiry updated:`, result);\n }\n\n return result;\n}\n\nexport async function scratchpadCmd(\n vaultPath: string,\n action: \"list\" | \"add\" | \"consolidate\" | \"gc\",\n text?: string,\n options: { json?: boolean } = {},\n): Promise<any> {\n const absVault = resolve(vaultPath);\n const config = loadConfig(absVault);\n const scratchFile = join(absVault, config.paths.scratchpadFile);\n\n if (action === \"add\") {\n if (!text) throw new Error(\"Text is required for scratchpad add.\");\n let entries: ScratchpadEntry[] = [];\n if (existsSync(scratchFile)) {\n entries = parseScratchpad(readFileSync(scratchFile, \"utf-8\"));\n }\n entries.push({\n firstSeen: new Date().toISOString().slice(0, 10),\n claim: text.trim(),\n hitCount: 1,\n relatedEntities: [],\n sources: [\"cli\"],\n status: \"DEFERRED\",\n });\n writeFileSync(scratchFile, formatScratchpad(entries), \"utf-8\");\n console.log(`Recorded note to ${config.paths.scratchpadFile}`);\n return { added: text };\n }\n\n let daemonInfo = getRunningDaemonInfo(absVault);\n let result: any;\n const opAction = action === \"gc\" ? \"gc\" : \"inspect\";\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/scratchpad`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ action: opAction }),\n });\n result = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const ops = new VaultOps(absVault);\n result = await ops.consolidateScratchpad({ action: opAction });\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return result;\n }\n\n console.log(\n `\\n⚔ Scratchpad Buffer (Total: ${result.activeCount}, Ready for Promotion: ${result.promotions.length}):`,\n );\n for (const p of result.promotions) {\n console.log(\n ` ⭐ [PROMOTION READY] ${p.claim} (hits: ${p.hitCount}, sources: ${p.sources.join(\", \")})`,\n );\n }\n if (result.decayedArchivedCount) {\n console.log(\n ` šŸ—‘ļø Pruned & archived ${result.decayedArchivedCount} expired entries to .lernstoff/archive/decayed.jsonl`,\n );\n }\n console.log(\"\");\n\n return result;\n}\n\nexport async function lintCmd(vaultPath: string, options: { json?: boolean } = {}): Promise<any> {\n const absVault = resolve(vaultPath);\n let daemonInfo = getRunningDaemonInfo(absVault);\n let result: any;\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/lint`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n checkOrphans: true,\n checkContradictions: true,\n checkSynthesisReady: true,\n }),\n });\n result = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const ops = new VaultOps(absVault);\n result = await ops.lintWiki();\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return result;\n }\n\n console.log(`\\nšŸ›ļø Socratic Health Audit:`);\n console.log(` Total Notes: ${result.summary.totalNotes}`);\n console.log(` Orphan Notes (in-degree 0): ${result.summary.orphanCount}`);\n for (const o of result.orphans) {\n console.log(` āš ļø Orphan: [[${o.title}]] (in: ${o.inDegree}, out: ${o.outDegree})`);\n }\n\n console.log(` Contradictions: ${result.summary.contradictionCount}`);\n for (const c of result.contradictions) {\n console.log(` ⚔ Latent Contradiction: [[${c.noteA}]] vs [[${c.noteB}]]`);\n }\n\n console.log(` Synthesis Ready Inquiries: ${result.summary.synthesisReadyCount}`);\n for (const s of result.synthesisReady) {\n console.log(\n ` 🌟 Ready: ${s.inquiryId} has ${s.supportingNoteCount} supporting notes -> ready for survey note!`,\n );\n }\n console.log(\"\");\n\n return result;\n}\n","#!/usr/bin/env node\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n copyFileSync,\n openSync,\n closeSync,\n} from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport {\n initVault,\n loadConfig,\n getConfigValue,\n setConfigValue,\n resetConfigToDefaults,\n getConfigPath,\n DaemonServer,\n LERNSTOFF_DIR,\n} from \"@lernstoff/core\";\nimport { getRunningDaemonInfo, killDaemonProcess } from \"./daemon-pid.js\";\nimport { runMcpStdio } from \"./stdio-proxy.js\";\nimport { ServiceManager } from \"./service-manager.js\";\nimport { AgentInstaller, DEFAULT_SKILL_MD } from \"./agent-installer.js\";\nimport { searchCmd, inquiryCmd, scratchpadCmd, lintCmd } from \"./cognitive-cmds.js\";\n\n// Minimal helper to parse flags and arguments\nfunction parseArgs(args: string[]) {\n const flags: Record<string, string | boolean> = {};\n const positional: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg.startsWith(\"--\")) {\n const key = arg.slice(2);\n if (i + 1 < args.length && !args[i + 1]!.startsWith(\"--\")) {\n flags[key] = args[i + 1]!;\n i++;\n } else {\n flags[key] = true;\n }\n } else if (arg.startsWith(\"-\")) {\n flags[arg.slice(1)] = true;\n } else {\n positional.push(arg);\n }\n }\n\n return { flags, positional };\n}\n\nasync function main() {\n const rawArgs = process.argv.slice(2);\n const { flags, positional } = parseArgs(rawArgs);\n\n const vaultPath = resolve(typeof flags.vault === \"string\" ? flags.vault : process.cwd());\n const command = positional[0] || \"help\";\n const subCommand = positional[1];\n\n switch (command) {\n case \"init\": {\n await initVault(vaultPath);\n console.log(`✨ Initialized lernstoff-wiki in: ${vaultPath}`);\n console.log(` Created .lernstoff/config.json and starter templates.`);\n break;\n }\n\n case \"config\": {\n const action = subCommand || \"list\";\n const key = positional[2];\n const val = positional[3];\n\n if (action === \"path\") {\n console.log(getConfigPath(vaultPath));\n } else if (action === \"get\" && key) {\n const value = getConfigValue(vaultPath, key);\n console.log(typeof value === \"object\" ? JSON.stringify(value, null, 2) : value);\n } else if (action === \"set\" && key && val !== undefined) {\n let parsedVal: any = val;\n if (val === \"true\") parsedVal = true;\n else if (val === \"false\") parsedVal = false;\n else if (!isNaN(Number(val))) parsedVal = Number(val);\n\n setConfigValue(vaultPath, key, parsedVal);\n console.log(`Updated ${key} = ${JSON.stringify(parsedVal)}`);\n\n // Notify daemon if running\n const daemonInfo = getRunningDaemonInfo(vaultPath);\n if (daemonInfo) {\n try {\n await fetch(`http://127.0.0.1:${daemonInfo.port}/api/reload-config`, {\n method: \"POST\",\n });\n } catch {}\n }\n } else if (action === \"reset\") {\n const conf = resetConfigToDefaults(vaultPath, key);\n console.log(`Reset configuration to defaults:`, conf);\n } else {\n const conf = loadConfig(vaultPath);\n console.log(JSON.stringify(conf, null, 2));\n }\n break;\n }\n\n case \"server\": {\n const action = subCommand || \"status\";\n\n if (action === \"start\") {\n const isDaemon = flags.daemon !== undefined || flags.d !== undefined;\n\n if (isDaemon) {\n const existing = getRunningDaemonInfo(vaultPath);\n if (existing) {\n console.log(\n `Daemon already running on http://127.0.0.1:${existing.port} (PID ${existing.pid})`,\n );\n return;\n }\n\n const logPath = join(vaultPath, LERNSTOFF_DIR, \"daemon.log\");\n const logFd = openSync(logPath, \"a\");\n\n const child = spawn(\n process.execPath,\n [process.argv[1] || \"\", \"server\", \"start\", \"--foreground\", \"--vault\", vaultPath],\n {\n stdio: [\"ignore\", logFd, logFd],\n detached: true,\n cwd: vaultPath,\n env: process.env,\n },\n );\n child.unref();\n closeSync(logFd);\n\n console.log(`šŸš€ Started lernstoff daemon in background (PID ${child.pid})`);\n console.log(` Logs: ${logPath}`);\n } else {\n // Foreground server mode\n const daemon = new DaemonServer({ vaultPath });\n if (flags.port) {\n daemon.config.server.port = Number(flags.port);\n }\n const port = await daemon.start();\n console.log(\n `🧠 Lernstoff daemon running on http://127.0.0.1:${port} (PID ${process.pid})`,\n );\n\n const shutdown = async () => {\n console.log(\"\\nShutting down lernstoff daemon...\");\n await daemon.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n }\n } else if (action === \"stop\") {\n const existing = getRunningDaemonInfo(vaultPath);\n if (!existing) {\n console.log(`No daemon running for vault: ${vaultPath}`);\n return;\n }\n killDaemonProcess(existing.pid);\n console.log(`šŸ›‘ Stopped daemon (PID ${existing.pid})`);\n } else if (action === \"restart\") {\n const existing = getRunningDaemonInfo(vaultPath);\n if (existing) {\n killDaemonProcess(existing.pid);\n }\n const daemon = new DaemonServer({ vaultPath });\n const port = await daemon.start();\n console.log(`šŸ”„ Restarted daemon on port ${port} (PID ${process.pid})`);\n } else if (action === \"status\") {\n const existing = getRunningDaemonInfo(vaultPath);\n if (existing) {\n console.log(`🟢 Daemon Running (PID ${existing.pid}, Port ${existing.port})`);\n } else {\n console.log(`⚪ Daemon Stopped`);\n }\n } else if (action === \"logs\") {\n const logPath = join(vaultPath, LERNSTOFF_DIR, \"daemon.log\");\n if (existsSync(logPath)) {\n const lines = readFileSync(logPath, \"utf-8\").split(\"\\n\").slice(-50).join(\"\\n\");\n console.log(lines);\n } else {\n console.log(`No logs found at ${logPath}`);\n }\n }\n break;\n }\n\n case \"service\": {\n const action = subCommand || \"status\";\n if (action === \"install\") {\n const res = await ServiceManager.installService(vaultPath, process.argv[1]);\n console.log(\n `āœ… Installed OS boot auto-start service (${res.platform}): ${res.servicePath}`,\n );\n } else if (action === \"uninstall\") {\n await ServiceManager.uninstallService(vaultPath);\n console.log(`šŸ—‘ļø Uninstalled OS boot auto-start service for: ${vaultPath}`);\n } else {\n const status = await ServiceManager.getServiceStatus(vaultPath);\n console.log(`Service Status:`, status);\n }\n break;\n }\n\n case \"mcp\": {\n await runMcpStdio(vaultPath);\n break;\n }\n\n case \"search\": {\n const query = positional.slice(1).join(\" \");\n if (!query) {\n console.error(\"Usage: lernstoff search <query>\");\n process.exit(1);\n }\n await searchCmd(vaultPath, query, {\n lex: !!flags.lex,\n vec: !!flags.vec,\n limit: flags.limit ? Number(flags.limit) : 5,\n json: !!flags.json,\n });\n break;\n }\n\n case \"inquiry\": {\n const action = (subCommand as any) || \"list\";\n const textOrId = positional[2];\n await inquiryCmd(vaultPath, action, textOrId, { json: !!flags.json });\n break;\n }\n\n case \"scratchpad\": {\n const action = (subCommand as any) || \"list\";\n const text = positional.slice(2).join(\" \");\n await scratchpadCmd(vaultPath, action, text, { json: !!flags.json });\n break;\n }\n\n case \"lint\": {\n await lintCmd(vaultPath, { json: !!flags.json });\n break;\n }\n\n case \"skill\": {\n const action = subCommand || \"show\";\n if (action === \"install\") {\n const target = (flags.target as any) || \"all\";\n const skills = AgentInstaller.installSkill(target, vaultPath);\n const mcps = AgentInstaller.installMcp(target, vaultPath);\n console.log(`āœ… Installed SKILL.md to:\\n ${skills.join(\"\\n \")}`);\n console.log(`āœ… Injected MCP configuration to:\\n ${mcps.join(\"\\n \")}`);\n } else {\n console.log(DEFAULT_SKILL_MD);\n }\n break;\n }\n\n case \"doctor\": {\n const report = await AgentInstaller.runDoctor({\n vaultPath,\n pullModels: !!flags[\"pull-models\"],\n cleanup: !!flags.cleanup,\n });\n console.log(`\\n🩺 Lernstoff Doctor Report:`);\n console.log(JSON.stringify(report, null, 2));\n break;\n }\n\n case \"plugin\": {\n const action = subCommand || \"install\";\n if (action === \"install\") {\n const obsidianDir = join(vaultPath, \".obsidian\");\n const targetPluginDir = join(obsidianDir, \"plugins\", \"lernstoff-wiki\");\n mkdirSync(targetPluginDir, { recursive: true });\n\n // Look for plugin assets in known locations\n const candidateDirs = [\n join(import.meta.dirname, \"../../obsidian-plugin/dist\"),\n join(import.meta.dirname, \"../node_modules/@lernstoff/obsidian-plugin/dist\"),\n join(process.cwd(), \"packages/obsidian-plugin/dist\"),\n ];\n let foundDir: string | null = null;\n for (const dir of candidateDirs) {\n if (existsSync(join(dir, \"main.js\")) && existsSync(join(dir, \"manifest.json\"))) {\n foundDir = dir;\n break;\n }\n }\n\n if (!foundDir) {\n console.error(\n \"Could not find compiled plugin assets (main.js, manifest.json). Please run 'pnpm build' first.\",\n );\n process.exit(1);\n }\n\n copyFileSync(join(foundDir, \"main.js\"), join(targetPluginDir, \"main.js\"));\n copyFileSync(join(foundDir, \"manifest.json\"), join(targetPluginDir, \"manifest.json\"));\n if (existsSync(join(foundDir, \"styles.css\"))) {\n copyFileSync(join(foundDir, \"styles.css\"), join(targetPluginDir, \"styles.css\"));\n }\n\n // Enable in community-plugins.json if it exists\n const communityPluginsPath = join(obsidianDir, \"community-plugins.json\");\n try {\n let plugins: string[] = [];\n if (existsSync(communityPluginsPath)) {\n plugins = JSON.parse(readFileSync(communityPluginsPath, \"utf-8\"));\n }\n if (!plugins.includes(\"lernstoff-wiki\")) {\n plugins.push(\"lernstoff-wiki\");\n writeFileSync(communityPluginsPath, JSON.stringify(plugins, null, 2), \"utf-8\");\n }\n } catch {}\n\n console.log(`āœ… Successfully installed Obsidian plugin into:\\n ${targetPluginDir}`);\n console.log(` Copied: main.js, manifest.json, styles.css`);\n console.log(` Enabled in community-plugins.json`);\n }\n break;\n }\n\n default: {\n console.log(`\n🧠 lernstoff-wiki (v0.1.0-beta.1) - Headless Cognitive Selective Note-Taking Engine\n\nUsage:\n lernstoff init [--vault <path>]\n lernstoff config <get|set|list|reset|path> [key] [value] [--vault <path>]\n lernstoff server <start|stop|restart|status|logs> [--daemon|--foreground] [--port <n>]\n lernstoff service <install|uninstall|status> [--vault <path>]\n lernstoff mcp [--vault <path>]\n lernstoff search <query> [--lex|--vec] [--limit <n>] [--json]\n lernstoff inquiry <list|add|close|reopen> [textOrId] [--json]\n lernstoff scratchpad <list|add|consolidate|gc> [text] [--json]\n lernstoff lint [--vault <path>] [--json]\n lernstoff skill <install|show> [--target <all|claude|cursor|antigravity>]\n lernstoff plugin install [--vault <path>]\n lernstoff doctor [--pull-models|--cleanup]\n`);\n break;\n }\n }\n}\n\nmain().catch((err) => {\n console.error(\"CLI Error:\", err);\n process.exit(1);\n});\n"],"mappings":"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"}
1
+ {"version":3,"file":"bin.mjs","names":[],"sources":["../src/daemon-pid.ts","../src/stdio-proxy.ts","../src/service-manager.ts","../src/agent-installer.ts","../src/cognitive-cmds.ts","../src/bin.ts"],"sourcesContent":["import { existsSync, readFileSync, unlinkSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\nimport { execSync } from \"node:child_process\";\nimport { LERNSTOFF_DIR } from \"@lernstoff/core\";\n\n/**\n * Check if a process ID is currently running in the OS.\n */\nexport function isPidAlive(pid: number): boolean {\n if (!Number.isInteger(pid) || pid <= 0) return false;\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Read the full command line of a process by PID across macOS, Linux, and Windows.\n */\nexport function readProcessCmdline(pid: number): string | null {\n try {\n if (process.platform === \"win32\") {\n const output = execSync(`wmic process where ProcessId=${pid} get CommandLine /value`, {\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 1000,\n }).toString(\"utf-8\");\n const match = output.match(/CommandLine=(.*)/i);\n return match ? match[1]!.trim() : null;\n } else {\n const output = execSync(`ps -p ${pid} -o command=`, {\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n timeout: 1000,\n }).toString(\"utf-8\");\n return output.trim();\n }\n } catch {\n return null;\n }\n}\n\n/**\n * Verifies process identity to prevent false positives from recycled PIDs.\n * Modeled on qmd/src/cli/mcp-pid.ts#L74-L86.\n */\nexport function looksLikeLernstoffDaemon(cmdline: string): boolean {\n const lower = cmdline.toLowerCase();\n return (\n lower.includes(\"lernstoff\") ||\n lower.includes(\"daemon-server\") ||\n lower.includes(\"@lernstoff/cli\") ||\n lower.includes(\"lernstoff-wiki\")\n );\n}\n\nexport interface RunningDaemonInfo {\n pid: number;\n port: number;\n}\n\n/**\n * Inspects <vault>/.lernstoff/daemon.pid and daemon.port to check if the daemon is alive.\n * If the process is dead or stale, cleans up the files and returns null.\n */\nexport function getRunningDaemonInfo(vaultPath: string): RunningDaemonInfo | null {\n const resolved = resolve(vaultPath);\n const lernstoffDir = join(resolved, LERNSTOFF_DIR);\n const pidFile = join(lernstoffDir, \"daemon.pid\");\n const portFile = join(lernstoffDir, \"daemon.port\");\n\n if (!existsSync(pidFile)) {\n return null;\n }\n\n let pid: number;\n try {\n pid = parseInt(readFileSync(pidFile, \"utf-8\").trim(), 10);\n } catch {\n return null;\n }\n\n if (!isPidAlive(pid)) {\n // Stale PID file, clean up\n try {\n unlinkSync(pidFile);\n } catch {}\n try {\n if (existsSync(portFile)) unlinkSync(portFile);\n } catch {}\n return null;\n }\n\n const cmdline = readProcessCmdline(pid);\n if (cmdline && !looksLikeLernstoffDaemon(cmdline)) {\n // Process ID was recycled by another unrelated process\n try {\n unlinkSync(pidFile);\n } catch {}\n try {\n if (existsSync(portFile)) unlinkSync(portFile);\n } catch {}\n return null;\n }\n\n let port = 8188;\n if (existsSync(portFile)) {\n try {\n port = parseInt(readFileSync(portFile, \"utf-8\").trim(), 10) || 8188;\n } catch {}\n }\n\n return { pid, port };\n}\n\n/**\n * Gracefully kill a running daemon process.\n */\nexport function killDaemonProcess(pid: number, timeoutMs = 3000): boolean {\n if (!isPidAlive(pid)) return true;\n\n try {\n process.kill(pid, \"SIGTERM\");\n } catch {\n return !isPidAlive(pid);\n }\n\n const start = Date.now();\n while (Date.now() - start < timeoutMs) {\n if (!isPidAlive(pid)) return true;\n try {\n execSync(\"sleep 0.05\");\n } catch {}\n }\n\n // Force kill if SIGTERM didn't succeed\n try {\n process.kill(pid, \"SIGKILL\");\n } catch {}\n\n return !isPidAlive(pid);\n}\n","import { createInterface } from \"node:readline\";\nimport { StdioServerTransport } from \"@modelcontextprotocol/server/stdio\";\nimport { createLernstoffMcpServer } from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\n/**\n * Runs MCP over stdio.\n * If the Vault's background daemon is already running, proxies JSON-RPC over HTTP\n * with zero memory footprint; otherwise boots an in-process MCP server instance.\n */\nexport async function runMcpStdio(vaultPath: string): Promise<void> {\n const daemonInfo = getRunningDaemonInfo(vaultPath);\n\n if (daemonInfo) {\n // Mode A: Stdio-to-HTTP Proxy (0 Memory Overhead)\n const daemonUrl = `http://127.0.0.1:${daemonInfo.port}/mcp`;\n\n const rl = createInterface({\n input: process.stdin,\n terminal: false,\n });\n\n rl.on(\"line\", async (line) => {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n try {\n const res = await fetch(daemonUrl, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json, text/event-stream\",\n },\n body: trimmed,\n });\n\n const contentType = res.headers.get(\"content-type\") || \"\";\n if (contentType.includes(\"json\")) {\n const bodyText = await res.text();\n if (bodyText) {\n process.stdout.write(`${bodyText}\\n`);\n }\n } else {\n // Streamable response\n const reader = res.body?.getReader();\n if (reader) {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n process.stdout.write(value);\n }\n }\n }\n } catch (err: any) {\n const errorRpc = {\n jsonrpc: \"2.0\",\n id: null,\n error: {\n code: -32603,\n message: `Daemon proxy error: ${err.message}`,\n },\n };\n process.stdout.write(`${JSON.stringify(errorRpc)}\\n`);\n }\n });\n\n return;\n }\n\n // Mode B: Direct in-process Stdio MCP Server\n const server = createLernstoffMcpServer({ vaultPath });\n const transport = new StdioServerTransport();\n await server.connect(transport);\n}\n","import { existsSync, writeFileSync, unlinkSync, mkdirSync } from \"node:fs\";\nimport { join, resolve, basename } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { execSync } from \"node:child_process\";\nimport { VaultOps } from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\nexport interface ServiceStatus {\n installed: boolean;\n running: boolean;\n servicePath?: string;\n platform: string;\n pid?: number;\n port?: number;\n}\n\nexport class ServiceManager {\n public static getServiceSlug(vaultPath: string): string {\n const name = basename(resolve(vaultPath));\n return VaultOps.slugify(name || \"default\");\n }\n\n public static getLaunchdPlistPath(vaultPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n return join(homedir(), \"Library/LaunchAgents\", `ai.lernstoff.wiki.${slug}.plist`);\n }\n\n public static getSystemdServicePath(vaultPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n return join(homedir(), \".config/systemd/user\", `lernstoff-wiki@${slug}.service`);\n }\n\n public static generateLaunchdPlist(vaultPath: string, cliPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n const absVault = resolve(vaultPath);\n const logPath = join(absVault, \".lernstoff\", \"daemon.log\");\n\n return `<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>Label</key>\n <string>ai.lernstoff.wiki.${slug}</string>\n <key>ProgramArguments</key>\n <array>\n <string>${process.execPath}</string>\n <string>${cliPath}</string>\n <string>server</string>\n <string>start</string>\n <string>--foreground</string>\n <string>--vault</string>\n <string>${absVault}</string>\n </array>\n <key>RunAtLoad</key>\n <true/>\n <key>KeepAlive</key>\n <true/>\n <key>StandardOutPath</key>\n <string>${logPath}</string>\n <key>StandardErrorPath</key>\n <string>${logPath}</string>\n <key>WorkingDirectory</key>\n <string>${absVault}</string>\n</dict>\n</plist>\n`;\n }\n\n public static generateSystemdService(vaultPath: string, cliPath: string): string {\n const slug = ServiceManager.getServiceSlug(vaultPath);\n const absVault = resolve(vaultPath);\n const logPath = join(absVault, \".lernstoff\", \"daemon.log\");\n\n return `[Unit]\nDescription=Lernstoff Wiki Headless Cognitive Engine (${slug})\nAfter=network.target\n\n[Service]\nType=simple\nWorkingDirectory=${absVault}\nExecStart=${process.execPath} ${cliPath} server start --foreground --vault ${absVault}\nRestart=always\nRestartSec=5\nStandardOutput=append:${logPath}\nStandardError=append:${logPath}\n\n[Install]\nWantedBy=default.target\n`;\n }\n\n /**\n * Install OS boot auto-start service for the target Vault.\n */\n public static async installService(\n vaultPath: string,\n cliPath = process.argv[1] || \"lernstoff\",\n ): Promise<{ success: boolean; servicePath: string; platform: string }> {\n const absVault = resolve(vaultPath);\n const platform = process.platform;\n\n if (platform === \"darwin\") {\n const plistPath = ServiceManager.getLaunchdPlistPath(absVault);\n mkdirSync(join(homedir(), \"Library/LaunchAgents\"), { recursive: true });\n const plistXml = ServiceManager.generateLaunchdPlist(absVault, cliPath);\n writeFileSync(plistPath, plistXml, \"utf-8\");\n\n try {\n execSync(`launchctl load \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch {\n // May already be loaded or in dry-run\n }\n\n return { success: true, servicePath: plistPath, platform: \"darwin\" };\n }\n\n if (platform === \"linux\") {\n const servicePath = ServiceManager.getSystemdServicePath(absVault);\n mkdirSync(join(homedir(), \".config/systemd/user\"), { recursive: true });\n const serviceUnit = ServiceManager.generateSystemdService(absVault, cliPath);\n writeFileSync(servicePath, serviceUnit, \"utf-8\");\n\n try {\n execSync(\"systemctl --user daemon-reload\", { stdio: \"ignore\" });\n execSync(`systemctl --user enable --now \"${basename(servicePath)}\"`, { stdio: \"ignore\" });\n } catch {}\n\n return { success: true, servicePath, platform: \"linux\" };\n }\n\n // Windows or other fallback\n const fallbackPath = join(absVault, \".lernstoff\", \"autostart.cmd\");\n writeFileSync(\n fallbackPath,\n `@echo off\\n\"${process.execPath}\" \"${cliPath}\" server start --foreground --vault \"${absVault}\"\\n`,\n \"utf-8\",\n );\n return { success: true, servicePath: fallbackPath, platform: \"win32\" };\n }\n\n /**\n * Uninstall and deregister the OS boot auto-start service.\n */\n public static async uninstallService(\n vaultPath: string,\n ): Promise<{ success: boolean; servicePath?: string }> {\n const absVault = resolve(vaultPath);\n const platform = process.platform;\n\n if (platform === \"darwin\") {\n const plistPath = ServiceManager.getLaunchdPlistPath(absVault);\n if (existsSync(plistPath)) {\n try {\n execSync(`launchctl unload \"${plistPath}\"`, { stdio: \"ignore\" });\n } catch {}\n try {\n unlinkSync(plistPath);\n } catch {}\n return { success: true, servicePath: plistPath };\n }\n } else if (platform === \"linux\") {\n const servicePath = ServiceManager.getSystemdServicePath(absVault);\n if (existsSync(servicePath)) {\n try {\n execSync(`systemctl --user stop \"${basename(servicePath)}\"`, { stdio: \"ignore\" });\n execSync(`systemctl --user disable \"${basename(servicePath)}\"`, { stdio: \"ignore\" });\n } catch {}\n try {\n unlinkSync(servicePath);\n } catch {}\n return { success: true, servicePath };\n }\n }\n\n return { success: true };\n }\n\n /**\n * Get service registration status and current running daemon info.\n */\n public static async getServiceStatus(vaultPath: string): Promise<ServiceStatus> {\n const absVault = resolve(vaultPath);\n const platform = process.platform;\n let installed = false;\n let servicePath: string | undefined;\n\n if (platform === \"darwin\") {\n servicePath = ServiceManager.getLaunchdPlistPath(absVault);\n installed = existsSync(servicePath);\n } else if (platform === \"linux\") {\n servicePath = ServiceManager.getSystemdServicePath(absVault);\n installed = existsSync(servicePath);\n }\n\n const daemonInfo = getRunningDaemonInfo(absVault);\n\n return {\n installed,\n running: !!daemonInfo,\n servicePath: installed ? servicePath : undefined,\n platform,\n pid: daemonInfo?.pid,\n port: daemonInfo?.port,\n };\n }\n}\n","import { existsSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { join, resolve, dirname } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { QmdBridge, LERNSTOFF_DIR } from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\nexport const DEFAULT_SKILL_MD = `---\nname: lernstoff-wiki\ndescription: Headless Cognitive Selective Note-Taking Protocol for AI Agents and Obsidian. Use when reading documentation, analyzing papers, researching concepts, managing curiosity inquiry trees, verifying cognitive deltas, and creating evergreen proposition notes.\n---\n\n# lernstoff-wiki Cognitive Selective Note-Taking Protocol\n\nWhen pair-programming, exploring codebases, reading papers, or synthesizing architecture decisions, follow this 4-step selective note-taking protocol to avoid information hoarding (\"Collector's Fallacy\") and keep the Obsidian Vault high-signal.\n\n## Protocol Workflow\n1. Step 1: Probe Cognitive Delta (lernstoff_probe_delta) - NEVER write notes directly to disk.\n2. Step 2: Socratic 4-Question Defense (Q1: Delta, Q2: Belief update, Q3: >= 2 outbound links, Q4: Proposition-as-Title).\n3. Step 3: Crystallize Proposition Note (lernstoff_crystallize_note).\n4. Step 4: Fast Scratchpad Consolidation (lernstoff_consolidate_scratchpad).\n`;\n\nexport interface InstallAgentOptions {\n target: \"all\" | \"claude\" | \"cursor\" | \"antigravity\";\n vaultPath: string;\n}\n\nexport interface DoctorReport {\n nodeVersion: string;\n platform: string;\n arch: string;\n vaultPath: string;\n vaultInitialized: boolean;\n daemonRunning: boolean;\n daemonPid?: number;\n daemonPort?: number;\n sqlitePresent: boolean;\n configValid: boolean;\n models: Record<string, string>;\n}\n\nexport class AgentInstaller {\n public static getMcpConfig(vaultPath: string): { command: string; args: string[] } {\n return {\n command: \"lernstoff\",\n args: [\"mcp\", \"--vault\", resolve(vaultPath)],\n };\n }\n\n public static installSkill(\n target: \"all\" | \"claude\" | \"cursor\" | \"antigravity\",\n vaultPath: string,\n ): string[] {\n const absVault = resolve(vaultPath);\n const installedPaths: string[] = [];\n\n // Resolve SKILL.md template from repo if available, else fallback to embedded\n let skillContent = DEFAULT_SKILL_MD;\n const localSkill = join(absVault, \"skills/lernstoff-wiki/SKILL.md\");\n if (existsSync(localSkill)) {\n try {\n skillContent = readFileSync(localSkill, \"utf-8\");\n } catch {}\n }\n\n const targets: Record<string, string[]> = {\n claude: [join(homedir(), \".claude/skills/lernstoff-wiki/SKILL.md\")],\n antigravity: [join(homedir(), \".gemini/config/skills/lernstoff-wiki/SKILL.md\")],\n cursor: [\n join(absVault, \".cursor/skills/lernstoff-wiki/SKILL.md\"),\n join(homedir(), \".cursor/skills/lernstoff-wiki/SKILL.md\"),\n ],\n };\n\n const keys = target === \"all\" ? Object.keys(targets) : [target];\n for (const key of keys) {\n const paths = targets[key] || [];\n for (const p of paths) {\n try {\n mkdirSync(dirname(p), { recursive: true });\n writeFileSync(p, skillContent, \"utf-8\");\n installedPaths.push(p);\n } catch {}\n }\n }\n\n return installedPaths;\n }\n\n public static installMcp(\n target: \"all\" | \"claude\" | \"cursor\" | \"antigravity\",\n vaultPath: string,\n ): string[] {\n const absVault = resolve(vaultPath);\n const mcpEntry = AgentInstaller.getMcpConfig(absVault);\n const configuredFiles: string[] = [];\n\n const configFiles: Record<string, string[]> = {\n claude: [join(homedir(), \".claude.json\"), join(absVault, \".mcp.json\")],\n cursor: [join(absVault, \".cursor/mcp.json\"), join(homedir(), \".cursor/mcp.json\")],\n antigravity: [join(homedir(), \".gemini/antigravity/mcp_config.json\")],\n };\n\n const keys = target === \"all\" ? Object.keys(configFiles) : [target];\n for (const key of keys) {\n const files = configFiles[key] || [];\n for (const file of files) {\n try {\n mkdirSync(dirname(file), { recursive: true });\n let json: any = {};\n if (existsSync(file)) {\n try {\n json = JSON.parse(readFileSync(file, \"utf-8\"));\n } catch {\n json = {};\n }\n }\n\n if (!json.mcpServers) json.mcpServers = {};\n json.mcpServers[\"lernstoff\"] = mcpEntry;\n\n writeFileSync(file, JSON.stringify(json, null, 2), \"utf-8\");\n configuredFiles.push(file);\n } catch {}\n }\n }\n\n return configuredFiles;\n }\n\n public static async runDoctor(options: {\n vaultPath: string;\n pullModels?: boolean;\n cleanup?: boolean;\n }): Promise<DoctorReport> {\n const absVault = resolve(options.vaultPath);\n const lernstoffDir = join(absVault, LERNSTOFF_DIR);\n const configFile = join(lernstoffDir, \"config.json\");\n const sqliteFile = join(lernstoffDir, \"index.sqlite\");\n\n const vaultInitialized = existsSync(configFile);\n const sqlitePresent = existsSync(sqliteFile);\n const daemonInfo = getRunningDaemonInfo(absVault);\n\n let models: Record<string, string> = {};\n if (vaultInitialized) {\n try {\n const conf = JSON.parse(readFileSync(configFile, \"utf-8\"));\n models = conf.models || {};\n } catch {}\n }\n\n if (options.cleanup && sqlitePresent) {\n try {\n const bridge = new QmdBridge({ vaultPath: absVault });\n const store = await bridge.getStore();\n // Trigger SQLite vacuum and cleanup if supported by store\n if (typeof (store as any).cleanup === \"function\") {\n await (store as any).cleanup();\n }\n await bridge.close();\n } catch {}\n }\n\n if (options.pullModels) {\n // In offline/test environments, verify model paths exist or trigger download\n }\n\n return {\n nodeVersion: process.version,\n platform: process.platform,\n arch: process.arch,\n vaultPath: absVault,\n vaultInitialized,\n daemonRunning: !!daemonInfo,\n daemonPid: daemonInfo?.pid,\n daemonPort: daemonInfo?.port,\n sqlitePresent,\n configValid: vaultInitialized,\n models,\n };\n }\n}\n","import { resolve, join } from \"node:path\";\nimport { readFileSync, writeFileSync, existsSync } from \"node:fs\";\nimport {\n VaultOps,\n QmdBridge,\n loadConfig,\n parseScratchpad,\n formatScratchpad,\n type ScratchpadEntry,\n} from \"@lernstoff/core\";\nimport { getRunningDaemonInfo } from \"./daemon-pid.js\";\n\n/**\n * Builds editor URI (e.g. obsidian://open?path={path}) for terminal hyperlinks.\n * Modeled on qmd/src/cli/qmd.ts#L2660-L2675.\n */\nexport function buildEditorUri(template: string, absPath: string, line = 1, col = 1): string {\n return template\n .replace(\"{path}\", encodeURIComponent(absPath))\n .replace(\"{line}\", String(line))\n .replace(\"{col}\", String(col));\n}\n\n/**\n * OSC-8 terminal hyperlink format.\n */\nexport function termLink(\n text: string,\n url: string,\n isTTY: boolean = !!process.stdout.isTTY,\n): string {\n if (!isTTY) return text;\n return `\\x1b]8;;${url}\\x07${text}\\x1b]8;;\\x07`;\n}\n\nexport async function searchCmd(\n vaultPath: string,\n query: string,\n options: { lex?: boolean; vec?: boolean; ppr?: boolean; limit?: number; json?: boolean } = {},\n): Promise<any> {\n const absVault = resolve(vaultPath);\n const config = loadConfig(absVault);\n const limit = options.limit || 5;\n\n let daemonInfo = getRunningDaemonInfo(absVault);\n let searchResult: any;\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/search`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n queries: [{ type: options.lex ? \"lex\" : \"vec\", query }],\n limit,\n }),\n });\n searchResult = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const bridge = new QmdBridge({ vaultPath: absVault, config });\n try {\n searchResult = await bridge.search({\n queries: [{ type: options.lex ? \"lex\" : \"vec\", query }],\n limit,\n });\n } finally {\n await bridge.close();\n }\n }\n\n if (options.json) {\n console.log(JSON.stringify(searchResult, null, 2));\n return searchResult;\n }\n\n const hits = Array.isArray(searchResult) ? searchResult : searchResult.directHits || [];\n if (hits.length === 0) {\n console.log(`No results found for \"${query}\".`);\n return hits;\n }\n\n console.log(`\\nšŸ” Found ${hits.length} note(s) for \"${query}\":\\n`);\n for (const hit of hits) {\n const filePath = hit.displayPath || hit.file || \"\";\n const fullPath = join(absVault, filePath);\n const link = termLink(filePath, buildEditorUri(config.paths.editorUriTemplate, fullPath));\n const title = hit.title || filePath;\n const score = hit.score !== undefined ? ` (score: ${(hit.score * 100).toFixed(1)}%)` : \"\";\n console.log(` • ${title}${score}`);\n console.log(` ${link}\\n`);\n }\n\n return searchResult;\n}\n\nexport async function inquiryCmd(\n vaultPath: string,\n action: \"list\" | \"add\" | \"close\" | \"reopen\",\n textOrId?: string,\n options: { json?: boolean } = {},\n): Promise<any> {\n const absVault = resolve(vaultPath);\n let daemonInfo = getRunningDaemonInfo(absVault);\n let result: any;\n\n const payload: any = { action };\n if (action === \"add\") payload.question = textOrId;\n if (action === \"close\" || action === \"reopen\") payload.id = textOrId;\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/inquiries`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(payload),\n });\n result = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const ops = new VaultOps(absVault);\n result = await ops.manageInquiries(payload);\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return result;\n }\n\n if (action === \"list\" && Array.isArray(result)) {\n console.log(`\\n🧠 Active Inquiry Tree (${result.length} questions):\\n`);\n for (const inq of result) {\n const statusIcon = inq.status === \"OPEN\" ? \"🟢\" : \"⚪\";\n console.log(` ${statusIcon} [${inq.id || \"#\"}] ${inq.question}`);\n if (inq.supportingNoteCount > 0) {\n console.log(` ↳ ${inq.supportingNoteCount} supporting proposition note(s)`);\n }\n }\n console.log(\"\");\n } else {\n console.log(`Inquiry updated:`, result);\n }\n\n return result;\n}\n\nexport async function scratchpadCmd(\n vaultPath: string,\n action: \"list\" | \"add\" | \"consolidate\" | \"gc\",\n text?: string,\n options: { json?: boolean } = {},\n): Promise<any> {\n const absVault = resolve(vaultPath);\n const config = loadConfig(absVault);\n const scratchFile = join(absVault, config.paths.scratchpadFile);\n\n if (action === \"add\") {\n if (!text) throw new Error(\"Text is required for scratchpad add.\");\n let entries: ScratchpadEntry[] = [];\n if (existsSync(scratchFile)) {\n entries = parseScratchpad(readFileSync(scratchFile, \"utf-8\"));\n }\n entries.push({\n firstSeen: new Date().toISOString().slice(0, 10),\n claim: text.trim(),\n hitCount: 1,\n relatedEntities: [],\n sources: [\"cli\"],\n status: \"DEFERRED\",\n });\n writeFileSync(scratchFile, formatScratchpad(entries), \"utf-8\");\n console.log(`Recorded note to ${config.paths.scratchpadFile}`);\n return { added: text };\n }\n\n let daemonInfo = getRunningDaemonInfo(absVault);\n let result: any;\n const opAction = action === \"gc\" ? \"gc\" : \"inspect\";\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/scratchpad`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ action: opAction }),\n });\n result = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const ops = new VaultOps(absVault);\n result = await ops.consolidateScratchpad({ action: opAction });\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return result;\n }\n\n console.log(\n `\\n⚔ Scratchpad Buffer (Total: ${result.activeCount}, Ready for Promotion: ${result.promotions.length}):`,\n );\n for (const p of result.promotions) {\n console.log(\n ` ⭐ [PROMOTION READY] ${p.claim} (hits: ${p.hitCount}, sources: ${p.sources.join(\", \")})`,\n );\n }\n if (result.decayedArchivedCount) {\n console.log(\n ` šŸ—‘ļø Pruned & archived ${result.decayedArchivedCount} expired entries to .lernstoff/archive/decayed.jsonl`,\n );\n }\n console.log(\"\");\n\n return result;\n}\n\nexport async function lintCmd(vaultPath: string, options: { json?: boolean } = {}): Promise<any> {\n const absVault = resolve(vaultPath);\n let daemonInfo = getRunningDaemonInfo(absVault);\n let result: any;\n\n if (daemonInfo) {\n try {\n const res = await fetch(`http://127.0.0.1:${daemonInfo.port}/api/lint`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n checkOrphans: true,\n checkContradictions: true,\n checkSynthesisReady: true,\n }),\n });\n result = await res.json();\n } catch {\n daemonInfo = null;\n }\n }\n\n if (!daemonInfo) {\n const ops = new VaultOps(absVault);\n result = await ops.lintWiki();\n }\n\n if (options.json) {\n console.log(JSON.stringify(result, null, 2));\n return result;\n }\n\n console.log(`\\nšŸ›ļø Socratic Health Audit:`);\n console.log(` Total Notes: ${result.summary.totalNotes}`);\n console.log(` Orphan Notes (in-degree 0): ${result.summary.orphanCount}`);\n for (const o of result.orphans) {\n console.log(` āš ļø Orphan: [[${o.title}]] (in: ${o.inDegree}, out: ${o.outDegree})`);\n }\n\n console.log(` Contradictions: ${result.summary.contradictionCount}`);\n for (const c of result.contradictions) {\n console.log(` ⚔ Latent Contradiction: [[${c.noteA}]] vs [[${c.noteB}]]`);\n }\n\n console.log(` Synthesis Ready Inquiries: ${result.summary.synthesisReadyCount}`);\n for (const s of result.synthesisReady) {\n console.log(\n ` 🌟 Ready: ${s.inquiryId} has ${s.supportingNoteCount} supporting notes -> ready for survey note!`,\n );\n }\n console.log(\"\");\n\n return result;\n}\n","#!/usr/bin/env node\nimport {\n existsSync,\n readFileSync,\n writeFileSync,\n mkdirSync,\n copyFileSync,\n openSync,\n closeSync,\n} from \"node:fs\";\nimport { resolve, join } from \"node:path\";\nimport { spawn } from \"node:child_process\";\nimport { createRequire } from \"node:module\";\nimport {\n initVault,\n loadConfig,\n getConfigValue,\n setConfigValue,\n resetConfigToDefaults,\n getConfigPath,\n DaemonServer,\n LERNSTOFF_DIR,\n} from \"@lernstoff/core\";\nimport { getRunningDaemonInfo, killDaemonProcess } from \"./daemon-pid.js\";\nimport { runMcpStdio } from \"./stdio-proxy.js\";\nimport { ServiceManager } from \"./service-manager.js\";\nimport { AgentInstaller, DEFAULT_SKILL_MD } from \"./agent-installer.js\";\nimport { searchCmd, inquiryCmd, scratchpadCmd, lintCmd } from \"./cognitive-cmds.js\";\n\nconst require = createRequire(import.meta.url);\nconst CLI_VERSION: string = (() => {\n try {\n return require(\"../package.json\").version || \"0.0.0\";\n } catch {\n return \"0.0.0\";\n }\n})();\n\n// Minimal helper to parse flags and arguments\nfunction parseArgs(args: string[]) {\n const flags: Record<string, string | boolean> = {};\n const positional: string[] = [];\n\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!;\n if (arg.startsWith(\"--\")) {\n const key = arg.slice(2);\n if (i + 1 < args.length && !args[i + 1]!.startsWith(\"--\")) {\n flags[key] = args[i + 1]!;\n i++;\n } else {\n flags[key] = true;\n }\n } else if (arg.startsWith(\"-\")) {\n flags[arg.slice(1)] = true;\n } else {\n positional.push(arg);\n }\n }\n\n return { flags, positional };\n}\n\nasync function main() {\n const rawArgs = process.argv.slice(2);\n const { flags, positional } = parseArgs(rawArgs);\n\n if (flags.version || flags.v || positional[0] === \"--version\" || positional[0] === \"-v\") {\n console.log(CLI_VERSION);\n return;\n }\n\n const vaultPath = resolve(typeof flags.vault === \"string\" ? flags.vault : process.cwd());\n const command = positional[0] || \"help\";\n const subCommand = positional[1];\n\n switch (command) {\n case \"init\": {\n await initVault(vaultPath);\n console.log(`✨ Initialized lernstoff-wiki in: ${vaultPath}`);\n console.log(` Created .lernstoff/config.json and starter templates.`);\n break;\n }\n\n case \"config\": {\n const action = subCommand || \"list\";\n const key = positional[2];\n const val = positional[3];\n\n if (action === \"path\") {\n console.log(getConfigPath(vaultPath));\n } else if (action === \"get\" && key) {\n const value = getConfigValue(vaultPath, key);\n console.log(typeof value === \"object\" ? JSON.stringify(value, null, 2) : value);\n } else if (action === \"set\" && key && val !== undefined) {\n let parsedVal: any = val;\n if (val === \"true\") parsedVal = true;\n else if (val === \"false\") parsedVal = false;\n else if (!isNaN(Number(val))) parsedVal = Number(val);\n\n setConfigValue(vaultPath, key, parsedVal);\n console.log(`Updated ${key} = ${JSON.stringify(parsedVal)}`);\n\n // Notify daemon if running\n const daemonInfo = getRunningDaemonInfo(vaultPath);\n if (daemonInfo) {\n try {\n await fetch(`http://127.0.0.1:${daemonInfo.port}/api/reload-config`, {\n method: \"POST\",\n });\n } catch {}\n }\n } else if (action === \"reset\") {\n const conf = resetConfigToDefaults(vaultPath, key);\n console.log(`Reset configuration to defaults:`, conf);\n } else {\n const conf = loadConfig(vaultPath);\n console.log(JSON.stringify(conf, null, 2));\n }\n break;\n }\n\n case \"server\": {\n const action = subCommand || \"status\";\n\n if (action === \"start\") {\n const isDaemon = flags.daemon !== undefined || flags.d !== undefined;\n\n if (isDaemon) {\n const existing = getRunningDaemonInfo(vaultPath);\n if (existing) {\n console.log(\n `Daemon already running on http://127.0.0.1:${existing.port} (PID ${existing.pid})`,\n );\n return;\n }\n\n const logPath = join(vaultPath, LERNSTOFF_DIR, \"daemon.log\");\n const logFd = openSync(logPath, \"a\");\n\n const child = spawn(\n process.execPath,\n [process.argv[1] || \"\", \"server\", \"start\", \"--foreground\", \"--vault\", vaultPath],\n {\n stdio: [\"ignore\", logFd, logFd],\n detached: true,\n cwd: vaultPath,\n env: process.env,\n },\n );\n child.unref();\n closeSync(logFd);\n\n console.log(`šŸš€ Started lernstoff daemon in background (PID ${child.pid})`);\n console.log(` Logs: ${logPath}`);\n } else {\n // Foreground server mode\n const daemon = new DaemonServer({ vaultPath });\n if (flags.port) {\n daemon.config.server.port = Number(flags.port);\n }\n const port = await daemon.start();\n console.log(\n `🧠 Lernstoff daemon running on http://127.0.0.1:${port} (PID ${process.pid})`,\n );\n\n const shutdown = async () => {\n console.log(\"\\nShutting down lernstoff daemon...\");\n await daemon.stop();\n process.exit(0);\n };\n\n process.on(\"SIGINT\", shutdown);\n process.on(\"SIGTERM\", shutdown);\n }\n } else if (action === \"stop\") {\n const existing = getRunningDaemonInfo(vaultPath);\n if (!existing) {\n console.log(`No daemon running for vault: ${vaultPath}`);\n return;\n }\n killDaemonProcess(existing.pid);\n console.log(`šŸ›‘ Stopped daemon (PID ${existing.pid})`);\n } else if (action === \"restart\") {\n const existing = getRunningDaemonInfo(vaultPath);\n if (existing) {\n killDaemonProcess(existing.pid);\n }\n const daemon = new DaemonServer({ vaultPath });\n const port = await daemon.start();\n console.log(`šŸ”„ Restarted daemon on port ${port} (PID ${process.pid})`);\n } else if (action === \"status\") {\n const existing = getRunningDaemonInfo(vaultPath);\n if (existing) {\n console.log(`🟢 Daemon Running (PID ${existing.pid}, Port ${existing.port})`);\n } else {\n console.log(`⚪ Daemon Stopped`);\n }\n } else if (action === \"logs\") {\n const logPath = join(vaultPath, LERNSTOFF_DIR, \"daemon.log\");\n if (existsSync(logPath)) {\n const lines = readFileSync(logPath, \"utf-8\").split(\"\\n\").slice(-50).join(\"\\n\");\n console.log(lines);\n } else {\n console.log(`No logs found at ${logPath}`);\n }\n }\n break;\n }\n\n case \"service\": {\n const action = subCommand || \"status\";\n if (action === \"install\") {\n const res = await ServiceManager.installService(vaultPath, process.argv[1]);\n console.log(\n `āœ… Installed OS boot auto-start service (${res.platform}): ${res.servicePath}`,\n );\n } else if (action === \"uninstall\") {\n await ServiceManager.uninstallService(vaultPath);\n console.log(`šŸ—‘ļø Uninstalled OS boot auto-start service for: ${vaultPath}`);\n } else {\n const status = await ServiceManager.getServiceStatus(vaultPath);\n console.log(`Service Status:`, status);\n }\n break;\n }\n\n case \"mcp\": {\n await runMcpStdio(vaultPath);\n break;\n }\n\n case \"search\": {\n const query = positional.slice(1).join(\" \");\n if (!query) {\n console.error(\"Usage: lernstoff search <query>\");\n process.exit(1);\n }\n await searchCmd(vaultPath, query, {\n lex: !!flags.lex,\n vec: !!flags.vec,\n limit: flags.limit ? Number(flags.limit) : 5,\n json: !!flags.json,\n });\n break;\n }\n\n case \"inquiry\": {\n const action = (subCommand as any) || \"list\";\n const textOrId = positional[2];\n await inquiryCmd(vaultPath, action, textOrId, { json: !!flags.json });\n break;\n }\n\n case \"scratchpad\": {\n const action = (subCommand as any) || \"list\";\n const text = positional.slice(2).join(\" \");\n await scratchpadCmd(vaultPath, action, text, { json: !!flags.json });\n break;\n }\n\n case \"lint\": {\n await lintCmd(vaultPath, { json: !!flags.json });\n break;\n }\n\n case \"skill\": {\n const action = subCommand || \"show\";\n if (action === \"install\") {\n const target = (flags.target as any) || \"all\";\n const skills = AgentInstaller.installSkill(target, vaultPath);\n const mcps = AgentInstaller.installMcp(target, vaultPath);\n console.log(`āœ… Installed SKILL.md to:\\n ${skills.join(\"\\n \")}`);\n console.log(`āœ… Injected MCP configuration to:\\n ${mcps.join(\"\\n \")}`);\n } else {\n console.log(DEFAULT_SKILL_MD);\n }\n break;\n }\n\n case \"doctor\": {\n const report = await AgentInstaller.runDoctor({\n vaultPath,\n pullModels: !!flags[\"pull-models\"],\n cleanup: !!flags.cleanup,\n });\n console.log(`\\n🩺 Lernstoff Doctor Report:`);\n console.log(JSON.stringify(report, null, 2));\n break;\n }\n\n case \"plugin\": {\n const action = subCommand || \"install\";\n if (action === \"install\") {\n const obsidianDir = join(vaultPath, \".obsidian\");\n const targetPluginDir = join(obsidianDir, \"plugins\", \"lernstoff-wiki\");\n mkdirSync(targetPluginDir, { recursive: true });\n\n // Look for plugin assets in known locations\n const candidateDirs = [\n join(import.meta.dirname, \"../../obsidian-plugin/dist\"),\n join(import.meta.dirname, \"../node_modules/@lernstoff/obsidian-plugin/dist\"),\n join(process.cwd(), \"packages/obsidian-plugin/dist\"),\n ];\n let foundDir: string | null = null;\n for (const dir of candidateDirs) {\n if (existsSync(join(dir, \"main.js\")) && existsSync(join(dir, \"manifest.json\"))) {\n foundDir = dir;\n break;\n }\n }\n\n if (!foundDir) {\n console.error(\n \"Could not find compiled plugin assets (main.js, manifest.json). Please run 'pnpm build' first.\",\n );\n process.exit(1);\n }\n\n copyFileSync(join(foundDir, \"main.js\"), join(targetPluginDir, \"main.js\"));\n copyFileSync(join(foundDir, \"manifest.json\"), join(targetPluginDir, \"manifest.json\"));\n if (existsSync(join(foundDir, \"styles.css\"))) {\n copyFileSync(join(foundDir, \"styles.css\"), join(targetPluginDir, \"styles.css\"));\n }\n\n // Enable in community-plugins.json if it exists\n const communityPluginsPath = join(obsidianDir, \"community-plugins.json\");\n try {\n let plugins: string[] = [];\n if (existsSync(communityPluginsPath)) {\n plugins = JSON.parse(readFileSync(communityPluginsPath, \"utf-8\"));\n }\n if (!plugins.includes(\"lernstoff-wiki\")) {\n plugins.push(\"lernstoff-wiki\");\n writeFileSync(communityPluginsPath, JSON.stringify(plugins, null, 2), \"utf-8\");\n }\n } catch {}\n\n console.log(`āœ… Successfully installed Obsidian plugin into:\\n ${targetPluginDir}`);\n console.log(` Copied: main.js, manifest.json, styles.css`);\n console.log(` Enabled in community-plugins.json`);\n }\n break;\n }\n\n default: {\n console.log(`\n🧠 lernstoff-wiki (v${CLI_VERSION}) - Headless Cognitive Selective Note-Taking Engine\n\nUsage:\n lernstoff init [--vault <path>]\n lernstoff config <get|set|list|reset|path> [key] [value] [--vault <path>]\n lernstoff server <start|stop|restart|status|logs> [--daemon|--foreground] [--port <n>]\n lernstoff service <install|uninstall|status> [--vault <path>]\n lernstoff mcp [--vault <path>]\n lernstoff search <query> [--lex|--vec] [--limit <n>] [--json]\n lernstoff inquiry <list|add|close|reopen> [textOrId] [--json]\n lernstoff scratchpad <list|add|consolidate|gc> [text] [--json]\n lernstoff lint [--vault <path>] [--json]\n lernstoff skill <install|show> [--target <all|claude|cursor|antigravity>]\n lernstoff plugin install [--vault <path>]\n lernstoff doctor [--pull-models|--cleanup]\n`);\n break;\n }\n }\n}\n\nmain().catch((err) => {\n console.error(\"CLI Error:\", err);\n process.exit(1);\n});\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lernstoff/cli",
3
- "version": "0.1.0-beta.1",
3
+ "version": "0.1.0-beta.3",
4
4
  "description": "Headless CLI and daemon manager for Lernstoff cognitive note-taking engine",
5
5
  "homepage": "https://github.com/JsonLee12138/lernstoff-wiki#readme",
6
6
  "license": "MIT",
@@ -25,7 +25,7 @@
25
25
  "dependencies": {
26
26
  "@modelcontextprotocol/server": "^2.4.0",
27
27
  "zod": "^4.6.7",
28
- "@lernstoff/core": "0.1.0-beta.1"
28
+ "@lernstoff/core": "0.1.0-beta.3"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^22.13.0"