@claude-view/plugin 0.8.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.
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "claude-view",
3
+ "description": "Mission Control for Claude Code — auto-starts a web dashboard, provides session/cost/fluency tools, and adds /session-recap, /daily-cost, /standup skills.",
4
+ "version": "0.8.0",
5
+ "author": {
6
+ "name": "tombelieber",
7
+ "email": "nicholasgee1997@gmail.com"
8
+ },
9
+ "homepage": "https://github.com/tombelieber/claude-view",
10
+ "repository": "https://github.com/tombelieber/claude-view",
11
+ "license": "MIT",
12
+ "keywords": [
13
+ "claude-code",
14
+ "mission-control",
15
+ "session-analytics",
16
+ "cost-tracking",
17
+ "fluency-score",
18
+ "dashboard"
19
+ ]
20
+ }
package/.mcp.json ADDED
@@ -0,0 +1,10 @@
1
+ {
2
+ "mcpServers": {
3
+ "claude-view": {
4
+ "type": "stdio",
5
+ "command": "node",
6
+ "args": ["${CLAUDE_PLUGIN_ROOT}/dist/index.js"],
7
+ "env": {}
8
+ }
9
+ }
10
+ }
package/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # claude-view plugin
2
+
3
+ Mission Control for Claude Code. Auto-starts a web dashboard, provides 8 session/cost/fluency
4
+ tools, and adds `/session-recap`, `/daily-cost`, `/standup` skills.
5
+
6
+ ## Install
7
+
8
+ ```bash
9
+ claude plugin add @claude-view/plugin
10
+ ```
11
+
12
+ ## Prerequisites
13
+
14
+ - **Node.js >= 18** (required by MCP SDK)
15
+ - The plugin auto-starts the claude-view server, but the binary must be available:
16
+
17
+ ```bash
18
+ npx claude-view # downloads the pre-built Rust binary on first run (~5-15s first time)
19
+ ```
20
+
21
+ > **First run note:** The very first session after install may take 5-30 seconds to download the
22
+ > Rust binary. The hook will time out gracefully — the server will start in the background and be
23
+ > ready for your next tool call or next session.
24
+
25
+ ## What You Get
26
+
27
+ ### Auto-start (SessionStart hook)
28
+ Every time you start a Claude Code session, the plugin checks if the claude-view server
29
+ is running. If not, it starts it in the background. Web dashboard appears at
30
+ `http://localhost:47892`.
31
+
32
+ ### 8 MCP Tools (available to Claude)
33
+ | Tool | Purpose |
34
+ |------|---------|
35
+ | `list_sessions` | List/filter/paginate sessions |
36
+ | `get_session` | Full session detail + commits |
37
+ | `search_sessions` | Full-text search across sessions |
38
+ | `get_stats` | Dashboard overview: projects, skills, trends |
39
+ | `get_fluency_score` | AI Fluency Score (0-100) |
40
+ | `get_token_stats` | Token usage breakdown |
41
+ | `list_live_sessions` | Currently running sessions |
42
+ | `get_live_summary` | Aggregate: cost today, attention count |
43
+
44
+ ### 3 Skills
45
+ | Skill | Trigger |
46
+ |-------|---------|
47
+ | `/session-recap` | "recap my last session", "summarize session" |
48
+ | `/daily-cost` | "how much did I spend today", "cost report" |
49
+ | `/standup` | "standup update", "what did I work on" |
50
+
51
+ ## Configuration
52
+
53
+ Set `CLAUDE_VIEW_PORT` to override the default port (47892).
54
+
55
+ ## License
56
+
57
+ MIT
@@ -0,0 +1,6 @@
1
+ export declare class ClaudeViewClient {
2
+ readonly baseUrl: string;
3
+ constructor(port?: number);
4
+ get<T = unknown>(path: string, params?: Record<string, string | number | undefined>): Promise<T>;
5
+ }
6
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,qBAAa,gBAAgB;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;gBAEZ,IAAI,CAAC,EAAE,MAAM;IAKnB,GAAG,CAAC,CAAC,GAAG,OAAO,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,GACnD,OAAO,CAAC,CAAC,CAAC;CA6Bd"}
package/dist/client.js ADDED
@@ -0,0 +1,33 @@
1
+ export class ClaudeViewClient {
2
+ baseUrl;
3
+ constructor(port) {
4
+ const resolvedPort = port ?? (Number(process.env.CLAUDE_VIEW_PORT) || 47892);
5
+ this.baseUrl = `http://localhost:${resolvedPort}`;
6
+ }
7
+ async get(path, params) {
8
+ const url = new URL(path, this.baseUrl);
9
+ if (params) {
10
+ for (const [key, value] of Object.entries(params)) {
11
+ if (value !== undefined) {
12
+ url.searchParams.set(key, String(value));
13
+ }
14
+ }
15
+ }
16
+ let response;
17
+ try {
18
+ response = await fetch(url.toString(), {
19
+ headers: { Accept: 'application/json' },
20
+ signal: AbortSignal.timeout(10_000),
21
+ });
22
+ }
23
+ catch {
24
+ throw new Error(`claude-view server not detected at ${this.baseUrl}. Start it with: npx claude-view`);
25
+ }
26
+ if (!response.ok) {
27
+ const body = await response.text().catch(() => '');
28
+ throw new Error(`claude-view API error ${response.status}: ${body}`);
29
+ }
30
+ return response.json();
31
+ }
32
+ }
33
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,gBAAgB;IAClB,OAAO,CAAQ;IAExB,YAAY,IAAa;QACvB,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,CAAA;QAC5E,IAAI,CAAC,OAAO,GAAG,oBAAoB,YAAY,EAAE,CAAA;IACnD,CAAC;IAED,KAAK,CAAC,GAAG,CACP,IAAY,EACZ,MAAoD;QAEpD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,CAAA;QACvC,IAAI,MAAM,EAAE,CAAC;YACX,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;gBAClD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;oBACxB,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAA;gBAC1C,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,QAAkB,CAAA;QACtB,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE;gBACrC,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;gBACvC,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC;aACpC,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,IAAI,KAAK,CACb,sCAAsC,IAAI,CAAC,OAAO,kCAAkC,CACrF,CAAA;QACH,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAA;YAClD,MAAM,IAAI,KAAK,CAAC,yBAAyB,QAAQ,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAA;QACtE,CAAC;QAED,OAAO,QAAQ,CAAC,IAAI,EAAgB,CAAA;IACtC,CAAC;CACF"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -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,9 @@
1
+ #!/usr/bin/env node
2
+ import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
3
+ import { TOOL_COUNT, createServer } from './server.js';
4
+ const port = process.env.CLAUDE_VIEW_PORT ? Number(process.env.CLAUDE_VIEW_PORT) : undefined;
5
+ const server = createServer(port);
6
+ const transport = new StdioServerTransport();
7
+ console.error(`claude-view MCP server starting (${TOOL_COUNT} tools, port ${port ?? 47892})`);
8
+ await server.connect(transport);
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAA;AAChF,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAEtD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5F,MAAM,MAAM,GAAG,YAAY,CAAC,IAAI,CAAC,CAAA;AACjC,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAA;AAE5C,OAAO,CAAC,KAAK,CAAC,oCAAoC,UAAU,gBAAgB,IAAI,IAAI,KAAK,GAAG,CAAC,CAAA;AAE7F,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA"}
@@ -0,0 +1,4 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ export declare const TOOL_COUNT: number;
3
+ export declare function createServer(port?: number): McpServer;
4
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AAOnE,eAAO,MAAM,UAAU,QAAmB,CAAA;AAE1C,wBAAgB,YAAY,CAAC,IAAI,CAAC,EAAE,MAAM,aA+BzC"}
package/dist/server.js ADDED
@@ -0,0 +1,34 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import { ClaudeViewClient } from './client.js';
3
+ import { liveTools } from './tools/live.js';
4
+ import { sessionTools } from './tools/sessions.js';
5
+ import { statsTools } from './tools/stats.js';
6
+ const ALL_TOOLS = [...sessionTools, ...statsTools, ...liveTools];
7
+ export const TOOL_COUNT = ALL_TOOLS.length;
8
+ export function createServer(port) {
9
+ const client = new ClaudeViewClient(port);
10
+ const server = new McpServer({
11
+ name: 'claude-view',
12
+ version: '0.8.0',
13
+ });
14
+ for (const tool of ALL_TOOLS) {
15
+ server.registerTool(tool.name, {
16
+ description: tool.description,
17
+ inputSchema: tool.inputSchema,
18
+ annotations: tool.annotations,
19
+ }, async (args) => {
20
+ try {
21
+ const result = await tool.handler(client, args);
22
+ return { content: [{ type: 'text', text: result }] };
23
+ }
24
+ catch (err) {
25
+ return {
26
+ content: [{ type: 'text', text: `Error: ${err.message}` }],
27
+ isError: true,
28
+ };
29
+ }
30
+ });
31
+ }
32
+ return server;
33
+ }
34
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAA;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAE7C,MAAM,SAAS,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,UAAU,EAAE,GAAG,SAAS,CAAC,CAAA;AAChE,MAAM,CAAC,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,CAAA;AAE1C,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,MAAM,MAAM,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,CAAA;IAEzC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC;QAC3B,IAAI,EAAE,aAAa;QACnB,OAAO,EAAE,OAAO;KACjB,CAAC,CAAA;IAEF,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;QAC7B,MAAM,CAAC,YAAY,CACjB,IAAI,CAAC,IAAI,EACT;YACE,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;YAC7B,WAAW,EAAE,IAAI,CAAC,WAAW;SAC9B,EACD,KAAK,EAAE,IAAS,EAAE,EAAE;YAClB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;gBAC/C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,EAAE,CAAA;YAC/D,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,OAAO;oBACL,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,UAAU,GAAG,CAAC,OAAO,EAAE,EAAE,CAAC;oBACnE,OAAO,EAAE,IAAI;iBACd,CAAA;YACH,CAAC;QACH,CAAC,CACF,CAAA;IACH,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import type { ClaudeViewClient } from '../client.js';
3
+ interface ToolDef<TSchema extends z.ZodObject<any> = z.ZodObject<any>> {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: TSchema;
7
+ annotations: Record<string, boolean>;
8
+ handler: (client: ClaudeViewClient, args: z.output<TSchema>) => Promise<string>;
9
+ }
10
+ export declare const liveTools: ToolDef[];
11
+ export {};
12
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../../src/tools/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,UAAU,OAAO,CAAC,OAAO,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAChF;AAED,eAAO,MAAM,SAAS,EAAE,OAAO,EAkD9B,CAAA"}
@@ -0,0 +1,43 @@
1
+ import { z } from 'zod';
2
+ export const liveTools = [
3
+ {
4
+ name: 'list_live_sessions',
5
+ description: 'List currently running Claude Code sessions with real-time agent state, model, token usage, cost, and activity.',
6
+ inputSchema: z.object({}),
7
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
8
+ handler: async (client) => {
9
+ const data = await client.get('/api/live/sessions');
10
+ const sessions = (data.sessions ?? []).map((s) => ({
11
+ id: s.id,
12
+ project: s.projectDisplayName,
13
+ agent_state: s.agentState?.label ?? s.agentState?.group,
14
+ model: s.model,
15
+ turn_count: s.turnCount,
16
+ cost_usd: s.cost?.totalUsd,
17
+ total_tokens: s.tokens?.totalTokens,
18
+ started: s.startedAt ? new Date(s.startedAt * 1000).toISOString() : null,
19
+ last_activity: s.lastActivityAt ? new Date(s.lastActivityAt * 1000).toISOString() : null,
20
+ sub_agents: (s.subAgents ?? []).length || undefined,
21
+ }));
22
+ return JSON.stringify({ sessions, total: data.total, process_count: data.processCount }, null, 2);
23
+ },
24
+ },
25
+ {
26
+ name: 'get_live_summary',
27
+ description: 'Get aggregate summary of all live Claude Code sessions: how many need attention, how many are autonomous, total cost today, total tokens today.',
28
+ inputSchema: z.object({}),
29
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
30
+ handler: async (client) => {
31
+ const data = await client.get('/api/live/summary');
32
+ return JSON.stringify({
33
+ needs_attention: data.needsYouCount,
34
+ autonomous: data.autonomousCount,
35
+ delivered: data.deliveredCount,
36
+ total_cost_today_usd: data.totalCostTodayUsd,
37
+ total_tokens_today: data.totalTokensToday,
38
+ process_count: data.processCount,
39
+ }, null, 2);
40
+ },
41
+ },
42
+ ];
43
+ //# sourceMappingURL=live.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.js","sourceRoot":"","sources":["../../src/tools/live.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAWvB,MAAM,CAAC,MAAM,SAAS,GAAc;IAClC;QACE,IAAI,EAAE,oBAAoB;QAC1B,WAAW,EACT,iHAAiH;QACnH,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE;QACjF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACxB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAM,oBAAoB,CAAC,CAAA;YACxD,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAM,EAAE,EAAE,CAAC,CAAC;gBACtD,EAAE,EAAE,CAAC,CAAC,EAAE;gBACR,OAAO,EAAE,CAAC,CAAC,kBAAkB;gBAC7B,WAAW,EAAE,CAAC,CAAC,UAAU,EAAE,KAAK,IAAI,CAAC,CAAC,UAAU,EAAE,KAAK;gBACvD,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,UAAU,EAAE,CAAC,CAAC,SAAS;gBACvB,QAAQ,EAAE,CAAC,CAAC,IAAI,EAAE,QAAQ;gBAC1B,YAAY,EAAE,CAAC,CAAC,MAAM,EAAE,WAAW;gBACnC,OAAO,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;gBACxE,aAAa,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI;gBACxF,UAAU,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,MAAM,IAAI,SAAS;aACpD,CAAC,CAAC,CAAA;YACH,OAAO,IAAI,CAAC,SAAS,CACnB,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,IAAI,CAAC,YAAY,EAAE,EACjE,IAAI,EACJ,CAAC,CACF,CAAA;QACH,CAAC;KACF;IACD;QACE,IAAI,EAAE,kBAAkB;QACxB,WAAW,EACT,iJAAiJ;QACnJ,WAAW,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACzB,WAAW,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE;QACjF,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;YACxB,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,GAAG,CAAM,mBAAmB,CAAC,CAAA;YACvD,OAAO,IAAI,CAAC,SAAS,CACnB;gBACE,eAAe,EAAE,IAAI,CAAC,aAAa;gBACnC,UAAU,EAAE,IAAI,CAAC,eAAe;gBAChC,SAAS,EAAE,IAAI,CAAC,cAAc;gBAC9B,oBAAoB,EAAE,IAAI,CAAC,iBAAiB;gBAC5C,kBAAkB,EAAE,IAAI,CAAC,gBAAgB;gBACzC,aAAa,EAAE,IAAI,CAAC,YAAY;aACjC,EACD,IAAI,EACJ,CAAC,CACF,CAAA;QACH,CAAC;KACF;CACF,CAAA"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import type { ClaudeViewClient } from '../client.js';
3
+ interface ToolDef<TSchema extends z.ZodObject<any> = z.ZodObject<any>> {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: TSchema;
7
+ annotations: Record<string, boolean>;
8
+ handler: (client: ClaudeViewClient, args: z.output<TSchema>) => Promise<string>;
9
+ }
10
+ export declare const sessionTools: ToolDef[];
11
+ export {};
12
+ //# sourceMappingURL=sessions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../../src/tools/sessions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,UAAU,OAAO,CAAC,OAAO,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAChF;AAyBD,eAAO,MAAM,YAAY,EAAE,OAAO,EA0GjC,CAAA"}
@@ -0,0 +1,118 @@
1
+ import { z } from 'zod';
2
+ const listSessionsSchema = z.object({
3
+ limit: z.number().optional().describe('Max sessions to return (default 30)'),
4
+ q: z.string().optional().describe('Text search query'),
5
+ filter: z.string().optional().describe('Filter: all, has_commits, high_reedit, long_session'),
6
+ sort: z.string().optional().describe('Sort: recent, tokens, prompts, files_edited, duration'),
7
+ offset: z.number().optional().describe('Pagination offset'),
8
+ branches: z.string().optional().describe('Comma-separated branch names'),
9
+ models: z.string().optional().describe('Comma-separated model names'),
10
+ time_after: z.number().optional().describe('Unix timestamp lower bound'),
11
+ time_before: z.number().optional().describe('Unix timestamp upper bound'),
12
+ });
13
+ const getSessionSchema = z.object({
14
+ session_id: z.string().describe('The session ID to look up'),
15
+ });
16
+ const searchSessionsSchema = z.object({
17
+ query: z.string().describe('Search query'),
18
+ limit: z.number().optional().describe('Max results (default 10)'),
19
+ offset: z.number().optional().describe('Pagination offset'),
20
+ scope: z.string().optional().describe('Search scope: all, user, assistant'),
21
+ });
22
+ export const sessionTools = [
23
+ {
24
+ name: 'list_sessions',
25
+ description: 'List Claude Code sessions with optional filters. Returns session summaries including project, model, duration, and token usage.',
26
+ inputSchema: listSessionsSchema,
27
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
28
+ handler: async (client, args) => {
29
+ const data = await client.get('/api/sessions', {
30
+ limit: args.limit,
31
+ q: args.q,
32
+ filter: args.filter,
33
+ sort: args.sort,
34
+ offset: args.offset,
35
+ branches: args.branches,
36
+ models: args.models,
37
+ time_after: args.time_after,
38
+ time_before: args.time_before,
39
+ });
40
+ const sessions = (data.sessions ?? []).map((s) => ({
41
+ id: s.id,
42
+ project: s.displayName || s.project,
43
+ branch: s.gitBranch,
44
+ model: s.primaryModel,
45
+ turns: s.turnCount,
46
+ messages: s.messageCount,
47
+ commits: s.commitCount,
48
+ duration_min: Math.round((s.durationSeconds ?? 0) / 60),
49
+ input_tokens: s.totalInputTokens,
50
+ output_tokens: s.totalOutputTokens,
51
+ modified: s.modifiedAt ? new Date(s.modifiedAt * 1000).toISOString() : null,
52
+ }));
53
+ return JSON.stringify({ sessions, total: data.total, has_more: data.hasMore }, null, 2);
54
+ },
55
+ },
56
+ {
57
+ name: 'get_session',
58
+ description: 'Get detailed information about a specific Claude Code session, including commits, token breakdown, and derived metrics.',
59
+ inputSchema: getSessionSchema,
60
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
61
+ handler: async (client, args) => {
62
+ const data = await client.get(`/api/sessions/${args.session_id}`);
63
+ return JSON.stringify({
64
+ id: data.id,
65
+ project: data.displayName || data.project,
66
+ branch: data.gitBranch,
67
+ model: data.primaryModel,
68
+ summary: data.preview,
69
+ turns: data.turnCount,
70
+ messages: data.userPromptCount,
71
+ commits: data.commits?.length ?? data.commitCount,
72
+ duration_min: Math.round((data.durationSeconds ?? 0) / 60),
73
+ input_tokens: data.totalInputTokens,
74
+ output_tokens: data.totalOutputTokens,
75
+ cache_read_tokens: data.totalCacheReadTokens,
76
+ derived_metrics: data.derivedMetrics,
77
+ recent_commits: (data.commits ?? []).slice(0, 10).map((c) => ({
78
+ hash: c.hash?.slice(0, 8),
79
+ message: c.message,
80
+ branch: c.branch,
81
+ })),
82
+ }, null, 2);
83
+ },
84
+ },
85
+ {
86
+ name: 'search_sessions',
87
+ description: 'Search across all Claude Code sessions using unified enhanced search. Returns matching sessions with highlighted snippets.',
88
+ inputSchema: searchSessionsSchema,
89
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
90
+ handler: async (client, args) => {
91
+ const data = await client.get('/api/search', {
92
+ q: args.query,
93
+ limit: args.limit,
94
+ offset: args.offset,
95
+ scope: args.scope,
96
+ });
97
+ return JSON.stringify({
98
+ query: data.query,
99
+ total_sessions: data.totalSessions,
100
+ total_matches: data.totalMatches,
101
+ elapsed_ms: data.elapsedMs,
102
+ results: (data.sessions ?? []).map((s) => ({
103
+ session_id: s.sessionId,
104
+ project: s.project,
105
+ branch: s.branch,
106
+ match_count: s.matchCount,
107
+ best_score: s.bestScore,
108
+ top_matches: (s.matches ?? []).slice(0, 3).map((m) => ({
109
+ role: m.role,
110
+ snippet: m.snippet?.replace(/<\/?mark>/g, '**'),
111
+ turn: m.turnNumber,
112
+ })),
113
+ })),
114
+ }, null, 2);
115
+ },
116
+ },
117
+ ];
118
+ //# sourceMappingURL=sessions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sessions.js","sourceRoot":"","sources":["../../src/tools/sessions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { z } from 'zod';
2
+ import type { ClaudeViewClient } from '../client.js';
3
+ interface ToolDef<TSchema extends z.ZodObject<any> = z.ZodObject<any>> {
4
+ name: string;
5
+ description: string;
6
+ inputSchema: TSchema;
7
+ annotations: Record<string, boolean>;
8
+ handler: (client: ClaudeViewClient, args: z.output<TSchema>) => Promise<string>;
9
+ }
10
+ export declare const statsTools: ToolDef[];
11
+ export {};
12
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/tools/stats.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAA;AAEpD,UAAU,OAAO,CAAC,OAAO,SAAS,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC;IACnE,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,OAAO,CAAA;IACpB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACpC,OAAO,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;CAChF;AAgDD,eAAO,MAAM,UAAU,EAAE,OAAO,EAqE/B,CAAA"}
@@ -0,0 +1,97 @@
1
+ import { z } from 'zod';
2
+ const getStatsSchema = z.object({
3
+ project: z.string().optional().describe('Filter by project name'),
4
+ branch: z.string().optional().describe('Filter by git branch'),
5
+ from: z
6
+ .union([z.number(), z.string()])
7
+ .optional()
8
+ .describe('Start time (Unix seconds, or ISO 8601 / YYYY-MM-DD date string)'),
9
+ to: z
10
+ .union([z.number(), z.string()])
11
+ .optional()
12
+ .describe('End time (Unix seconds, or ISO 8601 / YYYY-MM-DD date string)'),
13
+ });
14
+ function parseUnixSeconds(value, field) {
15
+ if (value === undefined) {
16
+ return undefined;
17
+ }
18
+ if (typeof value === 'number') {
19
+ if (!Number.isFinite(value)) {
20
+ throw new Error(`Invalid ${field} value: must be a finite number`);
21
+ }
22
+ return Math.trunc(value);
23
+ }
24
+ const trimmed = value.trim();
25
+ if (trimmed === '') {
26
+ return undefined;
27
+ }
28
+ const numeric = Number(trimmed);
29
+ if (Number.isFinite(numeric) && /^\d+$/.test(trimmed)) {
30
+ return Math.trunc(numeric);
31
+ }
32
+ const parsedMs = Date.parse(trimmed);
33
+ if (!Number.isNaN(parsedMs)) {
34
+ return Math.trunc(parsedMs / 1000);
35
+ }
36
+ throw new Error(`Invalid ${field} value: expected Unix seconds or parseable date string`);
37
+ }
38
+ export const statsTools = [
39
+ {
40
+ name: 'get_stats',
41
+ description: 'Get dashboard overview statistics: total sessions, projects, top skills, tool usage totals, current week metrics, and week-over-week trends. Optionally filter by project, branch, or date range.',
42
+ inputSchema: getStatsSchema,
43
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
44
+ handler: async (client, args) => {
45
+ const from = parseUnixSeconds(args.from, 'from');
46
+ const to = parseUnixSeconds(args.to, 'to');
47
+ const data = await client.get('/api/stats/dashboard', {
48
+ project: args.project,
49
+ branch: args.branch,
50
+ from,
51
+ to,
52
+ });
53
+ return JSON.stringify({
54
+ total_sessions: data.totalSessions,
55
+ total_projects: data.totalProjects,
56
+ top_projects: (data.topProjects ?? []).slice(0, 5).map((p) => ({
57
+ name: p.displayName || p.name,
58
+ sessions: p.sessionCount,
59
+ })),
60
+ top_skills: (data.topSkills ?? []).slice(0, 5),
61
+ tool_totals: data.toolTotals,
62
+ current_week: data.currentWeek,
63
+ trends: data.trends,
64
+ ranges: data.meta?.ranges,
65
+ }, null, 2);
66
+ },
67
+ },
68
+ {
69
+ name: 'get_fluency_score',
70
+ description: 'Get the AI Fluency Score (0-100 composite) measuring coding effectiveness with Claude. Includes achievement rate, friction rate, cost efficiency, satisfaction trend, consistency.',
71
+ inputSchema: z.object({}),
72
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
73
+ handler: async (client) => {
74
+ const data = await client.get('/api/score');
75
+ return JSON.stringify({
76
+ score: data.score,
77
+ achievementRate: data.achievementRate,
78
+ frictionRate: data.frictionRate,
79
+ costEfficiency: data.costEfficiency,
80
+ satisfactionTrend: data.satisfactionTrend,
81
+ consistency: data.consistency,
82
+ sessionsAnalyzed: data.sessionsAnalyzed,
83
+ }, null, 2);
84
+ },
85
+ },
86
+ {
87
+ name: 'get_token_stats',
88
+ description: "Get token usage statistics: total input/output/cache tokens, cache hit ratio, session and turn counts. Note: no USD cost fields — use live summary for today's cost.",
89
+ inputSchema: z.object({}),
90
+ annotations: { readOnlyHint: true, destructiveHint: false, openWorldHint: false },
91
+ handler: async (client) => {
92
+ const data = await client.get('/api/stats/tokens');
93
+ return JSON.stringify(data, null, 2);
94
+ },
95
+ },
96
+ ];
97
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/tools/stats.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ {
2
+ "hooks": {
3
+ "SessionStart": [
4
+ {
5
+ "matcher": "startup|resume|clear|compact",
6
+ "hooks": [
7
+ {
8
+ "type": "command",
9
+ "command": "${CLAUDE_PLUGIN_ROOT}/hooks/start-server.sh",
10
+ "async": false
11
+ }
12
+ ]
13
+ }
14
+ ]
15
+ }
16
+ }
@@ -0,0 +1,57 @@
1
+ #!/usr/bin/env bash
2
+ # claude-view SessionStart hook — ensure server is running
3
+ # Non-blocking: ALWAYS exits 0, even if server fails to start.
4
+ # Uses set -uo pipefail (no -e) so the script never aborts early.
5
+
6
+ set -uo pipefail
7
+
8
+ PORT="${CLAUDE_VIEW_PORT:-47892}"
9
+ HEALTH_URL="http://localhost:${PORT}/api/health"
10
+
11
+ # Check if already running (curl inside if-guard: safe with any set flags)
12
+ if curl -sf --max-time 2 "${HEALTH_URL}" >/dev/null 2>&1; then
13
+ exit 0
14
+ fi
15
+
16
+ # Locate npx — version managers (nvm, volta, fnm, asdf) put it outside system PATH.
17
+ # Claude Code hooks run with limited env, so we search common locations.
18
+ find_npx() {
19
+ # 1. Already in PATH?
20
+ command -v npx 2>/dev/null && return
21
+ # 2. Common version manager locations
22
+ for candidate in \
23
+ "${HOME}/.volta/bin/npx" \
24
+ "${HOME}/.local/share/fnm/aliases/default/bin/npx" \
25
+ "/usr/local/bin/npx" \
26
+ "/opt/homebrew/bin/npx"; do
27
+ [ -x "$candidate" ] && echo "$candidate" && return
28
+ done
29
+ # 3. nvm — glob for the default version
30
+ for candidate in "${HOME}"/.nvm/versions/node/*/bin/npx; do
31
+ [ -x "$candidate" ] && echo "$candidate" && return
32
+ done
33
+ }
34
+
35
+ NPX="$(find_npx)"
36
+ if [ -z "$NPX" ]; then
37
+ # npx not found — cannot auto-start server. Tools will show a clear error.
38
+ exit 0
39
+ fi
40
+
41
+ # Not running — start in background.
42
+ # CLAUDE_VIEW_NO_OPEN=1 suppresses browser tab open from the hook context.
43
+ # || true ensures nohup failure (e.g. binary download timeout) never propagates.
44
+ CLAUDE_VIEW_NO_OPEN=1 nohup "$NPX" claude-view >/dev/null 2>&1 &
45
+
46
+ # Wait up to 3 seconds for server to become healthy.
47
+ # On first-ever run, binary download takes 5-30s — this will time out. That's fine:
48
+ # the server starts in the background and will be ready for the next tool call or session.
49
+ for _ in 1 2 3; do
50
+ sleep 1
51
+ if curl -sf --max-time 1 "${HEALTH_URL}" >/dev/null 2>&1; then
52
+ exit 0
53
+ fi
54
+ done
55
+
56
+ # Server didn't start in time — don't block the session.
57
+ exit 0
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@claude-view/plugin",
3
+ "version": "0.8.0",
4
+ "description": "Claude Code plugin for claude-view — auto-starts web dashboard, provides session/cost/fluency tools and skills",
5
+ "private": false,
6
+ "type": "module",
7
+ "files": [".claude-plugin/", ".mcp.json", "skills/", "hooks/", "dist/", "README.md"],
8
+ "scripts": {
9
+ "build": "node scripts/bundle-mcp.mjs",
10
+ "prepublishOnly": "node scripts/bundle-mcp.mjs",
11
+ "typecheck": "echo 'no TS in plugin'",
12
+ "lint": "echo 'markdown + json only'",
13
+ "test": "node scripts/bundle-mcp.mjs && bash scripts/validate-plugin.sh"
14
+ },
15
+ "dependencies": {
16
+ "@modelcontextprotocol/sdk": "^1.27.1",
17
+ "zod": "^3.24"
18
+ },
19
+ "engines": {
20
+ "node": ">=18"
21
+ },
22
+ "keywords": [
23
+ "claude-code",
24
+ "claude-code-plugin",
25
+ "claude-view",
26
+ "mission-control",
27
+ "session-analytics",
28
+ "cost-tracking"
29
+ ],
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "https://github.com/tombelieber/claude-view",
33
+ "directory": "packages/plugin"
34
+ },
35
+ "license": "MIT"
36
+ }
@@ -0,0 +1,37 @@
1
+ ---
2
+ name: daily-cost
3
+ description: "Use when the user asks about cost, spending, or budget — e.g. 'how much did I spend today', 'daily cost', 'cost report', 'what's my spend'"
4
+ ---
5
+
6
+ # Daily Cost Report
7
+
8
+ Show the user's Claude Code spending for today using the claude-view MCP tools.
9
+
10
+ ## Steps
11
+
12
+ 1. **Get live summary.** Call `mcp__claude-view__get_live_summary` to get today's aggregate cost and active session counts.
13
+
14
+ 2. **Get per-session details.** If there are running sessions (needs_attention > 0 or autonomous > 0), call `mcp__claude-view__list_live_sessions` to get per-session project, model, cost, and agent state.
15
+
16
+ 3. **Get dashboard stats.** Call `mcp__claude-view__get_stats` with `from` set to today's date (e.g. `2026-03-01`) to get today's session breakdown.
17
+
18
+ 4. **Present the cost report** in this format:
19
+
20
+ ```
21
+ ## Daily Cost Report — [today's date]
22
+
23
+ **Total spent today:** $X.XX USD
24
+ **Sessions today:** N | **Currently running:** M
25
+
26
+ ### Running sessions
27
+ - [project] — [model] — $X.XX — [agent_state]
28
+ (per-session data from list_live_sessions)
29
+
30
+ ### Token usage today
31
+ - Input: X tokens | Output: Y tokens
32
+ - Cache read: Z tokens
33
+ ```
34
+
35
+ 5. **If total cost is $0.00**, say "No Claude Code usage detected today" and suggest checking if the claude-view server has indexed recent sessions.
36
+
37
+ 6. **If the user asks about a different time range** (e.g. "this week", "last month"), use the `from` and `to` parameters on `mcp__claude-view__get_stats` accordingly.
@@ -0,0 +1,35 @@
1
+ ---
2
+ name: session-recap
3
+ description: "Use when the user asks to recap, summarize, or review a Claude Code session — e.g. 'recap my last session', 'what happened in that session', 'session summary'"
4
+ ---
5
+
6
+ # Session Recap
7
+
8
+ Summarize a Claude Code session using the claude-view MCP tools.
9
+
10
+ ## Steps
11
+
12
+ 1. **Identify the session.** If the user specified a session ID, use it. Otherwise, call the `mcp__claude-view__list_sessions` tool with `limit: 5` to show recent sessions and ask which one to recap. If the user says "last session" or "most recent", use the first result.
13
+
14
+ 2. **Fetch session details.** Call the `mcp__claude-view__get_session` tool with the session ID.
15
+
16
+ 3. **Present the recap** in this format:
17
+
18
+ ```
19
+ ## Session Recap: [project] — [branch]
20
+
21
+ **Duration:** X minutes | **Model:** [model] | **Turns:** [turns]
22
+
23
+ ### What was done
24
+ [2-3 sentence summary based on recent_commits and summary field]
25
+
26
+ ### Commits
27
+ - `abc1234` — commit message
28
+ - `def5678` — commit message
29
+
30
+ ### Metrics
31
+ - Input tokens: [input_tokens] | Output tokens: [output_tokens] | Cache hits: [cache_read_tokens]
32
+ - Cost efficiency: [from derived_metrics if available]
33
+ ```
34
+
35
+ 4. **Keep it concise.** The recap should fit in one screen. If there are more than 5 commits, show the top 5 and note "and N more".
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: standup
3
+ description: "Use when the user asks for a standup update, work log, or activity summary — e.g. 'standup update', 'what did I work on today', 'work log', 'daily summary'"
4
+ ---
5
+
6
+ # Standup Update
7
+
8
+ Generate a standup-style work summary from recent Claude Code sessions.
9
+
10
+ ## Steps
11
+
12
+ 1. **Fetch recent sessions.** Call `mcp__claude-view__list_sessions` with:
13
+ - `sort: "recent"`
14
+ - `limit: 20`
15
+
16
+ From the results, filter to sessions whose `modified` field (ISO 8601 string) is within the last 24 hours. If the user asks about a different period (e.g. "this week"), adjust the filter accordingly.
17
+
18
+ 2. **For the top 3-5 sessions by duration**, call `mcp__claude-view__get_session` on each to get commit details.
19
+
20
+ 3. **Check for running sessions.** Call `mcp__claude-view__list_live_sessions` to find any currently active sessions for the "In Progress" section.
21
+
22
+ 4. **Present the standup** in this format:
23
+
24
+ ```
25
+ ## Standup — [today's date]
26
+
27
+ ### Done
28
+ - **[project] ([branch])** — [1-line summary from recent_commits/summary] (Xm)
29
+ - **[project] ([branch])** — [1-line summary] (Xm)
30
+
31
+ ### In Progress
32
+ - [project] — [model] — [agent_state] (from list_live_sessions)
33
+
34
+ ### Metrics
35
+ - Sessions: N | Total time: Xh Ym | Commits: Z
36
+ ```
37
+
38
+ 5. **Keep each item to one line.** The standup should be copy-pasteable into Slack or a standup bot.
39
+
40
+ 6. **If no sessions found in the time range**, say "No Claude Code sessions found in the last 24 hours."