@mattli/dotmd 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -0
- package/dist/cli/commands/init.d.ts +4 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +23 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/install-hook.d.ts +2 -0
- package/dist/cli/commands/install-hook.d.ts.map +1 -0
- package/dist/cli/commands/install-hook.js +31 -0
- package/dist/cli/commands/install-hook.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +5 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +75 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/serve.d.ts +4 -0
- package/dist/cli/commands/serve.d.ts.map +1 -0
- package/dist/cli/commands/serve.js +8 -0
- package/dist/cli/commands/serve.js.map +1 -0
- package/dist/cli/commands/status.d.ts +2 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +70 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +38 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/config/defaults.d.ts +13 -0
- package/dist/config/defaults.d.ts.map +1 -0
- package/dist/config/defaults.js +36 -0
- package/dist/config/defaults.js.map +1 -0
- package/dist/config/loader.d.ts +4 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +28 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/dashboard/layout.d.ts +6 -0
- package/dist/dashboard/layout.d.ts.map +1 -0
- package/dist/dashboard/layout.js +47 -0
- package/dist/dashboard/layout.js.map +1 -0
- package/dist/dashboard/server.d.ts +5 -0
- package/dist/dashboard/server.d.ts.map +1 -0
- package/dist/dashboard/server.js +305 -0
- package/dist/dashboard/server.js.map +1 -0
- package/dist/dashboard/settings-client.d.ts +2 -0
- package/dist/dashboard/settings-client.d.ts.map +1 -0
- package/dist/dashboard/settings-client.js +310 -0
- package/dist/dashboard/settings-client.js.map +1 -0
- package/dist/dashboard/settings.d.ts +3 -0
- package/dist/dashboard/settings.d.ts.map +1 -0
- package/dist/dashboard/settings.js +99 -0
- package/dist/dashboard/settings.js.map +1 -0
- package/dist/dashboard/views.d.ts +8 -0
- package/dist/dashboard/views.d.ts.map +1 -0
- package/dist/dashboard/views.js +694 -0
- package/dist/dashboard/views.js.map +1 -0
- package/dist/dashboard/wizard-client.d.ts +2 -0
- package/dist/dashboard/wizard-client.d.ts.map +1 -0
- package/dist/dashboard/wizard-client.js +266 -0
- package/dist/dashboard/wizard-client.js.map +1 -0
- package/dist/dashboard/wizard.d.ts +9 -0
- package/dist/dashboard/wizard.d.ts.map +1 -0
- package/dist/dashboard/wizard.js +236 -0
- package/dist/dashboard/wizard.js.map +1 -0
- package/dist/scanner/git.d.ts +8 -0
- package/dist/scanner/git.d.ts.map +1 -0
- package/dist/scanner/git.js +34 -0
- package/dist/scanner/git.js.map +1 -0
- package/dist/scanner/index.d.ts +10 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +60 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/storage/db.d.ts +3 -0
- package/dist/storage/db.d.ts.map +1 -0
- package/dist/storage/db.js +52 -0
- package/dist/storage/db.js.map +1 -0
- package/dist/storage/snapshots.d.ts +43 -0
- package/dist/storage/snapshots.d.ts.map +1 -0
- package/dist/storage/snapshots.js +102 -0
- package/dist/storage/snapshots.js.map +1 -0
- package/package.json +60 -0
package/README.md
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# dotmd
|
|
2
|
+
|
|
3
|
+
Track changes to your AI instruction files.
|
|
4
|
+
|
|
5
|
+
If you use Claude Code, Cursor, Codex, or similar tools, you've accumulated markdown files that control how AI behaves: `CLAUDE.md`, `AGENTS.md`, memory files, skill configs. These files live in scattered locations, get modified by both you and AI agents, and have no change history.
|
|
6
|
+
|
|
7
|
+
dotmd watches these files and keeps a local history of every change, with diffs. A web dashboard lets you see what changed, when, and across which projects.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install -g @mattli/dotmd
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Requires Node.js 18+.
|
|
16
|
+
|
|
17
|
+
## Quick Start
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
dotmd init
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
This opens a setup wizard in your browser where you pick which folders and file patterns to track. Once you confirm, dotmd takes an initial snapshot of all discovered files.
|
|
24
|
+
|
|
25
|
+
To view your files and change history:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
dotmd serve
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
This starts a local dashboard at `http://localhost:3333`.
|
|
32
|
+
|
|
33
|
+
## Commands
|
|
34
|
+
|
|
35
|
+
| Command | Description |
|
|
36
|
+
|---------|-------------|
|
|
37
|
+
| `dotmd init` | Launch the setup wizard |
|
|
38
|
+
| `dotmd status` | Scan for changes and show a summary in the terminal |
|
|
39
|
+
| `dotmd serve` | Start the web dashboard |
|
|
40
|
+
|
|
41
|
+
## What It Tracks
|
|
42
|
+
|
|
43
|
+
By default, dotmd looks for:
|
|
44
|
+
|
|
45
|
+
- `CLAUDE.md` (Claude Code)
|
|
46
|
+
- `AGENTS.md` (Codex)
|
|
47
|
+
- `MEMORY.md`
|
|
48
|
+
- `SKILL.md` (Codex skills)
|
|
49
|
+
- `.cursorrules` (Cursor)
|
|
50
|
+
- `.windsurfrules` (Windsurf)
|
|
51
|
+
|
|
52
|
+
You can add custom patterns and folders through the setup wizard or the settings page in the dashboard.
|
|
53
|
+
|
|
54
|
+
## How It Works
|
|
55
|
+
|
|
56
|
+
dotmd scans your configured folders for matching files and stores snapshots in a local SQLite database at `~/.dotmd/history.db`. When a file changes, it saves the new version and a diff. The dashboard rescans on every page load, so you always see current data.
|
|
57
|
+
|
|
58
|
+
All data stays on your machine. Nothing is sent anywhere.
|
|
59
|
+
|
|
60
|
+
## Configuration
|
|
61
|
+
|
|
62
|
+
Settings are managed through the dashboard's settings page. Config is stored at `~/.dotmd/config.yaml`.
|
|
63
|
+
|
|
64
|
+
## Uninstall
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm uninstall -g dotmd
|
|
68
|
+
rm -rf ~/.dotmd
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Feedback
|
|
72
|
+
|
|
73
|
+
Questions, suggestions, or bugs? [Open an issue](https://github.com/mattli/dotmd/issues).
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA0B3E"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { exec } from "child_process";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import { startServer } from "../../dashboard/server.js";
|
|
4
|
+
export async function initCommand(options) {
|
|
5
|
+
const port = options.port ? parseInt(options.port, 10) : 3333;
|
|
6
|
+
const url = `http://localhost:${port}/setup`;
|
|
7
|
+
console.log(chalk.bold("\nStarting setup wizard...\n"));
|
|
8
|
+
startServer(port);
|
|
9
|
+
// Open browser
|
|
10
|
+
const openCmd = process.platform === "darwin"
|
|
11
|
+
? "open"
|
|
12
|
+
: process.platform === "win32"
|
|
13
|
+
? "start"
|
|
14
|
+
: "xdg-open";
|
|
15
|
+
exec(`${openCmd} ${url}`, (err) => {
|
|
16
|
+
if (err) {
|
|
17
|
+
console.log(chalk.yellow(`Could not open browser automatically.`));
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
console.log(`Setup wizard running at ${chalk.blue(url)}`);
|
|
21
|
+
console.log(chalk.dim("Press Ctrl+C to stop the server.\n"));
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/cli/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAA0B;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,MAAM,GAAG,GAAG,oBAAoB,IAAI,QAAQ,CAAC;IAE7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,CAAC;IAExD,WAAW,CAAC,IAAI,CAAC,CAAC;IAElB,eAAe;IACf,MAAM,OAAO,GACX,OAAO,CAAC,QAAQ,KAAK,QAAQ;QAC3B,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO;YAC5B,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,UAAU,CAAC;IAEnB,IAAI,CAAC,GAAG,OAAO,IAAI,GAAG,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE;QAChC,IAAI,GAAG,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CAAC,uCAAuC,CAAC,CACtD,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CAAC,2BAA2B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC1D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAC,CAAC;AAC/D,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hook.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/install-hook.ts"],"names":[],"mappings":"AAgBA,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC,CAqBxD"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
const HOOK_MARKER = "# dotmd shell hook";
|
|
6
|
+
const HOOK_LINE = `\n${HOOK_MARKER}\nif command -v dotmd &> /dev/null; then dotmd scan --session --quiet 2>/dev/null; fi\n`;
|
|
7
|
+
function getShellRcPath() {
|
|
8
|
+
const shell = process.env.SHELL || "/bin/zsh";
|
|
9
|
+
if (shell.includes("bash")) {
|
|
10
|
+
return path.join(os.homedir(), ".bashrc");
|
|
11
|
+
}
|
|
12
|
+
return path.join(os.homedir(), ".zshrc");
|
|
13
|
+
}
|
|
14
|
+
export async function installHookCommand() {
|
|
15
|
+
const rcPath = getShellRcPath();
|
|
16
|
+
const shellName = rcPath.endsWith(".bashrc") ? "bash" : "zsh";
|
|
17
|
+
console.log(chalk.bold(`\nInstalling dotmd session hook for ${shellName}\n`));
|
|
18
|
+
// Check if already installed
|
|
19
|
+
if (fs.existsSync(rcPath)) {
|
|
20
|
+
const content = fs.readFileSync(rcPath, "utf-8");
|
|
21
|
+
if (content.includes(HOOK_MARKER)) {
|
|
22
|
+
console.log(chalk.yellow("Hook already installed. Skipping."));
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Append hook
|
|
27
|
+
fs.appendFileSync(rcPath, HOOK_LINE);
|
|
28
|
+
console.log(chalk.green(`Hook added to ${rcPath.replace(os.homedir(), "~")}`));
|
|
29
|
+
console.log(chalk.dim("Open a new terminal to activate, or run: source " + rcPath.replace(os.homedir(), "~")));
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=install-hook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-hook.js","sourceRoot":"","sources":["../../../src/cli/commands/install-hook.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,WAAW,GAAG,oBAAoB,CAAC;AACzC,MAAM,SAAS,GAAG,KAAK,WAAW,yFAAyF,CAAC;AAE5H,SAAS,cAAc;IACrB,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,IAAI,UAAU,CAAC;IAC9C,IAAI,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IAC5C,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB;IACtC,MAAM,MAAM,GAAG,cAAc,EAAE,CAAC;IAChC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;IAE9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,SAAS,IAAI,CAAC,CAAC,CAAC;IAE9E,6BAA6B;IAC7B,IAAI,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACjD,IAAI,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,mCAAmC,CAAC,CAAC,CAAC;YAC/D,OAAO;QACT,CAAC;IACH,CAAC;IAED,cAAc;IACd,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;IAC/E,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CAAC,kDAAkD,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC,CAClG,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AAYA,wBAAsB,WAAW,CAAC,OAAO,EAAE;IACzC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2FhB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import { loadConfig } from "../../config/loader.js";
|
|
4
|
+
import { getDb } from "../../storage/db.js";
|
|
5
|
+
import { scanFiles } from "../../scanner/index.js";
|
|
6
|
+
import { recordSession, getLastSessionTime, getLatestSessionTime, getRecentChanges, } from "../../storage/snapshots.js";
|
|
7
|
+
export async function scanCommand(options) {
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
const db = getDb();
|
|
10
|
+
// Record session if this is a session-triggered scan
|
|
11
|
+
let lastSession = null;
|
|
12
|
+
if (options.session) {
|
|
13
|
+
// Debounce: skip scan if a session was recorded less than 60 seconds ago
|
|
14
|
+
const latestSession = getLatestSessionTime(db);
|
|
15
|
+
if (latestSession) {
|
|
16
|
+
const elapsed = Date.now() - new Date(latestSession + "Z").getTime();
|
|
17
|
+
if (elapsed < 60_000) {
|
|
18
|
+
recordSession(db);
|
|
19
|
+
db.close();
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
lastSession = getLastSessionTime(db);
|
|
24
|
+
recordSession(db);
|
|
25
|
+
}
|
|
26
|
+
const results = scanFiles(db, config);
|
|
27
|
+
const changed = results.filter((r) => r.result.changed);
|
|
28
|
+
const newFiles = results.filter((r) => r.result.isNew);
|
|
29
|
+
if (options.quiet && changed.length === 0) {
|
|
30
|
+
db.close();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
if (changed.length === 0 && !options.session) {
|
|
34
|
+
console.log(chalk.dim("No changes detected."));
|
|
35
|
+
db.close();
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
// Session mode: show changes since last session
|
|
39
|
+
if (options.session) {
|
|
40
|
+
if (lastSession) {
|
|
41
|
+
const recentChanges = getRecentChanges(db, lastSession, 10);
|
|
42
|
+
if (recentChanges.length === 0) {
|
|
43
|
+
db.close();
|
|
44
|
+
return; // silent when no changes
|
|
45
|
+
}
|
|
46
|
+
console.log(chalk.bold(`\ndotmd: ${recentChanges.length} file${recentChanges.length === 1 ? "" : "s"} changed since last session`));
|
|
47
|
+
const toShow = recentChanges.slice(0, 5);
|
|
48
|
+
for (const change of toShow) {
|
|
49
|
+
const display = change.path.replace(os.homedir(), "~");
|
|
50
|
+
const lines = (change.diff?.match(/\n/g) || []).length;
|
|
51
|
+
console.log(chalk.dim(` ${display} — ${lines} lines changed`));
|
|
52
|
+
}
|
|
53
|
+
if (recentChanges.length > 5) {
|
|
54
|
+
console.log(chalk.dim(` and ${recentChanges.length - 5} more — run \`dotmd status\` for details`));
|
|
55
|
+
}
|
|
56
|
+
console.log();
|
|
57
|
+
}
|
|
58
|
+
db.close();
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
// Normal scan output
|
|
62
|
+
if (newFiles.length > 0) {
|
|
63
|
+
console.log(chalk.green(`${newFiles.length} new file(s) tracked`));
|
|
64
|
+
}
|
|
65
|
+
if (changed.length > 0) {
|
|
66
|
+
console.log(chalk.yellow(`${changed.length} file(s) changed:`));
|
|
67
|
+
for (const r of changed) {
|
|
68
|
+
const display = r.path.replace(os.homedir(), "~");
|
|
69
|
+
console.log(` ${display}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
console.log(chalk.dim(`\nScanned ${results.length} files total.`));
|
|
73
|
+
db.close();
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=scan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scan.js","sourceRoot":"","sources":["../../../src/cli/commands/scan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAGjC;IACC,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IAEnB,qDAAqD;IACrD,IAAI,WAAW,GAAkB,IAAI,CAAC;IACtC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,yEAAyE;QACzE,MAAM,aAAa,GAAG,oBAAoB,CAAC,EAAE,CAAC,CAAC;QAC/C,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC;YACrE,IAAI,OAAO,GAAG,MAAM,EAAE,CAAC;gBACrB,aAAa,CAAC,EAAE,CAAC,CAAC;gBAClB,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO;YACT,CAAC;QACH,CAAC;QAED,WAAW,GAAG,kBAAkB,CAAC,EAAE,CAAC,CAAC;QACrC,aAAa,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACxD,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IAEvD,IAAI,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1C,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IAED,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAC7C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC/C,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IAED,gDAAgD;IAChD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,aAAa,GAAG,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,EAAE,CAAC,CAAC;YAC5D,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC/B,EAAE,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,yBAAyB;YACnC,CAAC;YAED,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,IAAI,CACR,YAAY,aAAa,CAAC,MAAM,QAAQ,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,6BAA6B,CAC3G,CACF,CAAC;YAEF,MAAM,MAAM,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACzC,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;gBAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;gBACvD,MAAM,KAAK,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC;gBACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,MAAM,KAAK,gBAAgB,CAAC,CAAC,CAAC;YAClE,CAAC;YAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7B,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,GAAG,CACP,SAAS,aAAa,CAAC,MAAM,GAAG,CAAC,0CAA0C,CAC5E,CACF,CAAC;YACJ,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;QACD,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IAED,qBAAqB;IACrB,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC,MAAM,sBAAsB,CAAC,CAAC,CAAC;IACrE,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CACT,KAAK,CAAC,MAAM,CACV,GAAG,OAAO,CAAC,MAAM,mBAAmB,CACrC,CACF,CAAC;QACF,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,MAAM,OAAO,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;YAClD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QAC9B,CAAC;IACH,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,aAAa,OAAO,CAAC,MAAM,eAAe,CAAC,CAAC,CAAC;IACnE,EAAE,CAAC,KAAK,EAAE,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"AAGA,wBAAsB,YAAY,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAI5E"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { startServer } from "../../dashboard/server.js";
|
|
3
|
+
export async function serveCommand(options) {
|
|
4
|
+
const port = options.port ? parseInt(options.port, 10) : 3333;
|
|
5
|
+
console.log(chalk.bold(`\nStarting dotmd dashboard on port ${port}...\n`));
|
|
6
|
+
startServer(port);
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/cli/commands/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAExD,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAA0B;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,sCAAsC,IAAI,OAAO,CAAC,CAAC,CAAC;IAC3E,WAAW,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAUA,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAoEnD"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import os from "os";
|
|
3
|
+
import { loadConfig } from "../../config/loader.js";
|
|
4
|
+
import { getDb } from "../../storage/db.js";
|
|
5
|
+
import { scanFiles } from "../../scanner/index.js";
|
|
6
|
+
import { getTrackedFiles, getRecentChanges, } from "../../storage/snapshots.js";
|
|
7
|
+
export async function statusCommand() {
|
|
8
|
+
const db = getDb();
|
|
9
|
+
const config = loadConfig();
|
|
10
|
+
scanFiles(db, config);
|
|
11
|
+
const files = getTrackedFiles(db);
|
|
12
|
+
if (files.length === 0) {
|
|
13
|
+
console.log(chalk.yellow("No tracked files. Run `dotmd init` first."));
|
|
14
|
+
db.close();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
// Group by category
|
|
18
|
+
const groups = {};
|
|
19
|
+
for (const file of files) {
|
|
20
|
+
if (!groups[file.category])
|
|
21
|
+
groups[file.category] = [];
|
|
22
|
+
groups[file.category].push(file);
|
|
23
|
+
}
|
|
24
|
+
const fixedLabels = {
|
|
25
|
+
global: "Claude Code Global",
|
|
26
|
+
memory: "Claude Code Memory",
|
|
27
|
+
custom: "Other",
|
|
28
|
+
};
|
|
29
|
+
function getCatLabel(cat) {
|
|
30
|
+
if (fixedLabels[cat])
|
|
31
|
+
return fixedLabels[cat];
|
|
32
|
+
if (cat.startsWith("project:"))
|
|
33
|
+
return cat.slice("project:".length);
|
|
34
|
+
return cat;
|
|
35
|
+
}
|
|
36
|
+
function getCatSortKey(cat) {
|
|
37
|
+
if (cat === "global")
|
|
38
|
+
return 0;
|
|
39
|
+
if (cat === "memory")
|
|
40
|
+
return 1;
|
|
41
|
+
if (cat.startsWith("project:"))
|
|
42
|
+
return 2;
|
|
43
|
+
return 3;
|
|
44
|
+
}
|
|
45
|
+
const sortedCategories = Object.keys(groups).sort((a, b) => getCatSortKey(a) - getCatSortKey(b) || a.localeCompare(b));
|
|
46
|
+
console.log(chalk.bold(`\nTracking ${files.length} files:\n`));
|
|
47
|
+
for (const cat of sortedCategories) {
|
|
48
|
+
const catFiles = groups[cat];
|
|
49
|
+
if (!catFiles || catFiles.length === 0)
|
|
50
|
+
continue;
|
|
51
|
+
console.log(chalk.dim(`── ${getCatLabel(cat)} ──`));
|
|
52
|
+
for (const file of catFiles) {
|
|
53
|
+
const display = file.path.replace(os.homedir(), "~");
|
|
54
|
+
console.log(` ${display}`);
|
|
55
|
+
}
|
|
56
|
+
console.log();
|
|
57
|
+
}
|
|
58
|
+
// Recent changes
|
|
59
|
+
const recent = getRecentChanges(db, undefined, 5);
|
|
60
|
+
if (recent.length > 0) {
|
|
61
|
+
console.log(chalk.bold("Recent changes:"));
|
|
62
|
+
for (const change of recent) {
|
|
63
|
+
const display = change.path.replace(os.homedir(), "~");
|
|
64
|
+
console.log(chalk.dim(` ${display} — ${change.created_at}`));
|
|
65
|
+
}
|
|
66
|
+
console.log();
|
|
67
|
+
}
|
|
68
|
+
db.close();
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=status.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/cli/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACnD,OAAO,EACL,eAAe,EACf,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,MAAM,EAAE,GAAG,KAAK,EAAE,CAAC;IACnB,MAAM,MAAM,GAAG,UAAU,EAAE,CAAC;IAC5B,SAAS,CAAC,EAAE,EAAE,MAAM,CAAC,CAAC;IACtB,MAAM,KAAK,GAAG,eAAe,CAAC,EAAE,CAAC,CAAC;IAElC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,2CAA2C,CAAC,CAAC,CAAC;QACvE,EAAE,CAAC,KAAK,EAAE,CAAC;QACX,OAAO;IACT,CAAC;IAED,oBAAoB;IACpB,MAAM,MAAM,GAAiC,EAAE,CAAC;IAChD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;YAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;QACvD,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnC,CAAC;IAED,MAAM,WAAW,GAA2B;QAC1C,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,oBAAoB;QAC5B,MAAM,EAAE,OAAO;KAChB,CAAC;IAEF,SAAS,WAAW,CAAC,GAAW;QAC9B,IAAI,WAAW,CAAC,GAAG,CAAC;YAAE,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC;QAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;QACpE,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS,aAAa,CAAC,GAAW;QAChC,IAAI,GAAG,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC;QAC/B,IAAI,GAAG,KAAK,QAAQ;YAAE,OAAO,CAAC,CAAC;QAC/B,IAAI,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC;YAAE,OAAO,CAAC,CAAC;QACzC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAC/C,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CACpE,CAAC;IAEF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,KAAK,CAAC,MAAM,WAAW,CAAC,CAAC,CAAC;IAE/D,KAAK,MAAM,GAAG,IAAI,gBAAgB,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7B,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,SAAS;QAEjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;QACpD,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;YACrD,OAAO,CAAC,GAAG,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;QAC9B,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,iBAAiB;IACjB,MAAM,MAAM,GAAG,gBAAgB,CAAC,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC;QAC3C,KAAK,MAAM,MAAM,IAAI,MAAM,EAAE,CAAC;YAC5B,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,MAAM,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,EAAE,CAAC,KAAK,EAAE,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { initCommand } from "./commands/init.js";
|
|
4
|
+
import { scanCommand } from "./commands/scan.js";
|
|
5
|
+
import { statusCommand } from "./commands/status.js";
|
|
6
|
+
import { installHookCommand } from "./commands/install-hook.js";
|
|
7
|
+
import { serveCommand } from "./commands/serve.js";
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name("dotmd")
|
|
11
|
+
.description("Track changes to AI instruction files")
|
|
12
|
+
.version("0.1.0");
|
|
13
|
+
program
|
|
14
|
+
.command("init")
|
|
15
|
+
.description("Open the setup wizard in your browser")
|
|
16
|
+
.option("-p, --port <port>", "Port for setup wizard", "3333")
|
|
17
|
+
.action(initCommand);
|
|
18
|
+
program
|
|
19
|
+
.command("scan", { hidden: true })
|
|
20
|
+
.description("Scan tracked files for changes")
|
|
21
|
+
.option("-q, --quiet", "Only output if changes detected")
|
|
22
|
+
.option("-s, --session", "Session-triggered scan (shows changes since last session)")
|
|
23
|
+
.action(scanCommand);
|
|
24
|
+
program
|
|
25
|
+
.command("status")
|
|
26
|
+
.description("Show tracked files and recent changes")
|
|
27
|
+
.action(statusCommand);
|
|
28
|
+
program
|
|
29
|
+
.command("install-hook", { hidden: true })
|
|
30
|
+
.description("Install shell hook for session-triggered scans")
|
|
31
|
+
.action(installHookCommand);
|
|
32
|
+
program
|
|
33
|
+
.command("serve")
|
|
34
|
+
.description("Start the web dashboard")
|
|
35
|
+
.option("-p, --port <port>", "Port to listen on", "3333")
|
|
36
|
+
.action(serveCommand);
|
|
37
|
+
program.parse();
|
|
38
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAEnD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,OAAO,CAAC;KACb,WAAW,CAAC,uCAAuC,CAAC;KACpD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,mBAAmB,EAAE,uBAAuB,EAAE,MAAM,CAAC;KAC5D,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KACjC,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,aAAa,EAAE,iCAAiC,CAAC;KACxD,MAAM,CAAC,eAAe,EAAE,2DAA2D,CAAC;KACpF,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,uCAAuC,CAAC;KACpD,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KACzC,WAAW,CAAC,gDAAgD,CAAC;KAC7D,MAAM,CAAC,kBAAkB,CAAC,CAAC;AAE9B,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,yBAAyB,CAAC;KACtC,MAAM,CAAC,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,CAAC;KACxD,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface DotmdConfig {
|
|
2
|
+
scan_roots: string[];
|
|
3
|
+
patterns: string[];
|
|
4
|
+
exclude: string[];
|
|
5
|
+
}
|
|
6
|
+
export declare const DOTMD_DIR: string;
|
|
7
|
+
export declare const CONFIG_PATH: string;
|
|
8
|
+
export declare const DB_PATH: string;
|
|
9
|
+
export declare const DEFAULT_CONFIG: DotmdConfig;
|
|
10
|
+
export declare const SUGGESTED_ROOTS: string[];
|
|
11
|
+
export declare const SUGGESTED_PATTERNS: string[];
|
|
12
|
+
export declare function expandHome(p: string): string;
|
|
13
|
+
//# sourceMappingURL=defaults.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,eAAO,MAAM,SAAS,QAAoC,CAAC;AAC3D,eAAO,MAAM,WAAW,QAAsC,CAAC;AAC/D,eAAO,MAAM,OAAO,QAAqC,CAAC;AAE1D,eAAO,MAAM,cAAc,EAAE,WAU5B,CAAC;AAEF,eAAO,MAAM,eAAe,UAI3B,CAAC;AAEF,eAAO,MAAM,kBAAkB,UAO9B,CAAC;AAEF,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAK5C"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import os from "os";
|
|
2
|
+
import path from "path";
|
|
3
|
+
export const DOTMD_DIR = path.join(os.homedir(), ".dotmd");
|
|
4
|
+
export const CONFIG_PATH = path.join(DOTMD_DIR, "config.yaml");
|
|
5
|
+
export const DB_PATH = path.join(DOTMD_DIR, "history.db");
|
|
6
|
+
export const DEFAULT_CONFIG = {
|
|
7
|
+
scan_roots: [path.join("~", ".claude")],
|
|
8
|
+
patterns: ["CLAUDE.md", "AGENTS.md", "MEMORY.md"],
|
|
9
|
+
exclude: [
|
|
10
|
+
"**/node_modules/**",
|
|
11
|
+
"**/.git/**",
|
|
12
|
+
"**/vendor/**",
|
|
13
|
+
"**/plugins/**",
|
|
14
|
+
"**/cache/**",
|
|
15
|
+
],
|
|
16
|
+
};
|
|
17
|
+
export const SUGGESTED_ROOTS = [
|
|
18
|
+
"~/.claude",
|
|
19
|
+
"~/projects",
|
|
20
|
+
"~/dev",
|
|
21
|
+
];
|
|
22
|
+
export const SUGGESTED_PATTERNS = [
|
|
23
|
+
"CLAUDE.md",
|
|
24
|
+
"AGENTS.md",
|
|
25
|
+
"MEMORY.md",
|
|
26
|
+
"SKILL.md",
|
|
27
|
+
".cursorrules",
|
|
28
|
+
".windsurfrules",
|
|
29
|
+
];
|
|
30
|
+
export function expandHome(p) {
|
|
31
|
+
if (p.startsWith("~")) {
|
|
32
|
+
return path.join(os.homedir(), p.slice(1));
|
|
33
|
+
}
|
|
34
|
+
return p;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=defaults.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/config/defaults.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAQxB,MAAM,CAAC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAC3D,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;AAC/D,MAAM,CAAC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;AAE1D,MAAM,CAAC,MAAM,cAAc,GAAgB;IACzC,UAAU,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;IACvC,QAAQ,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,WAAW,CAAC;IACjD,OAAO,EAAE;QACP,oBAAoB;QACpB,YAAY;QACZ,cAAc;QACd,eAAe;QACf,aAAa;KACd;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,WAAW;IACX,YAAY;IACZ,OAAO;CACR,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,WAAW;IACX,WAAW;IACX,WAAW;IACX,UAAU;IACV,cAAc;IACd,gBAAgB;CACjB,CAAC;AAEF,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC7C,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.d.ts","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,WAAW,EAIZ,MAAM,eAAe,CAAC;AAEvB,wBAAgB,UAAU,CAAC,UAAU,GAAE,MAAoB,GAAG,WAAW,CAiBxE;AAED,wBAAgB,UAAU,CACxB,MAAM,EAAE,WAAW,EACnB,UAAU,GAAE,MAAoB,GAC/B,IAAI,CAON"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import { parse, stringify } from "yaml";
|
|
3
|
+
import { DEFAULT_CONFIG, CONFIG_PATH, DOTMD_DIR, } from "./defaults.js";
|
|
4
|
+
export function loadConfig(configPath = CONFIG_PATH) {
|
|
5
|
+
if (!fs.existsSync(configPath)) {
|
|
6
|
+
return { ...DEFAULT_CONFIG };
|
|
7
|
+
}
|
|
8
|
+
const raw = fs.readFileSync(configPath, "utf-8");
|
|
9
|
+
try {
|
|
10
|
+
const parsed = parse(raw);
|
|
11
|
+
return {
|
|
12
|
+
scan_roots: parsed.scan_roots ?? DEFAULT_CONFIG.scan_roots,
|
|
13
|
+
patterns: parsed.patterns ?? DEFAULT_CONFIG.patterns,
|
|
14
|
+
exclude: parsed.exclude ?? DEFAULT_CONFIG.exclude,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
catch (err) {
|
|
18
|
+
throw new Error(`Failed to parse config at ${configPath}: ${err.message}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export function saveConfig(config, configPath = CONFIG_PATH) {
|
|
22
|
+
if (!fs.existsSync(DOTMD_DIR)) {
|
|
23
|
+
fs.mkdirSync(DOTMD_DIR, { recursive: true });
|
|
24
|
+
}
|
|
25
|
+
const content = stringify(config);
|
|
26
|
+
fs.writeFileSync(configPath, content, "utf-8");
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACxC,OAAO,EAEL,cAAc,EACd,WAAW,EACX,SAAS,GACV,MAAM,eAAe,CAAC;AAEvB,MAAM,UAAU,UAAU,CAAC,aAAqB,WAAW;IACzD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,CAAC;IAED,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAyB,CAAC;QAClD,OAAO;YACL,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,cAAc,CAAC,UAAU;YAC1D,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,cAAc,CAAC,QAAQ;YACpD,OAAO,EAAE,MAAM,CAAC,OAAO,IAAI,cAAc,CAAC,OAAO;SAClD,CAAC;IACJ,CAAC;IAAC,OAAO,GAAQ,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CAAC,6BAA6B,UAAU,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC7E,CAAC;AACH,CAAC;AAED,MAAM,UAAU,UAAU,CACxB,MAAmB,EACnB,aAAqB,WAAW;IAEhC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,CAAC;IAED,MAAM,OAAO,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC;IAClC,EAAE,CAAC,aAAa,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.d.ts","sourceRoot":"","sources":["../../src/dashboard/layout.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,CA8CtF"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function layout(title, content, options) {
|
|
2
|
+
const nav = options?.hideNav
|
|
3
|
+
? ""
|
|
4
|
+
: `<nav class="bg-white border-b border-gray-200 px-6 py-3">
|
|
5
|
+
<div class="max-w-5xl mx-auto flex items-center gap-6">
|
|
6
|
+
<a href="/" class="font-bold text-lg">dotmd</a>
|
|
7
|
+
<a href="/timeline" class="text-gray-600 hover:text-gray-900">Timeline</a>
|
|
8
|
+
<a href="/files" class="text-gray-600 hover:text-gray-900">Files</a>
|
|
9
|
+
<a href="/settings" class="text-gray-600 hover:text-gray-900">Settings</a>
|
|
10
|
+
<button
|
|
11
|
+
onclick="fetch('/api/scan', { method: 'POST' }).then(() => location.reload())"
|
|
12
|
+
class="ml-auto flex items-center gap-1.5 text-gray-400 hover:text-gray-700 transition-colors"
|
|
13
|
+
title="Scan now"
|
|
14
|
+
>
|
|
15
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15"/></svg>
|
|
16
|
+
<span class="text-sm">Refresh</span>
|
|
17
|
+
</button>
|
|
18
|
+
</div>
|
|
19
|
+
</nav>`;
|
|
20
|
+
return `<!DOCTYPE html>
|
|
21
|
+
<html lang="en">
|
|
22
|
+
<head>
|
|
23
|
+
<meta charset="UTF-8">
|
|
24
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
25
|
+
<title>${title} — dotmd</title>
|
|
26
|
+
<link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
|
|
27
|
+
<style>
|
|
28
|
+
.diff-add { background: #dcfce7; }
|
|
29
|
+
.diff-del { background: #fee2e2; }
|
|
30
|
+
.diff-hunk { color: #6b7280; background: #f3f4f6; }
|
|
31
|
+
</style>
|
|
32
|
+
${options?.scripts ?? ""}
|
|
33
|
+
<script>
|
|
34
|
+
window.addEventListener('pageshow', function(e) {
|
|
35
|
+
if (e.persisted) location.reload();
|
|
36
|
+
});
|
|
37
|
+
</script>
|
|
38
|
+
</head>
|
|
39
|
+
<body class="bg-gray-50 text-gray-900 min-h-screen">
|
|
40
|
+
${nav}
|
|
41
|
+
<main class="max-w-5xl mx-auto px-6 py-8">
|
|
42
|
+
${content}
|
|
43
|
+
</main>
|
|
44
|
+
</body>
|
|
45
|
+
</html>`;
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/dashboard/layout.ts"],"names":[],"mappings":"AAKA,MAAM,UAAU,MAAM,CAAC,KAAa,EAAE,OAAe,EAAE,OAAuB;IAC5E,MAAM,GAAG,GAAG,OAAO,EAAE,OAAO;QAC1B,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC;;;;;;;;;;;;;;;SAeG,CAAC;IAER,OAAO;;;;;WAKE,KAAK;;;;;;;IAOZ,OAAO,EAAE,OAAO,IAAI,EAAE;;;;;;;;IAQtB,GAAG;;MAED,OAAO;;;QAGL,CAAC;AACT,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Hono } from "hono";
|
|
2
|
+
import Database from "better-sqlite3";
|
|
3
|
+
export declare function createApp(db: Database.Database): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
4
|
+
export declare function startServer(port?: number): void;
|
|
5
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/dashboard/server.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AA8BtC,wBAAgB,SAAS,CAAC,EAAE,EAAE,QAAQ,CAAC,QAAQ,8EA4U9C;AAED,wBAAgB,WAAW,CAAC,IAAI,GAAE,MAAa,GAAG,IAAI,CAWrD"}
|