claudedash 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +207 -0
  3. package/dist/cli.d.ts +3 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +247 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/core/contextHealth.d.ts +14 -0
  8. package/dist/core/contextHealth.d.ts.map +1 -0
  9. package/dist/core/contextHealth.js +46 -0
  10. package/dist/core/contextHealth.js.map +1 -0
  11. package/dist/core/insightsEngine.d.ts +4 -0
  12. package/dist/core/insightsEngine.d.ts.map +1 -0
  13. package/dist/core/insightsEngine.js +223 -0
  14. package/dist/core/insightsEngine.js.map +1 -0
  15. package/dist/core/logParser.d.ts +11 -0
  16. package/dist/core/logParser.d.ts.map +1 -0
  17. package/dist/core/logParser.js +127 -0
  18. package/dist/core/logParser.js.map +1 -0
  19. package/dist/core/qualityTimeline.d.ts +8 -0
  20. package/dist/core/qualityTimeline.d.ts.map +1 -0
  21. package/dist/core/qualityTimeline.js +40 -0
  22. package/dist/core/qualityTimeline.js.map +1 -0
  23. package/dist/core/queueParser.d.ts +25 -0
  24. package/dist/core/queueParser.d.ts.map +1 -0
  25. package/dist/core/queueParser.js +283 -0
  26. package/dist/core/queueParser.js.map +1 -0
  27. package/dist/core/stateEngine.d.ts +6 -0
  28. package/dist/core/stateEngine.d.ts.map +1 -0
  29. package/dist/core/stateEngine.js +154 -0
  30. package/dist/core/stateEngine.js.map +1 -0
  31. package/dist/core/todoReader.d.ts +12 -0
  32. package/dist/core/todoReader.d.ts.map +1 -0
  33. package/dist/core/todoReader.js +301 -0
  34. package/dist/core/todoReader.js.map +1 -0
  35. package/dist/core/types.d.ts +167 -0
  36. package/dist/core/types.d.ts.map +1 -0
  37. package/dist/core/types.js +2 -0
  38. package/dist/core/types.js.map +1 -0
  39. package/dist/core/worktreeDetector.d.ts +18 -0
  40. package/dist/core/worktreeDetector.d.ts.map +1 -0
  41. package/dist/core/worktreeDetector.js +99 -0
  42. package/dist/core/worktreeDetector.js.map +1 -0
  43. package/dist/core/worktreeMapper.d.ts +10 -0
  44. package/dist/core/worktreeMapper.d.ts.map +1 -0
  45. package/dist/core/worktreeMapper.js +38 -0
  46. package/dist/core/worktreeMapper.js.map +1 -0
  47. package/dist/public/404/index.html +1 -0
  48. package/dist/public/404.html +1 -0
  49. package/dist/public/__next.__PAGE__.txt +9 -0
  50. package/dist/public/__next._full.txt +17 -0
  51. package/dist/public/__next._head.txt +5 -0
  52. package/dist/public/__next._index.txt +5 -0
  53. package/dist/public/__next._tree.txt +2 -0
  54. package/dist/public/_next/static/36m05Da62vzqVee_ifGeq/_buildManifest.js +42 -0
  55. package/dist/public/_next/static/36m05Da62vzqVee_ifGeq/_clientMiddlewareManifest.json +1 -0
  56. package/dist/public/_next/static/36m05Da62vzqVee_ifGeq/_ssgManifest.js +1 -0
  57. package/dist/public/_next/static/chunks/02c545b35c5a7a0d.js +2 -0
  58. package/dist/public/_next/static/chunks/4611ba49fa18f0e2.js +1 -0
  59. package/dist/public/_next/static/chunks/64ee9622541d967c.js +1 -0
  60. package/dist/public/_next/static/chunks/66f59f4487e89157.js +1 -0
  61. package/dist/public/_next/static/chunks/a6dad97d9634a72d.js +1 -0
  62. package/dist/public/_next/static/chunks/a6dad97d9634a72d.js.map +1 -0
  63. package/dist/public/_next/static/chunks/bfa1988f6340e536.css +2 -0
  64. package/dist/public/_next/static/chunks/d1f8ac52f80f9493.js +5 -0
  65. package/dist/public/_next/static/chunks/turbopack-87039ecabc6befeb.js +4 -0
  66. package/dist/public/_not-found/__next._full.txt +13 -0
  67. package/dist/public/_not-found/__next._head.txt +5 -0
  68. package/dist/public/_not-found/__next._index.txt +5 -0
  69. package/dist/public/_not-found/__next._not-found.__PAGE__.txt +5 -0
  70. package/dist/public/_not-found/__next._not-found.txt +4 -0
  71. package/dist/public/_not-found/__next._tree.txt +2 -0
  72. package/dist/public/_not-found/index.html +1 -0
  73. package/dist/public/_not-found/index.txt +13 -0
  74. package/dist/public/index.html +1 -0
  75. package/dist/public/index.txt +17 -0
  76. package/dist/server/routes/live.d.ts +9 -0
  77. package/dist/server/routes/live.d.ts.map +1 -0
  78. package/dist/server/routes/live.js +53 -0
  79. package/dist/server/routes/live.js.map +1 -0
  80. package/dist/server/routes/observability.d.ts +6 -0
  81. package/dist/server/routes/observability.d.ts.map +1 -0
  82. package/dist/server/routes/observability.js +18 -0
  83. package/dist/server/routes/observability.js.map +1 -0
  84. package/dist/server/routes/plan.d.ts +7 -0
  85. package/dist/server/routes/plan.d.ts.map +1 -0
  86. package/dist/server/routes/plan.js +134 -0
  87. package/dist/server/routes/plan.js.map +1 -0
  88. package/dist/server/server.d.ts +7 -0
  89. package/dist/server/server.d.ts.map +1 -0
  90. package/dist/server/server.js +42 -0
  91. package/dist/server/server.js.map +1 -0
  92. package/dist/server/watcher.d.ts +20 -0
  93. package/dist/server/watcher.d.ts.map +1 -0
  94. package/dist/server/watcher.js +97 -0
  95. package/dist/server/watcher.js.map +1 -0
  96. package/package.json +58 -0
@@ -0,0 +1 @@
1
+ <!DOCTYPE html><!--36m05Da62vzqVee_ifGeq--><html lang="en" class="dark"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/bfa1988f6340e536.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/66f59f4487e89157.js"/><script src="/_next/static/chunks/4611ba49fa18f0e2.js" async=""></script><script src="/_next/static/chunks/d1f8ac52f80f9493.js" async=""></script><script src="/_next/static/chunks/turbopack-87039ecabc6befeb.js" async=""></script><script src="/_next/static/chunks/64ee9622541d967c.js" async=""></script><script src="/_next/static/chunks/02c545b35c5a7a0d.js" async=""></script><title>agent-scope</title><meta name="description" content="Execution observer for AI agent workflows"/><script src="/_next/static/chunks/a6dad97d9634a72d.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div class="h-screen bg-background flex items-center justify-center"><div class="text-muted-foreground">Loading...</div></div><!--$--><!--/$--><script src="/_next/static/chunks/66f59f4487e89157.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57043,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"default\"]\n3:I[27657,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"default\"]\n4:I[16339,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"ClientPageRoot\"]\n5:I[23733,[\"/_next/static/chunks/02c545b35c5a7a0d.js\"],\"default\"]\n8:I[56978,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"OutletBoundary\"]\n9:\"$Sreact.suspense\"\nb:I[56978,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"ViewportBoundary\"]\nd:I[56978,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"MetadataBoundary\"]\nf:I[30687,[\"/_next/static/chunks/64ee9622541d967c.js\"],\"default\"]\n:HL[\"/_next/static/chunks/bfa1988f6340e536.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"36m05Da62vzqVee_ifGeq\",\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/bfa1988f6340e536.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"className\":\"dark\",\"children\":[\"$\",\"body\",null,{\"children\":[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L4\",null,{\"Component\":\"$5\",\"serverProvidedParams\":{\"searchParams\":{},\"params\":{},\"promises\":[\"$@6\",\"$@7\"]}}],[[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/02c545b35c5a7a0d.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"$L8\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@a\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Lb\",null,{\"children\":\"$Lc\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Ld\",null,{\"children\":[\"$\",\"$9\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Le\"}]}]}],null]}],false]],\"m\":\"$undefined\",\"G\":[\"$f\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"6:{}\n7:\"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params\"\n"])</script><script>self.__next_f.push([1,"c:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"a:null\ne:[[\"$\",\"title\",\"0\",{\"children\":\"agent-scope\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"Execution observer for AI agent workflows\"}]]\n"])</script></body></html>
@@ -0,0 +1,17 @@
1
+ 1:"$Sreact.fragment"
2
+ 2:I[57043,["/_next/static/chunks/64ee9622541d967c.js"],"default"]
3
+ 3:I[27657,["/_next/static/chunks/64ee9622541d967c.js"],"default"]
4
+ 4:I[16339,["/_next/static/chunks/64ee9622541d967c.js"],"ClientPageRoot"]
5
+ 5:I[23733,["/_next/static/chunks/02c545b35c5a7a0d.js"],"default"]
6
+ 8:I[56978,["/_next/static/chunks/64ee9622541d967c.js"],"OutletBoundary"]
7
+ 9:"$Sreact.suspense"
8
+ b:I[56978,["/_next/static/chunks/64ee9622541d967c.js"],"ViewportBoundary"]
9
+ d:I[56978,["/_next/static/chunks/64ee9622541d967c.js"],"MetadataBoundary"]
10
+ f:I[30687,["/_next/static/chunks/64ee9622541d967c.js"],"default"]
11
+ :HL["/_next/static/chunks/bfa1988f6340e536.css","style"]
12
+ 0:{"P":null,"b":"36m05Da62vzqVee_ifGeq","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/chunks/bfa1988f6340e536.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"en","className":"dark","children":["$","body",null,{"children":["$","$L2",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L3",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L4",null,{"Component":"$5","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@6","$@7"]}}],[["$","script","script-0",{"src":"/_next/static/chunks/02c545b35c5a7a0d.js","async":true,"nonce":"$undefined"}]],["$","$L8",null,{"children":["$","$9",null,{"name":"Next.MetadataOutlet","children":"$@a"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Lb",null,{"children":"$Lc"}],["$","div",null,{"hidden":true,"children":["$","$Ld",null,{"children":["$","$9",null,{"name":"Next.Metadata","children":"$Le"}]}]}],null]}],false]],"m":"$undefined","G":["$f",[]],"S":true}
13
+ 6:{}
14
+ 7:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
15
+ c:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
16
+ a:null
17
+ e:[["$","title","0",{"children":"agent-scope"}],["$","meta","1",{"name":"description","content":"Execution observer for AI agent workflows"}]]
@@ -0,0 +1,9 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ import type { EventEmitter } from 'events';
3
+ export interface LiveRouteOptions {
4
+ claudeDir: string;
5
+ agentScopeDir?: string;
6
+ emitter: EventEmitter;
7
+ }
8
+ export declare function liveRoutes(fastify: FastifyInstance, opts: LiveRouteOptions): Promise<void>;
9
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../../src/server/routes/live.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAM/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,OAAO,EAAE,YAAY,CAAC;CACvB;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDhG"}
@@ -0,0 +1,53 @@
1
+ import { existsSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { readSessions } from '../../core/todoReader.js';
4
+ import { buildContextHealth } from '../../core/contextHealth.js';
5
+ export async function liveRoutes(fastify, opts) {
6
+ const { claudeDir, agentScopeDir, emitter } = opts;
7
+ const sseClients = new Set();
8
+ emitter.on('change', (event) => {
9
+ for (const send of sseClients)
10
+ send(event);
11
+ });
12
+ fastify.get('/health', async () => {
13
+ const hasLive = existsSync(join(claudeDir, 'tasks')) || existsSync(join(claudeDir, 'todos'));
14
+ const hasPlan = agentScopeDir ? existsSync(join(agentScopeDir, 'queue.md')) : false;
15
+ return { status: 'ok', modes: { live: hasLive, plan: hasPlan } };
16
+ });
17
+ fastify.get('/events', async (_request, reply) => {
18
+ reply.raw.writeHead(200, {
19
+ 'Content-Type': 'text/event-stream',
20
+ 'Cache-Control': 'no-cache',
21
+ 'Connection': 'keep-alive',
22
+ 'Access-Control-Allow-Origin': '*'
23
+ });
24
+ reply.raw.write(`data: ${JSON.stringify({ type: 'connected', timestamp: new Date().toISOString() })}\n\n`);
25
+ const send = (event) => {
26
+ reply.raw.write(`data: ${JSON.stringify(event)}\n\n`);
27
+ };
28
+ sseClients.add(send);
29
+ const pingInterval = setInterval(() => {
30
+ reply.raw.write(`: ping\n\n`);
31
+ }, 30000);
32
+ _request.raw.on('close', () => {
33
+ sseClients.delete(send);
34
+ clearInterval(pingInterval);
35
+ });
36
+ await new Promise(() => { });
37
+ });
38
+ fastify.get('/sessions', async () => {
39
+ const sessions = readSessions(claudeDir).map(s => ({
40
+ ...s,
41
+ contextHealth: buildContextHealth(s),
42
+ }));
43
+ return { sessions };
44
+ });
45
+ fastify.get('/sessions/:id', async (request) => {
46
+ const sessions = readSessions(claudeDir);
47
+ const found = sessions.find(s => s.id === request.params.id);
48
+ if (!found)
49
+ return { session: null, error: 'Session not found' };
50
+ return { session: { ...found, contextHealth: buildContextHealth(found) } };
51
+ });
52
+ }
53
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../../src/server/routes/live.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ export interface ObservabilityRouteOptions {
3
+ claudeDir: string;
4
+ }
5
+ export declare function observabilityRoutes(fastify: FastifyInstance, opts: ObservabilityRouteOptions): Promise<void>;
6
+ //# sourceMappingURL=observability.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.d.ts","sourceRoot":"","sources":["../../../src/server/routes/observability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK/C,MAAM,WAAW,yBAAyB;IACxC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,yBAAyB,GAAG,OAAO,CAAC,IAAI,CAAC,CAalH"}
@@ -0,0 +1,18 @@
1
+ import { readSessions } from '../../core/todoReader.js';
2
+ import { detectWorktrees, enrichWorktreeStatus } from '../../core/worktreeDetector.js';
3
+ import { mapTasksToWorktrees } from '../../core/worktreeMapper.js';
4
+ export async function observabilityRoutes(fastify, opts) {
5
+ const { claudeDir } = opts;
6
+ fastify.get('/worktrees', async () => {
7
+ try {
8
+ const raw = await detectWorktrees(process.cwd());
9
+ const enriched = await Promise.all(raw.map(w => enrichWorktreeStatus(w)));
10
+ const sessions = readSessions(claudeDir);
11
+ return { worktrees: mapTasksToWorktrees(sessions, enriched) };
12
+ }
13
+ catch {
14
+ return { worktrees: [] };
15
+ }
16
+ });
17
+ }
18
+ //# sourceMappingURL=observability.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"observability.js","sourceRoot":"","sources":["../../../src/server/routes/observability.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,gCAAgC,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAMnE,MAAM,CAAC,KAAK,UAAU,mBAAmB,CAAC,OAAwB,EAAE,IAA+B;IACjG,MAAM,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC;IAE3B,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,KAAK,IAAI,EAAE;QACnC,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,eAAe,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;YACjD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1E,MAAM,QAAQ,GAAG,YAAY,CAAC,SAAS,CAAC,CAAC;YACzC,OAAO,EAAE,SAAS,EAAE,mBAAmB,CAAC,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;QAChE,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC;QAC3B,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { FastifyInstance } from 'fastify';
2
+ export interface PlanRouteOptions {
3
+ claudeDir: string;
4
+ agentScopeDir?: string;
5
+ }
6
+ export declare function planRoutes(fastify: FastifyInstance, opts: PlanRouteOptions): Promise<void>;
7
+ //# sourceMappingURL=plan.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.d.ts","sourceRoot":"","sources":["../../../src/server/routes/plan.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAW/C,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAYD,wBAAsB,UAAU,CAAC,OAAO,EAAE,eAAe,EAAE,IAAI,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAyHhG"}
@@ -0,0 +1,134 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { join } from 'path';
3
+ import { parseQueue } from '../../core/queueParser.js';
4
+ import { parseLog } from '../../core/logParser.js';
5
+ import { computeSnapshot } from '../../core/stateEngine.js';
6
+ import { computePlanInsights, computeLiveInsights } from '../../core/insightsEngine.js';
7
+ import { readSessions } from '../../core/todoReader.js';
8
+ import { parseQualityTimeline } from '../../core/qualityTimeline.js';
9
+ function readQueueParseConfig(agentScopeDir) {
10
+ const configPath = join(agentScopeDir, 'config.json');
11
+ if (!existsSync(configPath))
12
+ return undefined;
13
+ try {
14
+ const configData = JSON.parse(readFileSync(configPath, 'utf-8'));
15
+ if (configData.taskModel)
16
+ return configData.taskModel;
17
+ }
18
+ catch { /* use defaults */ }
19
+ return undefined;
20
+ }
21
+ export async function planRoutes(fastify, opts) {
22
+ const { claudeDir, agentScopeDir } = opts;
23
+ fastify.get('/snapshot', async () => {
24
+ if (!agentScopeDir) {
25
+ return {
26
+ snapshot: null,
27
+ queueErrors: ['Plan mode not configured. Run "agent-scope init" first.'],
28
+ logErrors: [],
29
+ meta: { generatedAt: new Date().toISOString(), totalTasks: 0 }
30
+ };
31
+ }
32
+ const queuePath = join(agentScopeDir, 'queue.md');
33
+ const logPath = join(agentScopeDir, 'execution.log');
34
+ if (!existsSync(queuePath)) {
35
+ return {
36
+ snapshot: null,
37
+ queueErrors: ['queue.md not found'],
38
+ logErrors: [],
39
+ meta: { generatedAt: new Date().toISOString(), totalTasks: 0 }
40
+ };
41
+ }
42
+ const queueParseConfig = readQueueParseConfig(agentScopeDir);
43
+ const queueResult = parseQueue(readFileSync(queuePath, 'utf-8'), queueParseConfig);
44
+ if (queueResult.errors.length > 0) {
45
+ return {
46
+ snapshot: null,
47
+ queueErrors: queueResult.errors,
48
+ logErrors: [],
49
+ meta: { generatedAt: new Date().toISOString(), totalTasks: 0 }
50
+ };
51
+ }
52
+ let logResult = parseLog('');
53
+ if (existsSync(logPath)) {
54
+ logResult = parseLog(readFileSync(logPath, 'utf-8'));
55
+ }
56
+ let snapshot = null;
57
+ try {
58
+ snapshot = computeSnapshot(queueResult.tasks, logResult.events);
59
+ }
60
+ catch (error) {
61
+ return {
62
+ snapshot: null,
63
+ queueErrors: [`Failed to compute snapshot: ${error}`],
64
+ logErrors: logResult.errors,
65
+ meta: { generatedAt: new Date().toISOString(), totalTasks: queueResult.tasks.length }
66
+ };
67
+ }
68
+ return {
69
+ snapshot,
70
+ queueErrors: [],
71
+ logErrors: logResult.errors,
72
+ meta: { generatedAt: new Date().toISOString(), totalTasks: queueResult.tasks.length }
73
+ };
74
+ });
75
+ fastify.get('/insights', async () => {
76
+ const hasLive = existsSync(join(claudeDir, 'tasks')) || existsSync(join(claudeDir, 'todos'));
77
+ const hasPlan = agentScopeDir ? existsSync(join(agentScopeDir, 'queue.md')) : false;
78
+ const response = {
79
+ mode: hasLive && hasPlan ? 'both' : hasLive ? 'live' : 'plan',
80
+ generatedAt: new Date().toISOString(),
81
+ };
82
+ if (hasLive) {
83
+ response.live = computeLiveInsights(readSessions(claudeDir));
84
+ }
85
+ if (hasPlan && agentScopeDir) {
86
+ const queuePath = join(agentScopeDir, 'queue.md');
87
+ const logPath = join(agentScopeDir, 'execution.log');
88
+ if (existsSync(queuePath)) {
89
+ const queueParseConfig = readQueueParseConfig(agentScopeDir);
90
+ const queueResult = parseQueue(readFileSync(queuePath, 'utf-8'), queueParseConfig);
91
+ if (queueResult.errors.length === 0) {
92
+ let logResult = parseLog('');
93
+ if (existsSync(logPath))
94
+ logResult = parseLog(readFileSync(logPath, 'utf-8'));
95
+ try {
96
+ const snapshot = computeSnapshot(queueResult.tasks, logResult.events);
97
+ response.plan = computePlanInsights(snapshot.tasks, logResult.events);
98
+ }
99
+ catch { /* skip */ }
100
+ }
101
+ }
102
+ }
103
+ return response;
104
+ });
105
+ fastify.get('/quality-timeline', async (request) => {
106
+ if (!agentScopeDir)
107
+ return { events: [] };
108
+ const logPath = join(agentScopeDir, 'execution.log');
109
+ if (!existsSync(logPath))
110
+ return { events: [] };
111
+ try {
112
+ let events = parseQualityTimeline(readFileSync(logPath, 'utf-8'));
113
+ if (request.query.taskId) {
114
+ events = events.filter(e => e.taskId === request.query.taskId);
115
+ }
116
+ return { events };
117
+ }
118
+ catch {
119
+ return { events: [] };
120
+ }
121
+ });
122
+ fastify.get('/claude-insights', async (_request, reply) => {
123
+ const reportPath = join(claudeDir, 'usage-data', 'report.html');
124
+ if (!existsSync(reportPath)) {
125
+ return reply.code(404).send({
126
+ error: 'Claude insights report not found',
127
+ hint: 'Run /insight command in Claude Code to generate the report'
128
+ });
129
+ }
130
+ reply.type('text/html');
131
+ return reply.sendFile('usage-data/report.html', join(claudeDir));
132
+ });
133
+ }
134
+ //# sourceMappingURL=plan.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/server/routes/plan.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export interface ServerOptions {
2
+ agentScopeDir?: string;
3
+ claudeDir: string;
4
+ port: number;
5
+ }
6
+ export declare function startServer(options: ServerOptions): Promise<void>;
7
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAsB,WAAW,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCvE"}
@@ -0,0 +1,42 @@
1
+ import Fastify from 'fastify';
2
+ import cors from '@fastify/cors';
3
+ import staticPlugin from '@fastify/static';
4
+ import { existsSync } from 'fs';
5
+ import { join, dirname } from 'path';
6
+ import { fileURLToPath } from 'url';
7
+ import { createWatcher } from './watcher.js';
8
+ import { liveRoutes } from './routes/live.js';
9
+ import { planRoutes } from './routes/plan.js';
10
+ import { observabilityRoutes } from './routes/observability.js';
11
+ const __filename = fileURLToPath(import.meta.url);
12
+ const __dirname = dirname(__filename);
13
+ export async function startServer(options) {
14
+ const { claudeDir, port, agentScopeDir } = options;
15
+ const fastify = Fastify({ logger: false, ignoreTrailingSlash: true });
16
+ await fastify.register(cors, { origin: true });
17
+ const { watcher, emitter } = createWatcher({ claudeDir, agentScopeDir });
18
+ fastify.addHook('onClose', async () => { await watcher.close(); });
19
+ await fastify.register(liveRoutes, { claudeDir, agentScopeDir, emitter });
20
+ await fastify.register(planRoutes, { claudeDir, agentScopeDir });
21
+ await fastify.register(observabilityRoutes, { claudeDir });
22
+ // Serve static dashboard + SPA fallback
23
+ const publicPath = join(__dirname, '../public');
24
+ if (existsSync(publicPath)) {
25
+ await fastify.register(staticPlugin, { root: publicPath, prefix: '/' });
26
+ fastify.get('/', async (_request, reply) => reply.sendFile('index.html'));
27
+ fastify.setNotFoundHandler(async (_request, reply) => {
28
+ if (_request.url.startsWith('/api/') || _request.url.match(/\.\w+$/)) {
29
+ return reply.code(404).send({ error: 'Not found' });
30
+ }
31
+ return reply.sendFile('index.html');
32
+ });
33
+ }
34
+ try {
35
+ await fastify.listen({ port, host: '0.0.0.0' });
36
+ }
37
+ catch (err) {
38
+ fastify.log.error(err);
39
+ throw err;
40
+ }
41
+ }
42
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/server/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type FSWatcher } from 'chokidar';
2
+ import { EventEmitter } from 'events';
3
+ export interface WatcherOptions {
4
+ claudeDir: string;
5
+ agentScopeDir?: string;
6
+ }
7
+ export interface WatchEvent {
8
+ type: 'sessions' | 'plan';
9
+ timestamp: string;
10
+ }
11
+ /**
12
+ * Creates a file watcher that emits events when task files change.
13
+ * Watches ~/.claude/tasks/ and ~/.claude/todos/ for Live mode and .agent-scope/ for Plan mode.
14
+ * Monitors parent directory to detect late-created subdirectories.
15
+ */
16
+ export declare function createWatcher(options: WatcherOptions): {
17
+ watcher: FSWatcher;
18
+ emitter: EventEmitter;
19
+ };
20
+ //# sourceMappingURL=watcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.d.ts","sourceRoot":"","sources":["../../src/server/watcher.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,KAAK,SAAS,EAAE,MAAM,UAAU,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAC;AAItC,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,OAAO,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,CAmGpG"}
@@ -0,0 +1,97 @@
1
+ import { watch } from 'chokidar';
2
+ import { EventEmitter } from 'events';
3
+ import { existsSync } from 'fs';
4
+ import { join } from 'path';
5
+ /**
6
+ * Creates a file watcher that emits events when task files change.
7
+ * Watches ~/.claude/tasks/ and ~/.claude/todos/ for Live mode and .agent-scope/ for Plan mode.
8
+ * Monitors parent directory to detect late-created subdirectories.
9
+ */
10
+ export function createWatcher(options) {
11
+ const emitter = new EventEmitter();
12
+ const watchPaths = [];
13
+ const trackedSessionDirs = new Set();
14
+ const claudeTasksDir = join(options.claudeDir, 'tasks');
15
+ const claudeTodosDir = join(options.claudeDir, 'todos');
16
+ // Add existing session directories
17
+ for (const dir of [claudeTasksDir, claudeTodosDir]) {
18
+ if (existsSync(dir)) {
19
+ watchPaths.push(dir);
20
+ trackedSessionDirs.add(dir);
21
+ }
22
+ }
23
+ // Watch agent-scope files if configured
24
+ if (options.agentScopeDir && existsSync(options.agentScopeDir)) {
25
+ const queuePath = join(options.agentScopeDir, 'queue.md');
26
+ const logPath = join(options.agentScopeDir, 'execution.log');
27
+ if (existsSync(queuePath))
28
+ watchPaths.push(queuePath);
29
+ if (existsSync(logPath))
30
+ watchPaths.push(logPath);
31
+ }
32
+ // Always watch the parent claude dir to detect late-created tasks/ and todos/
33
+ if (existsSync(options.claudeDir)) {
34
+ watchPaths.push(options.claudeDir);
35
+ }
36
+ if (watchPaths.length === 0) {
37
+ const noopWatcher = watch([], { persistent: false });
38
+ return { watcher: noopWatcher, emitter };
39
+ }
40
+ let debounceTimer = null;
41
+ let pendingEventType = null;
42
+ const watcher = watch(watchPaths, {
43
+ persistent: true,
44
+ ignoreInitial: true,
45
+ depth: 2,
46
+ awaitWriteFinish: {
47
+ stabilityThreshold: 100,
48
+ pollInterval: 50
49
+ }
50
+ });
51
+ const emitDebounced = (eventType) => {
52
+ if (pendingEventType && pendingEventType !== eventType) {
53
+ pendingEventType = 'sessions';
54
+ }
55
+ else {
56
+ pendingEventType = eventType;
57
+ }
58
+ if (debounceTimer)
59
+ clearTimeout(debounceTimer);
60
+ debounceTimer = setTimeout(() => {
61
+ if (pendingEventType) {
62
+ const event = {
63
+ type: pendingEventType,
64
+ timestamp: new Date().toISOString()
65
+ };
66
+ emitter.emit('change', event);
67
+ pendingEventType = null;
68
+ }
69
+ }, 100);
70
+ };
71
+ const classifyEvent = (path) => {
72
+ return path.includes('.agent-scope') ? 'plan' : 'sessions';
73
+ };
74
+ // Detect late-created directories and start watching them
75
+ const maybeTrackNewDir = (path) => {
76
+ for (const dir of [claudeTasksDir, claudeTodosDir]) {
77
+ if (path === dir && !trackedSessionDirs.has(dir) && existsSync(dir)) {
78
+ watcher.add(dir);
79
+ trackedSessionDirs.add(dir);
80
+ }
81
+ }
82
+ };
83
+ watcher.on('addDir', (path) => {
84
+ maybeTrackNewDir(path);
85
+ });
86
+ watcher.on('change', (path) => {
87
+ emitDebounced(classifyEvent(path));
88
+ });
89
+ watcher.on('add', (path) => {
90
+ emitDebounced(classifyEvent(path));
91
+ });
92
+ watcher.on('unlink', (path) => {
93
+ emitDebounced(classifyEvent(path));
94
+ });
95
+ return { watcher, emitter };
96
+ }
97
+ //# sourceMappingURL=watcher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"watcher.js","sourceRoot":"","sources":["../../src/server/watcher.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "claudedash",
3
+ "version": "0.5.4",
4
+ "description": "Live Kanban, quality gates and context health monitoring for Claude Code agents",
5
+ "type": "module",
6
+ "bin": {
7
+ "claudedash": "dist/cli.js"
8
+ },
9
+ "files": [
10
+ "dist/",
11
+ "README.md",
12
+ "LICENSE"
13
+ ],
14
+ "scripts": {
15
+ "dev": "tsx watch src/cli.ts start",
16
+ "build": "tsc && cd dashboard && npm run build",
17
+ "build:core": "tsc",
18
+ "build:dashboard": "cd dashboard && npm run build",
19
+ "test": "vitest --run",
20
+ "test:coverage": "vitest --coverage",
21
+ "version": "node scripts/sync-version.mjs && git add dashboard/package.json src/cli.ts"
22
+ },
23
+ "keywords": [
24
+ "claude",
25
+ "claude-code",
26
+ "ai-agent",
27
+ "monitoring",
28
+ "observability",
29
+ "kanban",
30
+ "task-tracking",
31
+ "dashboard",
32
+ "devtools"
33
+ ],
34
+ "author": "Yunus Emre Gurlu <yunusemregurlu@gmail.com>",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/yunusemrgrl/claudedash.git"
38
+ },
39
+ "bugs": {
40
+ "url": "https://github.com/yunusemrgrl/claudedash/issues"
41
+ },
42
+ "homepage": "https://github.com/yunusemrgrl/claudedash#readme",
43
+ "license": "MIT",
44
+ "dependencies": {
45
+ "@fastify/cors": "^9.0.1",
46
+ "@fastify/static": "^7.0.4",
47
+ "chokidar": "^5.0.0",
48
+ "commander": "^12.0.0",
49
+ "fastify": "^4.26.0"
50
+ },
51
+ "devDependencies": {
52
+ "@types/node": "^20.11.16",
53
+ "@vitest/coverage-v8": "^1.2.2",
54
+ "tsx": "^4.7.0",
55
+ "typescript": "^5.3.3",
56
+ "vitest": "^1.2.2"
57
+ }
58
+ }