devday 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 +58 -0
- package/bin/devday.js +2 -0
- package/dist/config.d.ts +14 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +89 -0
- package/dist/config.js.map +1 -0
- package/dist/cost.d.ts +12 -0
- package/dist/cost.d.ts.map +1 -0
- package/dist/cost.js +47 -0
- package/dist/cost.js.map +1 -0
- package/dist/git.d.ts +6 -0
- package/dist/git.d.ts.map +1 -0
- package/dist/git.js +95 -0
- package/dist/git.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +231 -0
- package/dist/index.js.map +1 -0
- package/dist/merge.d.ts +6 -0
- package/dist/merge.d.ts.map +1 -0
- package/dist/merge.js +80 -0
- package/dist/merge.js.map +1 -0
- package/dist/parsers/claude-code.d.ts +18 -0
- package/dist/parsers/claude-code.d.ts.map +1 -0
- package/dist/parsers/claude-code.js +385 -0
- package/dist/parsers/claude-code.js.map +1 -0
- package/dist/parsers/cursor.d.ts +15 -0
- package/dist/parsers/cursor.d.ts.map +1 -0
- package/dist/parsers/cursor.js +302 -0
- package/dist/parsers/cursor.js.map +1 -0
- package/dist/parsers/opencode.d.ts +21 -0
- package/dist/parsers/opencode.d.ts.map +1 -0
- package/dist/parsers/opencode.js +301 -0
- package/dist/parsers/opencode.js.map +1 -0
- package/dist/render.d.ts +6 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +161 -0
- package/dist/render.js.map +1 -0
- package/dist/summarize.d.ts +8 -0
- package/dist/summarize.d.ts.map +1 -0
- package/dist/summarize.js +157 -0
- package/dist/summarize.js.map +1 -0
- package/dist/types.d.ts +100 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +23 -0
- package/dist/types.js.map +1 -0
- package/package.json +54 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# devday
|
|
2
|
+
|
|
3
|
+
End-of-day recap for AI-assisted coding sessions. Reads your local conversations from OpenCode, Claude Code, and Cursor, cross-references with git, and generates standup-ready summaries.
|
|
4
|
+
|
|
5
|
+
## What it does
|
|
6
|
+
|
|
7
|
+
- Scans completed AI coding sessions from your local machine (nothing leaves your machine unless you enable LLM summaries)
|
|
8
|
+
- Shows tokens used, estimated cost, duration, and models per session
|
|
9
|
+
- Groups sessions by project and shows git commits alongside
|
|
10
|
+
- Optionally generates first-person standup messages via OpenAI or Anthropic
|
|
11
|
+
|
|
12
|
+
## Supported tools
|
|
13
|
+
|
|
14
|
+
| Tool | Data source |
|
|
15
|
+
|------|------------|
|
|
16
|
+
| OpenCode | `~/.local/share/opencode/storage/` |
|
|
17
|
+
| Claude Code | `~/.claude/` (SQLite + JSONL) |
|
|
18
|
+
| Cursor | `~/Library/Application Support/Cursor/User/globalStorage/state.vscdb` |
|
|
19
|
+
|
|
20
|
+
## Install
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
git clone https://github.com/ujjwaljainnn/devday.git
|
|
24
|
+
cd devday
|
|
25
|
+
npm install
|
|
26
|
+
npm run build
|
|
27
|
+
npm link
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Usage
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
devday # today's recap
|
|
34
|
+
devday -d yesterday # yesterday
|
|
35
|
+
devday -d 2026-02-11 # specific date
|
|
36
|
+
devday --standup # short standup format
|
|
37
|
+
devday --json # machine-readable output
|
|
38
|
+
devday --no-git # skip git integration
|
|
39
|
+
devday --no-summarize # skip LLM summaries
|
|
40
|
+
devday -v # debug output
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## AI summaries
|
|
44
|
+
|
|
45
|
+
Summaries are optional. Without an API key, devday shows stats and git only.
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
export OPENAI_API_KEY=sk-... # or
|
|
49
|
+
export ANTHROPIC_API_KEY=sk-...
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## How it works
|
|
53
|
+
|
|
54
|
+
devday reads completed sessions from each tool's local storage. Active sessions (still running) may not appear until they're closed. Sessions are grouped by project directory, and git commits are matched by date.
|
|
55
|
+
|
|
56
|
+
Duration is calculated from actual message processing times (not wall-clock), capped at 5 minutes per message to handle tools that write bogus completion timestamps.
|
|
57
|
+
|
|
58
|
+
Cost is estimated from token counts and model pricing tables when the tool doesn't provide it directly.
|
package/bin/devday.js
ADDED
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { DevDayConfig } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Load config purely from environment variables + auto-detection.
|
|
4
|
+
* API keys come from env vars only (OPENAI_API_KEY, ANTHROPIC_API_KEY).
|
|
5
|
+
* Tool paths are auto-detected. Non-sensitive preferences can be saved to config file.
|
|
6
|
+
*/
|
|
7
|
+
export declare function loadConfig(): DevDayConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Save non-sensitive preferences to config file.
|
|
10
|
+
* API keys are NEVER written to disk.
|
|
11
|
+
*/
|
|
12
|
+
export declare function saveConfig(config: DevDayConfig): void;
|
|
13
|
+
export declare function getConfigPath(): string;
|
|
14
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAY,MAAM,YAAY,CAAC;AA+BzD;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,YAAY,CAuCzC;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAOrD;AAED,wBAAgB,aAAa,IAAI,MAAM,CAEtC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
const CONFIG_DIR = join(homedir(), '.config', 'devday');
|
|
5
|
+
const CONFIG_FILE = join(CONFIG_DIR, 'config.json');
|
|
6
|
+
function getDefaultPaths() {
|
|
7
|
+
const home = homedir();
|
|
8
|
+
const platform = process.platform;
|
|
9
|
+
return {
|
|
10
|
+
opencodeStorage: join(home, '.local', 'share', 'opencode', 'storage'),
|
|
11
|
+
claudeCodeHome: join(home, '.claude'),
|
|
12
|
+
cursorStateDb: platform === 'darwin'
|
|
13
|
+
? join(home, 'Library', 'Application Support', 'Cursor', 'User', 'globalStorage', 'state.vscdb')
|
|
14
|
+
: platform === 'win32'
|
|
15
|
+
? join(home, 'AppData', 'Roaming', 'Cursor', 'User', 'globalStorage', 'state.vscdb')
|
|
16
|
+
: join(home, '.config', 'Cursor', 'User', 'globalStorage', 'state.vscdb'),
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function detectAvailableTools() {
|
|
20
|
+
const paths = getDefaultPaths();
|
|
21
|
+
const tools = [];
|
|
22
|
+
if (existsSync(paths.opencodeStorage))
|
|
23
|
+
tools.push('opencode');
|
|
24
|
+
if (existsSync(paths.claudeCodeHome))
|
|
25
|
+
tools.push('claude-code');
|
|
26
|
+
if (existsSync(paths.cursorStateDb))
|
|
27
|
+
tools.push('cursor');
|
|
28
|
+
return tools;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Load config purely from environment variables + auto-detection.
|
|
32
|
+
* API keys come from env vars only (OPENAI_API_KEY, ANTHROPIC_API_KEY).
|
|
33
|
+
* Tool paths are auto-detected. Non-sensitive preferences can be saved to config file.
|
|
34
|
+
*/
|
|
35
|
+
export function loadConfig() {
|
|
36
|
+
const paths = getDefaultPaths();
|
|
37
|
+
const anthropicKey = process.env.ANTHROPIC_API_KEY ?? null;
|
|
38
|
+
const openaiKey = process.env.OPENAI_API_KEY ?? null;
|
|
39
|
+
// Prefer OpenAI (cheaper for summarization), fall back to Anthropic
|
|
40
|
+
let preferredSummarizer = 'none';
|
|
41
|
+
if (openaiKey)
|
|
42
|
+
preferredSummarizer = 'openai';
|
|
43
|
+
else if (anthropicKey)
|
|
44
|
+
preferredSummarizer = 'anthropic';
|
|
45
|
+
const defaults = {
|
|
46
|
+
anthropicApiKey: anthropicKey,
|
|
47
|
+
openaiApiKey: openaiKey,
|
|
48
|
+
preferredSummarizer,
|
|
49
|
+
paths: {
|
|
50
|
+
opencodeStorage: existsSync(paths.opencodeStorage) ? paths.opencodeStorage : null,
|
|
51
|
+
claudeCodeHome: existsSync(paths.claudeCodeHome) ? paths.claudeCodeHome : null,
|
|
52
|
+
cursorStateDb: existsSync(paths.cursorStateDb) ? paths.cursorStateDb : null,
|
|
53
|
+
},
|
|
54
|
+
enabledTools: detectAvailableTools(),
|
|
55
|
+
gitAuthorFilter: null,
|
|
56
|
+
};
|
|
57
|
+
// Merge non-sensitive preferences from config file (gitAuthorFilter, etc.)
|
|
58
|
+
if (existsSync(CONFIG_FILE)) {
|
|
59
|
+
try {
|
|
60
|
+
const raw = readFileSync(CONFIG_FILE, 'utf-8');
|
|
61
|
+
const saved = JSON.parse(raw);
|
|
62
|
+
// Only merge non-sensitive fields — never read keys from file
|
|
63
|
+
if (saved.gitAuthorFilter)
|
|
64
|
+
defaults.gitAuthorFilter = saved.gitAuthorFilter;
|
|
65
|
+
if (saved.enabledTools)
|
|
66
|
+
defaults.enabledTools = saved.enabledTools;
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// Ignore corrupt config
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return defaults;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Save non-sensitive preferences to config file.
|
|
76
|
+
* API keys are NEVER written to disk.
|
|
77
|
+
*/
|
|
78
|
+
export function saveConfig(config) {
|
|
79
|
+
mkdirSync(CONFIG_DIR, { recursive: true });
|
|
80
|
+
const safe = {
|
|
81
|
+
gitAuthorFilter: config.gitAuthorFilter,
|
|
82
|
+
enabledTools: config.enabledTools,
|
|
83
|
+
};
|
|
84
|
+
writeFileSync(CONFIG_FILE, JSON.stringify(safe, null, 2), 'utf-8');
|
|
85
|
+
}
|
|
86
|
+
export function getConfigPath() {
|
|
87
|
+
return CONFIG_FILE;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/cost.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type TokenUsage } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Estimate cost in USD from token usage and model name.
|
|
4
|
+
* Falls back to a generic mid-tier pricing if model is unknown.
|
|
5
|
+
*/
|
|
6
|
+
export declare function estimateCost(model: string, tokens: TokenUsage): number;
|
|
7
|
+
/**
|
|
8
|
+
* Sum multiple TokenUsage objects.
|
|
9
|
+
*/
|
|
10
|
+
export declare function sumTokens(...usages: TokenUsage[]): TokenUsage;
|
|
11
|
+
export declare function emptyTokenUsage(): TokenUsage;
|
|
12
|
+
//# sourceMappingURL=cost.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.d.ts","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,UAAU,EAAqB,MAAM,YAAY,CAAC;AAE/E;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,MAAM,CAStE;AAsBD;;GAEG;AACH,wBAAgB,SAAS,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,GAAG,UAAU,CAY7D;AAED,wBAAgB,eAAe,IAAI,UAAU,CAE5C"}
|
package/dist/cost.js
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { MODEL_PRICING } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Estimate cost in USD from token usage and model name.
|
|
4
|
+
* Falls back to a generic mid-tier pricing if model is unknown.
|
|
5
|
+
*/
|
|
6
|
+
export function estimateCost(model, tokens) {
|
|
7
|
+
const pricing = findPricing(model);
|
|
8
|
+
const inputCost = (tokens.input / 1_000_000) * pricing.inputPerMillion;
|
|
9
|
+
const outputCost = (tokens.output / 1_000_000) * pricing.outputPerMillion;
|
|
10
|
+
const cacheReadCost = (tokens.cacheRead / 1_000_000) * (pricing.cacheReadPerMillion ?? pricing.inputPerMillion * 0.1);
|
|
11
|
+
const cacheWriteCost = (tokens.cacheWrite / 1_000_000) * (pricing.cacheWritePerMillion ?? pricing.inputPerMillion * 1.25);
|
|
12
|
+
return inputCost + outputCost + cacheReadCost + cacheWriteCost;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Find pricing for a model, trying exact match first, then prefix/substring match.
|
|
16
|
+
*/
|
|
17
|
+
function findPricing(model) {
|
|
18
|
+
const normalized = model.toLowerCase();
|
|
19
|
+
// Exact match
|
|
20
|
+
if (MODEL_PRICING[normalized])
|
|
21
|
+
return MODEL_PRICING[normalized];
|
|
22
|
+
// Prefix / substring match
|
|
23
|
+
for (const [key, pricing] of Object.entries(MODEL_PRICING)) {
|
|
24
|
+
if (normalized.includes(key) || key.includes(normalized)) {
|
|
25
|
+
return pricing;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
// Heuristic fallback: mid-tier pricing
|
|
29
|
+
return { inputPerMillion: 3, outputPerMillion: 15 };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Sum multiple TokenUsage objects.
|
|
33
|
+
*/
|
|
34
|
+
export function sumTokens(...usages) {
|
|
35
|
+
return usages.reduce((acc, t) => ({
|
|
36
|
+
input: acc.input + t.input,
|
|
37
|
+
output: acc.output + t.output,
|
|
38
|
+
reasoning: acc.reasoning + t.reasoning,
|
|
39
|
+
cacheRead: acc.cacheRead + t.cacheRead,
|
|
40
|
+
cacheWrite: acc.cacheWrite + t.cacheWrite,
|
|
41
|
+
total: acc.total + t.total,
|
|
42
|
+
}), emptyTokenUsage());
|
|
43
|
+
}
|
|
44
|
+
export function emptyTokenUsage() {
|
|
45
|
+
return { input: 0, output: 0, reasoning: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
|
|
46
|
+
}
|
|
47
|
+
//# sourceMappingURL=cost.js.map
|
package/dist/cost.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost.js","sourceRoot":"","sources":["../src/cost.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAsC,MAAM,YAAY,CAAC;AAE/E;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,MAAkB;IAC5D,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IAEnC,MAAM,SAAS,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,eAAe,CAAC;IACvE,MAAM,UAAU,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAC1E,MAAM,aAAa,GAAG,CAAC,MAAM,CAAC,SAAS,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,mBAAmB,IAAI,OAAO,CAAC,eAAe,GAAG,GAAG,CAAC,CAAC;IACtH,MAAM,cAAc,GAAG,CAAC,MAAM,CAAC,UAAU,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,oBAAoB,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC,CAAC;IAE1H,OAAO,SAAS,GAAG,UAAU,GAAG,aAAa,GAAG,cAAc,CAAC;AACjE,CAAC;AAED;;GAEG;AACH,SAAS,WAAW,CAAC,KAAa;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,WAAW,EAAE,CAAC;IAEvC,cAAc;IACd,IAAI,aAAa,CAAC,UAAU,CAAC;QAAE,OAAO,aAAa,CAAC,UAAU,CAAC,CAAC;IAEhE,2BAA2B;IAC3B,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QAC3D,IAAI,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC;YACzD,OAAO,OAAO,CAAC;QACjB,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,OAAO,EAAE,eAAe,EAAE,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,GAAG,MAAoB;IAC/C,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC;QACX,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;QAC1B,MAAM,EAAE,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM;QAC7B,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;QACtC,SAAS,EAAE,GAAG,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS;QACtC,UAAU,EAAE,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,UAAU;QACzC,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK;KAC3B,CAAC,EACF,eAAe,EAAE,CAClB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AACtF,CAAC"}
|
package/dist/git.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { GitActivity } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Get git activity for a project directory on a specific date.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getGitActivity(projectPath: string, date: string, authorFilter?: string | null): GitActivity | null;
|
|
6
|
+
//# sourceMappingURL=git.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAa,MAAM,YAAY,CAAC;AAEzD;;GAEG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,IAAI,EAAE,MAAM,EACZ,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,GAC3B,WAAW,GAAG,IAAI,CAuEpB"}
|
package/dist/git.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
3
|
+
import { join, basename } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* Get git activity for a project directory on a specific date.
|
|
6
|
+
*/
|
|
7
|
+
export function getGitActivity(projectPath, date, authorFilter) {
|
|
8
|
+
// Verify it's a git repo
|
|
9
|
+
if (!existsSync(join(projectPath, '.git')))
|
|
10
|
+
return null;
|
|
11
|
+
try {
|
|
12
|
+
const args = [
|
|
13
|
+
'log',
|
|
14
|
+
`--after=${date}T00:00:00`,
|
|
15
|
+
`--before=${date}T23:59:59`,
|
|
16
|
+
'--format=%H|%h|%an|%aI|%s',
|
|
17
|
+
'--no-merges',
|
|
18
|
+
];
|
|
19
|
+
if (authorFilter) {
|
|
20
|
+
args.push(`--author=${authorFilter}`);
|
|
21
|
+
}
|
|
22
|
+
const raw = execFileSync('git', args, {
|
|
23
|
+
cwd: projectPath,
|
|
24
|
+
encoding: 'utf-8',
|
|
25
|
+
timeout: 10_000,
|
|
26
|
+
}).trim();
|
|
27
|
+
if (!raw) {
|
|
28
|
+
return {
|
|
29
|
+
projectPath,
|
|
30
|
+
projectName: basename(projectPath),
|
|
31
|
+
commits: [],
|
|
32
|
+
totalFilesChanged: 0,
|
|
33
|
+
totalInsertions: 0,
|
|
34
|
+
totalDeletions: 0,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const commitLines = raw.split('\n').filter(Boolean);
|
|
38
|
+
const commits = [];
|
|
39
|
+
for (const line of commitLines) {
|
|
40
|
+
const [hash, shortHash, author, timestamp, ...messageParts] = line.split('|');
|
|
41
|
+
const message = messageParts.join('|'); // message might contain |
|
|
42
|
+
const stats = getCommitStats(projectPath, hash);
|
|
43
|
+
commits.push({
|
|
44
|
+
hash,
|
|
45
|
+
shortHash,
|
|
46
|
+
message,
|
|
47
|
+
author,
|
|
48
|
+
timestamp: new Date(timestamp),
|
|
49
|
+
filesChanged: stats.filesChanged,
|
|
50
|
+
insertions: stats.insertions,
|
|
51
|
+
deletions: stats.deletions,
|
|
52
|
+
files: stats.files,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
const totalFilesChanged = new Set(commits.flatMap((c) => c.files)).size;
|
|
56
|
+
const totalInsertions = commits.reduce((sum, c) => sum + c.insertions, 0);
|
|
57
|
+
const totalDeletions = commits.reduce((sum, c) => sum + c.deletions, 0);
|
|
58
|
+
return {
|
|
59
|
+
projectPath,
|
|
60
|
+
projectName: basename(projectPath),
|
|
61
|
+
commits,
|
|
62
|
+
totalFilesChanged,
|
|
63
|
+
totalInsertions,
|
|
64
|
+
totalDeletions,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function getCommitStats(projectPath, hash) {
|
|
72
|
+
try {
|
|
73
|
+
const raw = execFileSync('git', ['diff-tree', '--no-commit-id', '--numstat', '-r', hash], { cwd: projectPath, encoding: 'utf-8', timeout: 10_000 }).trim();
|
|
74
|
+
if (!raw)
|
|
75
|
+
return { filesChanged: 0, insertions: 0, deletions: 0, files: [] };
|
|
76
|
+
const lines = raw.split('\n').filter(Boolean);
|
|
77
|
+
let insertions = 0;
|
|
78
|
+
let deletions = 0;
|
|
79
|
+
const files = [];
|
|
80
|
+
for (const line of lines) {
|
|
81
|
+
const [ins, del, file] = line.split('\t');
|
|
82
|
+
if (ins !== '-')
|
|
83
|
+
insertions += parseInt(ins, 10) || 0;
|
|
84
|
+
if (del !== '-')
|
|
85
|
+
deletions += parseInt(del, 10) || 0;
|
|
86
|
+
if (file)
|
|
87
|
+
files.push(file);
|
|
88
|
+
}
|
|
89
|
+
return { filesChanged: files.length, insertions, deletions, files };
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return { filesChanged: 0, insertions: 0, deletions: 0, files: [] };
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=git.js.map
|
package/dist/git.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import ora from 'ora';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
import { format, subDays } from 'date-fns';
|
|
5
|
+
import { homedir } from 'node:os';
|
|
6
|
+
import { loadConfig } from './config.js';
|
|
7
|
+
import { OpenCodeParser } from './parsers/opencode.js';
|
|
8
|
+
import { ClaudeCodeParser } from './parsers/claude-code.js';
|
|
9
|
+
import { CursorParser } from './parsers/cursor.js';
|
|
10
|
+
import { getGitActivity } from './git.js';
|
|
11
|
+
import { buildDayRecap } from './merge.js';
|
|
12
|
+
import { summarizeRecap } from './summarize.js';
|
|
13
|
+
import { renderRecap } from './render.js';
|
|
14
|
+
let verbose = false;
|
|
15
|
+
function debug(msg) {
|
|
16
|
+
if (verbose)
|
|
17
|
+
console.error(chalk.dim(` [debug] ${msg}`));
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Resolve date string: supports YYYY-MM-DD, "today", "yesterday"
|
|
21
|
+
*/
|
|
22
|
+
function resolveDate(input) {
|
|
23
|
+
if (!input)
|
|
24
|
+
return format(new Date(), 'yyyy-MM-dd');
|
|
25
|
+
const lower = input.toLowerCase();
|
|
26
|
+
if (lower === 'today')
|
|
27
|
+
return format(new Date(), 'yyyy-MM-dd');
|
|
28
|
+
if (lower === 'yesterday')
|
|
29
|
+
return format(subDays(new Date(), 1), 'yyyy-MM-dd');
|
|
30
|
+
return input;
|
|
31
|
+
}
|
|
32
|
+
const program = new Command();
|
|
33
|
+
program
|
|
34
|
+
.name('devday')
|
|
35
|
+
.description('End-of-day recap for AI-assisted coding sessions')
|
|
36
|
+
.version('0.1.0')
|
|
37
|
+
.option('-d, --date <date>', 'date: YYYY-MM-DD, "today", or "yesterday" (default: today)')
|
|
38
|
+
.option('-s, --standup', 'output a short standup-ready summary')
|
|
39
|
+
.option('-j, --json', 'output raw JSON')
|
|
40
|
+
.option('-v, --verbose', 'show debug output')
|
|
41
|
+
.option('--no-git', 'skip git log integration')
|
|
42
|
+
.option('--no-summarize', 'skip LLM summarization')
|
|
43
|
+
.addHelpText('after', `
|
|
44
|
+
Examples:
|
|
45
|
+
$ devday today's recap
|
|
46
|
+
$ devday -d yesterday yesterday's recap
|
|
47
|
+
$ devday -d 2026-02-10 specific date
|
|
48
|
+
$ devday --standup short standup format
|
|
49
|
+
$ devday --json machine-readable output
|
|
50
|
+
$ devday -d yesterday -s yesterday's standup
|
|
51
|
+
|
|
52
|
+
Environment variables:
|
|
53
|
+
OPENAI_API_KEY enables AI-powered summaries via OpenAI (recommended)
|
|
54
|
+
ANTHROPIC_API_KEY enables AI-powered summaries via Anthropic
|
|
55
|
+
|
|
56
|
+
Supported tools:
|
|
57
|
+
opencode ~/.local/share/opencode/storage/
|
|
58
|
+
claude code ~/.claude/
|
|
59
|
+
cursor ~/Library/.../state.vscdb
|
|
60
|
+
`)
|
|
61
|
+
.action(async (opts) => {
|
|
62
|
+
verbose = opts.verbose ?? false;
|
|
63
|
+
const date = resolveDate(opts.date);
|
|
64
|
+
const config = loadConfig();
|
|
65
|
+
// Validate date format
|
|
66
|
+
if (!/^\d{4}-\d{2}-\d{2}$/.test(date)) {
|
|
67
|
+
console.error(chalk.red(`Invalid date format: "${opts.date}". Use YYYY-MM-DD, "today", or "yesterday".`));
|
|
68
|
+
process.exit(1);
|
|
69
|
+
}
|
|
70
|
+
const isJson = opts.json ?? false;
|
|
71
|
+
// ── First-run banner (skip for JSON output) ───────────────
|
|
72
|
+
if (!isJson) {
|
|
73
|
+
printBanner(config, date);
|
|
74
|
+
}
|
|
75
|
+
const spinner = ora({ text: 'Scanning sessions...', color: 'cyan' });
|
|
76
|
+
if (!verbose && !isJson)
|
|
77
|
+
spinner.start();
|
|
78
|
+
try {
|
|
79
|
+
// ── Initialize parsers ──────────────────────────────────
|
|
80
|
+
const parsers = [];
|
|
81
|
+
if (config.enabledTools.includes('opencode') && config.paths.opencodeStorage) {
|
|
82
|
+
parsers.push(new OpenCodeParser(config.paths.opencodeStorage));
|
|
83
|
+
debug(`opencode storage: ${config.paths.opencodeStorage}`);
|
|
84
|
+
}
|
|
85
|
+
if (config.enabledTools.includes('claude-code') && config.paths.claudeCodeHome) {
|
|
86
|
+
parsers.push(new ClaudeCodeParser(config.paths.claudeCodeHome));
|
|
87
|
+
debug(`claude code home: ${config.paths.claudeCodeHome}`);
|
|
88
|
+
}
|
|
89
|
+
if (config.enabledTools.includes('cursor') && config.paths.cursorStateDb) {
|
|
90
|
+
parsers.push(new CursorParser(config.paths.cursorStateDb));
|
|
91
|
+
debug(`cursor db: ${config.paths.cursorStateDb}`);
|
|
92
|
+
}
|
|
93
|
+
if (parsers.length === 0) {
|
|
94
|
+
spinner.stop();
|
|
95
|
+
printNoToolsMessage();
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// ── Collect sessions ────────────────────────────────────
|
|
99
|
+
const allSessions = [];
|
|
100
|
+
for (const parser of parsers) {
|
|
101
|
+
if (await parser.isAvailable()) {
|
|
102
|
+
spinner.text = `Reading ${parser.name} sessions...`;
|
|
103
|
+
debug(`scanning ${parser.name}...`);
|
|
104
|
+
const sessions = await parser.getSessions(date);
|
|
105
|
+
debug(` found ${sessions.length} session(s) from ${parser.name}`);
|
|
106
|
+
allSessions.push(...sessions);
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
debug(`${parser.name} not available, skipping`);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
// ── Early exit if nothing found ─────────────────────────
|
|
113
|
+
if (allSessions.length === 0) {
|
|
114
|
+
spinner.stop();
|
|
115
|
+
if (!isJson) {
|
|
116
|
+
console.log(chalk.dim(` No sessions found for ${date}.`));
|
|
117
|
+
if (date === format(new Date(), 'yyyy-MM-dd')) {
|
|
118
|
+
console.log(chalk.dim(' Try: devday -d yesterday'));
|
|
119
|
+
}
|
|
120
|
+
console.log('');
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
console.log(JSON.stringify({ date, projects: [], totalSessions: 0 }, null, 2));
|
|
124
|
+
}
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
spinner.text = `Found ${allSessions.length} session(s). Checking git...`;
|
|
128
|
+
// ── Collect git activity ────────────────────────────────
|
|
129
|
+
const gitActivities = [];
|
|
130
|
+
if (opts.git !== false) {
|
|
131
|
+
const projectPaths = [...new Set(allSessions.map((s) => s.projectPath).filter(Boolean))];
|
|
132
|
+
for (const projectPath of projectPaths) {
|
|
133
|
+
debug(`checking git in ${projectPath}`);
|
|
134
|
+
const git = getGitActivity(projectPath, date, config.gitAuthorFilter);
|
|
135
|
+
if (git) {
|
|
136
|
+
debug(` ${git.commits.length} commit(s)`);
|
|
137
|
+
gitActivities.push(git);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
// ── Merge ───────────────────────────────────────────────
|
|
142
|
+
let recap = buildDayRecap(date, allSessions, gitActivities);
|
|
143
|
+
// ── Summarize (only if API key is available) ──────────
|
|
144
|
+
const hasApiKey = config.preferredSummarizer !== 'none';
|
|
145
|
+
if (hasApiKey && opts.summarize !== false) {
|
|
146
|
+
debug(`using ${config.preferredSummarizer} for summarization`);
|
|
147
|
+
spinner.text = 'Generating summary...';
|
|
148
|
+
recap = await summarizeRecap(recap, config);
|
|
149
|
+
}
|
|
150
|
+
else if (!hasApiKey) {
|
|
151
|
+
debug('no API key set, skipping summarization');
|
|
152
|
+
}
|
|
153
|
+
spinner.stop();
|
|
154
|
+
// ── Standup without API key → exit early ────────────────
|
|
155
|
+
if (opts.standup && !hasApiKey) {
|
|
156
|
+
console.log('');
|
|
157
|
+
console.log(chalk.yellow(' Standup requires an API key to generate summaries.'));
|
|
158
|
+
console.log('');
|
|
159
|
+
console.log(' Run:');
|
|
160
|
+
console.log(chalk.cyan(' export OPENAI_API_KEY=sk-...'));
|
|
161
|
+
console.log('');
|
|
162
|
+
console.log(' Then try again:');
|
|
163
|
+
console.log(chalk.cyan(' devday --standup'));
|
|
164
|
+
console.log('');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
// ── Render ──────────────────────────────────────────────
|
|
168
|
+
renderRecap(recap, { standup: opts.standup, json: isJson });
|
|
169
|
+
// Prompt to set API key if not configured
|
|
170
|
+
if (!hasApiKey && !isJson) {
|
|
171
|
+
console.log('');
|
|
172
|
+
console.log(' To generate AI-powered summaries and standup messages:');
|
|
173
|
+
console.log(chalk.cyan(' export OPENAI_API_KEY=sk-...'));
|
|
174
|
+
console.log('');
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
catch (error) {
|
|
178
|
+
spinner.stop();
|
|
179
|
+
console.error(chalk.red('Error:'), error instanceof Error ? error.message : error);
|
|
180
|
+
if (verbose && error instanceof Error && error.stack) {
|
|
181
|
+
console.error(chalk.dim(error.stack));
|
|
182
|
+
}
|
|
183
|
+
process.exit(1);
|
|
184
|
+
}
|
|
185
|
+
});
|
|
186
|
+
program.parse();
|
|
187
|
+
// ── Helper functions ──────────────────────────────────────────────
|
|
188
|
+
function printBanner(config, date) {
|
|
189
|
+
console.log('');
|
|
190
|
+
console.log(chalk.bold.cyan(' devday') + chalk.dim(' v0.1.0'));
|
|
191
|
+
console.log('');
|
|
192
|
+
// Tools detected
|
|
193
|
+
const tools = [];
|
|
194
|
+
if (config.paths.opencodeStorage)
|
|
195
|
+
tools.push(chalk.green('opencode'));
|
|
196
|
+
if (config.paths.claudeCodeHome)
|
|
197
|
+
tools.push(chalk.green('claude code'));
|
|
198
|
+
if (config.paths.cursorStateDb)
|
|
199
|
+
tools.push(chalk.green('cursor'));
|
|
200
|
+
if (tools.length > 0) {
|
|
201
|
+
console.log(chalk.dim(' Tools: ') + tools.join(', '));
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
console.log(chalk.dim(' Tools: ') + chalk.yellow('none detected'));
|
|
205
|
+
}
|
|
206
|
+
// Summarizer status
|
|
207
|
+
if (config.preferredSummarizer !== 'none') {
|
|
208
|
+
console.log(chalk.dim(' Summaries: ') + chalk.green(config.preferredSummarizer));
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
console.log(chalk.dim(' Summaries: ') + chalk.yellow('not configured'));
|
|
212
|
+
}
|
|
213
|
+
console.log(chalk.dim(` Date: ${date}`));
|
|
214
|
+
console.log('');
|
|
215
|
+
}
|
|
216
|
+
function printNoToolsMessage() {
|
|
217
|
+
const home = homedir();
|
|
218
|
+
console.log('');
|
|
219
|
+
console.log(chalk.yellow(' No AI coding tools detected.'));
|
|
220
|
+
console.log('');
|
|
221
|
+
console.log(' devday scans local conversations from these tools:');
|
|
222
|
+
console.log('');
|
|
223
|
+
console.log(` ${chalk.cyan('opencode')} ${chalk.dim(home + '/.local/share/opencode/storage/')}`);
|
|
224
|
+
console.log(` ${chalk.cyan('claude code')} ${chalk.dim(home + '/.claude/')}`);
|
|
225
|
+
console.log(` ${chalk.cyan('cursor')} ${chalk.dim('~/Library/.../state.vscdb')}`);
|
|
226
|
+
console.log('');
|
|
227
|
+
console.log(' Install a supported tool and start a coding session,');
|
|
228
|
+
console.log(' then run ' + chalk.cyan('devday') + ' again.');
|
|
229
|
+
console.log('');
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/merge.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Session, GitActivity, DayRecap } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Merge sessions and git activity into a DayRecap.
|
|
4
|
+
*/
|
|
5
|
+
export declare function buildDayRecap(date: string, sessions: Session[], gitActivities: GitActivity[]): DayRecap;
|
|
6
|
+
//# sourceMappingURL=merge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merge.d.ts","sourceRoot":"","sources":["../src/merge.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,WAAW,EAAkB,QAAQ,EAAY,MAAM,YAAY,CAAC;AAG3F;;GAEG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,OAAO,EAAE,EACnB,aAAa,EAAE,WAAW,EAAE,GAC3B,QAAQ,CAsFV"}
|