codekin 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codekin might be problematic. Click here for more details.

Files changed (86) hide show
  1. package/README.md +83 -0
  2. package/bin/codekin.mjs +372 -0
  3. package/dist/assets/index-BrKgETi_.css +1 -0
  4. package/dist/assets/index-C8gwtjTl.js +105 -0
  5. package/dist/data/repos.json +33 -0
  6. package/dist/favicon.svg +15 -0
  7. package/dist/index.html +14 -0
  8. package/package.json +53 -0
  9. package/server/dist/auth-routes.d.ts +12 -0
  10. package/server/dist/auth-routes.js +29 -0
  11. package/server/dist/auth-routes.js.map +1 -0
  12. package/server/dist/claude-process.d.ts +103 -0
  13. package/server/dist/claude-process.js +524 -0
  14. package/server/dist/claude-process.js.map +1 -0
  15. package/server/dist/config.d.ts +27 -0
  16. package/server/dist/config.js +54 -0
  17. package/server/dist/config.js.map +1 -0
  18. package/server/dist/crypto-utils.d.ts +12 -0
  19. package/server/dist/crypto-utils.js +22 -0
  20. package/server/dist/crypto-utils.js.map +1 -0
  21. package/server/dist/session-archive.d.ts +53 -0
  22. package/server/dist/session-archive.js +160 -0
  23. package/server/dist/session-archive.js.map +1 -0
  24. package/server/dist/session-manager.d.ts +226 -0
  25. package/server/dist/session-manager.js +1476 -0
  26. package/server/dist/session-manager.js.map +1 -0
  27. package/server/dist/session-routes.d.ts +12 -0
  28. package/server/dist/session-routes.js +207 -0
  29. package/server/dist/session-routes.js.map +1 -0
  30. package/server/dist/stepflow-handler.d.ts +141 -0
  31. package/server/dist/stepflow-handler.js +445 -0
  32. package/server/dist/stepflow-handler.js.map +1 -0
  33. package/server/dist/stepflow-prompt.d.ts +29 -0
  34. package/server/dist/stepflow-prompt.js +119 -0
  35. package/server/dist/stepflow-prompt.js.map +1 -0
  36. package/server/dist/stepflow-types.d.ts +249 -0
  37. package/server/dist/stepflow-types.js +30 -0
  38. package/server/dist/stepflow-types.js.map +1 -0
  39. package/server/dist/types.d.ts +362 -0
  40. package/server/dist/types.js +9 -0
  41. package/server/dist/types.js.map +1 -0
  42. package/server/dist/upload-routes.d.ts +12 -0
  43. package/server/dist/upload-routes.js +217 -0
  44. package/server/dist/upload-routes.js.map +1 -0
  45. package/server/dist/webhook-config.d.ts +9 -0
  46. package/server/dist/webhook-config.js +55 -0
  47. package/server/dist/webhook-config.js.map +1 -0
  48. package/server/dist/webhook-dedup.d.ts +21 -0
  49. package/server/dist/webhook-dedup.js +122 -0
  50. package/server/dist/webhook-dedup.js.map +1 -0
  51. package/server/dist/webhook-github.d.ts +50 -0
  52. package/server/dist/webhook-github.js +175 -0
  53. package/server/dist/webhook-github.js.map +1 -0
  54. package/server/dist/webhook-handler.d.ts +69 -0
  55. package/server/dist/webhook-handler.js +368 -0
  56. package/server/dist/webhook-handler.js.map +1 -0
  57. package/server/dist/webhook-prompt.d.ts +5 -0
  58. package/server/dist/webhook-prompt.js +67 -0
  59. package/server/dist/webhook-prompt.js.map +1 -0
  60. package/server/dist/webhook-rate-limiter.d.ts +30 -0
  61. package/server/dist/webhook-rate-limiter.js +78 -0
  62. package/server/dist/webhook-rate-limiter.js.map +1 -0
  63. package/server/dist/webhook-routes.d.ts +16 -0
  64. package/server/dist/webhook-routes.js +58 -0
  65. package/server/dist/webhook-routes.js.map +1 -0
  66. package/server/dist/webhook-types.d.ts +98 -0
  67. package/server/dist/webhook-types.js +2 -0
  68. package/server/dist/webhook-types.js.map +1 -0
  69. package/server/dist/webhook-workspace.d.ts +11 -0
  70. package/server/dist/webhook-workspace.js +124 -0
  71. package/server/dist/webhook-workspace.js.map +1 -0
  72. package/server/dist/workflow-config.d.ts +24 -0
  73. package/server/dist/workflow-config.js +66 -0
  74. package/server/dist/workflow-config.js.map +1 -0
  75. package/server/dist/workflow-engine.d.ts +130 -0
  76. package/server/dist/workflow-engine.js +529 -0
  77. package/server/dist/workflow-engine.js.map +1 -0
  78. package/server/dist/workflow-loader.d.ts +31 -0
  79. package/server/dist/workflow-loader.js +297 -0
  80. package/server/dist/workflow-loader.js.map +1 -0
  81. package/server/dist/workflow-routes.d.ts +14 -0
  82. package/server/dist/workflow-routes.js +222 -0
  83. package/server/dist/workflow-routes.js.map +1 -0
  84. package/server/dist/ws-server.d.ts +14 -0
  85. package/server/dist/ws-server.js +441 -0
  86. package/server/dist/ws-server.js.map +1 -0
@@ -0,0 +1,33 @@
1
+ {
2
+ "repos": [
3
+ {
4
+ "id": "Erwin-Analytics",
5
+ "name": "Erwin-Analytics",
6
+ "path": "/srv/repos/Erwin-Analytics",
7
+ "workingDir": "/home/dev/repos/Erwin-Analytics",
8
+ "skills": [],
9
+ "tags": [
10
+ "node"
11
+ ]
12
+ },
13
+ {
14
+ "id": "codekin",
15
+ "name": "codekin",
16
+ "path": "/srv/repos/codekin",
17
+ "workingDir": "/home/dev/repos/codekin",
18
+ "skills": [],
19
+ "tags": [
20
+ "node"
21
+ ]
22
+ },
23
+ {
24
+ "id": "todo-tasks-md",
25
+ "name": "todo-tasks-md",
26
+ "path": "/srv/repos/todo-tasks-md",
27
+ "workingDir": "/home/dev/repos/todo-tasks-md",
28
+ "skills": [],
29
+ "tags": []
30
+ }
31
+ ],
32
+ "generatedAt": "2026-02-21T13:12:09.323Z"
33
+ }
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="#e4ae42" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round">
2
+ <path stroke="none" d="M0 0h24v24H0z" fill="none"/>
3
+ <!-- Center nucleus ring -->
4
+ <path d="M9 12a3 3 0 1 0 6 0a3 3 0 1 0 -6 0" />
5
+ <!-- Inner filled core -->
6
+ <circle cx="12" cy="12" r="0.75" fill="#e4ae42" stroke="none" />
7
+ <!-- Orbital arcs -->
8
+ <path d="M8 20.1a9 9 0 0 1 -5 -7.1" />
9
+ <path d="M16 20.1a9 9 0 0 0 5 -7.1" />
10
+ <path d="M6.2 5a9 9 0 0 1 11.4 0" />
11
+ <!-- Orbital endpoint dots -->
12
+ <circle cx="12" cy="21" r="1" fill="#e4ae42" stroke="none" />
13
+ <circle cx="3" cy="9" r="1" fill="#e4ae42" stroke="none" />
14
+ <circle cx="21" cy="9" r="1" fill="#e4ae42" stroke="none" />
15
+ </svg>
@@ -0,0 +1,14 @@
1
+ <!doctype html>
2
+ <html lang="en" class="dark">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
7
+ <title>Codekin</title>
8
+ <script type="module" crossorigin src="/assets/index-C8gwtjTl.js"></script>
9
+ <link rel="stylesheet" crossorigin href="/assets/index-BrKgETi_.css">
10
+ </head>
11
+ <body class="bg-neutral-12 text-neutral-2">
12
+ <div id="root"></div>
13
+ </body>
14
+ </html>
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "codekin",
3
+ "version": "0.1.3",
4
+ "description": "Web UI for Claude Code sessions with multi-session support and WebSocket streaming",
5
+ "type": "module",
6
+ "bin": {
7
+ "codekin": "bin/codekin.mjs"
8
+ },
9
+ "files": [
10
+ "bin/",
11
+ "dist/",
12
+ "server/dist/"
13
+ ],
14
+ "scripts": {
15
+ "dev": "vite",
16
+ "build": "tsc -b && vite build",
17
+ "lint": "eslint .",
18
+ "preview": "vite preview",
19
+ "test": "vitest run",
20
+ "test:watch": "vitest"
21
+ },
22
+ "dependencies": {
23
+ "@ai-sdk/groq": "^3.0.29",
24
+ "@tabler/icons-react": "^3.37.1",
25
+ "@tailwindcss/vite": "^4.2.0",
26
+ "ai": "^6.0.116",
27
+ "cmdk": "^1.1.1",
28
+ "react": "^19.2.0",
29
+ "react-dom": "^19.2.0",
30
+ "react-markdown": "^10.1.0",
31
+ "react-syntax-highlighter": "^16.1.0",
32
+ "remark-gfm": "^4.0.1",
33
+ "tailwindcss": "^4.2.0"
34
+ },
35
+ "devDependencies": {
36
+ "@eslint/js": "^9.39.1",
37
+ "@types/node": "^24.10.1",
38
+ "@types/react": "^19.2.7",
39
+ "@types/react-dom": "^19.2.3",
40
+ "@types/react-syntax-highlighter": "^15.5.13",
41
+ "@vitejs/plugin-react": "^5.1.1",
42
+ "@vitest/coverage-v8": "^4.0.18",
43
+ "eslint": "^9.39.1",
44
+ "eslint-plugin-react-hooks": "^7.0.1",
45
+ "eslint-plugin-react-refresh": "^0.4.24",
46
+ "globals": "^16.5.0",
47
+ "jsdom": "^28.1.0",
48
+ "typescript": "~5.9.3",
49
+ "typescript-eslint": "^8.48.0",
50
+ "vite": "^7.3.1",
51
+ "vitest": "^4.0.18"
52
+ }
53
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Auth and health REST routes.
3
+ *
4
+ * Mounted directly on the Express app (no path prefix).
5
+ */
6
+ import { Router } from 'express';
7
+ import type { Request } from 'express';
8
+ import type { SessionManager } from './session-manager.js';
9
+ type VerifyFn = (token: string | undefined) => boolean;
10
+ type ExtractFn = (req: Request) => string | undefined;
11
+ export declare function createAuthRouter(verifyToken: VerifyFn, extractToken: ExtractFn, sessions: SessionManager, claudeAvailable: boolean, claudeVersion: string, apiKeySet: boolean): Router;
12
+ export {};
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Auth and health REST routes.
3
+ *
4
+ * Mounted directly on the Express app (no path prefix).
5
+ */
6
+ import { Router } from 'express';
7
+ export function createAuthRouter(verifyToken, extractToken, sessions, claudeAvailable, claudeVersion, apiKeySet) {
8
+ const router = Router();
9
+ router.post('/auth-verify', (req, res) => {
10
+ const token = extractToken(req);
11
+ res.json({ valid: verifyToken(token) });
12
+ });
13
+ router.get('/api/health', (req, res) => {
14
+ const token = extractToken(req);
15
+ if (!verifyToken(token))
16
+ return res.status(401).json({ error: 'Unauthorized' });
17
+ const allSessions = sessions.list();
18
+ res.json({
19
+ status: 'ok',
20
+ claudeAvailable,
21
+ claudeVersion,
22
+ apiKeySet,
23
+ claudeSessions: allSessions.filter(s => s.active).length,
24
+ totalSessions: allSessions.length,
25
+ });
26
+ });
27
+ return router;
28
+ }
29
+ //# sourceMappingURL=auth-routes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-routes.js","sourceRoot":"","sources":["../auth-routes.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAOhC,MAAM,UAAU,gBAAgB,CAC9B,WAAqB,EACrB,YAAuB,EACvB,QAAwB,EACxB,eAAwB,EACxB,aAAqB,EACrB,SAAkB;IAElB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAA;IAEvB,MAAM,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACvC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACzC,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACrC,MAAM,KAAK,GAAG,YAAY,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC;YAAE,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,cAAc,EAAE,CAAC,CAAA;QAE/E,MAAM,WAAW,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;QACnC,GAAG,CAAC,IAAI,CAAC;YACP,MAAM,EAAE,IAAI;YACZ,eAAe;YACf,aAAa;YACb,SAAS;YACT,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM;YACxD,aAAa,EAAE,WAAW,CAAC,MAAM;SAClC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO,MAAM,CAAA;AACf,CAAC"}
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Manages a single Claude CLI child process using stream-json protocol.
3
+ *
4
+ * Spawns `claude` with --output-format stream-json --input-format stream-json,
5
+ * parses the NDJSON stdout line by line, and emits typed events for:
6
+ * - Streaming text deltas (batched from content_block_delta events)
7
+ * - Tool lifecycle (active → done with input summary)
8
+ * - Extended thinking (first-sentence summary extraction)
9
+ * - Permission prompts and control requests
10
+ * - Task/todo tracking (TodoWrite, TaskCreate, TaskUpdate)
11
+ * - Turn results and process exit
12
+ */
13
+ import { EventEmitter } from 'events';
14
+ import type { ClaudeEvent, TaskItem, PromptQuestion } from './types.js';
15
+ /** Typed event map for ClaudeProcess. Each key maps to the listener argument tuple. */
16
+ export interface ClaudeProcessEvents {
17
+ event: [ClaudeEvent];
18
+ text: [string];
19
+ tool_output: [content: string, isError: boolean];
20
+ system_init: [model: string];
21
+ thinking: [summary: string];
22
+ tool_active: [toolName: string, toolInput: string | undefined];
23
+ tool_done: [toolName: string, summary: string | undefined];
24
+ prompt: [promptType: 'permission' | 'question', question: string, options: Array<{
25
+ label: string;
26
+ value: string;
27
+ description?: string;
28
+ }>, multiSelect: boolean | undefined, toolName: string | undefined, toolInput: Record<string, unknown> | undefined, requestId: string | undefined, questions: PromptQuestion[] | undefined];
29
+ control_request: [requestId: string, toolName: string, toolInput: Record<string, unknown>];
30
+ planning_mode: [active: boolean];
31
+ todo_update: [tasks: TaskItem[]];
32
+ result: [text: string, isError: boolean];
33
+ error: [message: string];
34
+ exit: [code: number | null, signal: string | null];
35
+ }
36
+ /**
37
+ * Wraps a Claude CLI child process. Parses stream-json NDJSON output from
38
+ * stdout and emits structured events consumed by SessionManager.
39
+ */
40
+ export declare class ClaudeProcess extends EventEmitter<ClaudeProcessEvents> {
41
+ private workingDir;
42
+ private model?;
43
+ private proc;
44
+ private rl;
45
+ private sessionId;
46
+ private alive;
47
+ private currentToolName;
48
+ private currentToolInput;
49
+ private textBuffer;
50
+ private inThinkingBlock;
51
+ private thinkingText;
52
+ private thinkingSummaryEmitted;
53
+ private pendingExitPlanModeId;
54
+ private tasks;
55
+ private taskSeq;
56
+ /** Additional env vars passed to the child process (session ID, port, token). */
57
+ private extraEnv;
58
+ constructor(workingDir: string, sessionId?: string, extraEnv?: Record<string, string>, model?: string | undefined);
59
+ /** Spawn the Claude CLI process with stream-json I/O and acceptEdits mode. */
60
+ start(): void;
61
+ /** Parse a single NDJSON line from Claude's stdout and dispatch to the appropriate handler. */
62
+ private handleLine;
63
+ /**
64
+ * Process incremental stream events (content_block_start/delta/stop).
65
+ * Handles text deltas, tool input accumulation, thinking blocks, and
66
+ * planning mode detection.
67
+ */
68
+ private handleStreamEvent;
69
+ /** No-op: assistant messages are handled via stream_event deltas instead. */
70
+ private handleAssistantMessage;
71
+ /** Extract tool_result blocks from 'user' events and emit as tool_output. */
72
+ private handleUserEvent;
73
+ /**
74
+ * Handle a control_request from the CLI.
75
+ * With acceptEdits mode + PermissionRequest hook, most permissions go through hooks.
76
+ * This handler remains as fallback and for AskUserQuestion (which uses control_request
77
+ * for user interaction, not permissions).
78
+ */
79
+ private handleControlRequest;
80
+ /** Send a control_response back to the CLI to allow or deny a pending request. */
81
+ sendControlResponse(requestId: string, behavior: 'allow' | 'deny', updatedInput?: Record<string, unknown>, message?: string): void;
82
+ /**
83
+ * Update internal task state from TodoWrite/TaskCreate/TaskUpdate tool calls.
84
+ * Returns true if the task list changed (caller should emit todo_update).
85
+ */
86
+ private handleTaskTool;
87
+ /**
88
+ * Extract a short summary from extended thinking text.
89
+ * Tries to grab the first sentence (up to 120 chars), or truncates at a
90
+ * word boundary if no sentence ending is found after 60+ chars.
91
+ */
92
+ private extractThinkingSummary;
93
+ /** Generate a short human-readable summary of a tool invocation for the UI chip. */
94
+ private summarizeToolInput;
95
+ /** Send a user message to the Claude CLI via stdin (stream-json format). */
96
+ sendMessage(content: string): void;
97
+ /** Write raw data to stdin (used for control_response messages). */
98
+ sendRaw(data: string): void;
99
+ /** Gracefully stop the process (SIGTERM, then SIGKILL after 5s timeout). */
100
+ stop(): void;
101
+ isAlive(): boolean;
102
+ getSessionId(): string;
103
+ }