@ebowwa/coder 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 ADDED
@@ -0,0 +1,123 @@
1
+ # @ebowwa/claude-code-remake
2
+
3
+ A reimplementation of Claude Code CLI using TypeScript + Bun + Rust.
4
+
5
+ Based on binary analysis of Claude Code v2.1.50 (~92% feature parity).
6
+
7
+ ## Features
8
+
9
+ - **API Client**: SSE streaming for Anthropic API with cost calculation
10
+ - **Agent Loop**: Turn-based processing with tool execution
11
+ - **Built-in Tools**: Read, Write, Edit, Bash, Glob, Grep
12
+ - **MCP Client**: Model Context Protocol support (stdio, HTTP, SSE, WebSocket)
13
+ - **Hook System**: 10 lifecycle events for customization
14
+ - **Skill System**: YAML frontmatter skills with `/skillname` invocation
15
+ - **Teammate System**: Multi-agent coordination with tmux backend
16
+ - **Native Module**: Rust-based performance for search, tokens, diff, compact
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ bun install
22
+ bun run build
23
+ ```
24
+
25
+ ## Usage
26
+
27
+ ### CLI
28
+
29
+ ```bash
30
+ # Interactive mode
31
+ bun run cli
32
+
33
+ # Single query
34
+ bun run cli "What files are in this directory?"
35
+
36
+ # With specific model
37
+ bun run cli -m claude-opus-4-6 "Explain this codebase"
38
+
39
+ # With permission mode
40
+ bun run cli --permission-mode acceptEdits "Add a test"
41
+ ```
42
+
43
+ ### Programmatic
44
+
45
+ ```typescript
46
+ import { createMessageStream, agentLoop, tools } from "@ebowwa/claude-code-remake";
47
+
48
+ // Stream API messages
49
+ const result = await createMessageStream(messages, {
50
+ apiKey: process.env.ANTHROPIC_API_KEY,
51
+ model: "claude-sonnet-4-6",
52
+ onToken: (text) => process.stdout.write(text),
53
+ });
54
+
55
+ // Run agent loop
56
+ const agentResult = await agentLoop(messages, {
57
+ apiKey: process.env.ANTHROPIC_API_KEY,
58
+ systemPrompt: "You are a helpful assistant.",
59
+ tools: [tools.ReadTool, tools.WriteTool, tools.BashTool],
60
+ permissionMode: "default",
61
+ workingDirectory: process.cwd(),
62
+ });
63
+ ```
64
+
65
+ ## Project Structure
66
+
67
+ ```
68
+ claude-code-remake/
69
+ ├── src/
70
+ │ ├── types/ # TypeScript type definitions
71
+ │ ├── core/ # API client, agent loop
72
+ │ ├── tools/ # Built-in tools (Read, Write, Edit, Bash, etc.)
73
+ │ ├── mcp/ # MCP client implementation
74
+ │ ├── hooks/ # Hook system for lifecycle events
75
+ │ ├── skills/ # Skill parsing and invocation
76
+ │ ├── teammates/ # Multi-agent coordination
77
+ │ ├── native/ # Native module loader
78
+ │ └── cli.ts # CLI entry point
79
+ ├── rust/
80
+ │ └── src/
81
+ │ ├── search.rs # Ripgrep-based file search
82
+ │ ├── tokens.rs # Token counting
83
+ │ ├── diff.rs # Diff calculation
84
+ │ └── compact.rs # Content compaction
85
+ ├── native/ # Compiled native modules
86
+ └── dist/ # Build output
87
+ ```
88
+
89
+ ## Configuration
90
+
91
+ ### Environment Variables
92
+
93
+ - `ANTHROPIC_API_KEY` - API key for Claude
94
+
95
+ ### CLI Options
96
+
97
+ | Option | Description | Default |
98
+ |--------|-------------|---------|
99
+ | `-m, --model` | Model to use | claude-sonnet-4-6 |
100
+ | `-p, --permission-mode` | Permission mode | default |
101
+ | `--max-tokens` | Maximum output tokens | 4096 |
102
+ | `--system-prompt` | Override system prompt | - |
103
+ | `--mcp-config` | MCP server configuration | - |
104
+
105
+ ## Development
106
+
107
+ ```bash
108
+ # Build TypeScript
109
+ bun run build:ts
110
+
111
+ # Build Rust native module
112
+ bun run build:native
113
+
114
+ # Full build
115
+ bun run build
116
+
117
+ # Development mode with watch
118
+ bun run dev
119
+ ```
120
+
121
+ ## License
122
+
123
+ MIT
package/dist/cli.js ADDED
@@ -0,0 +1,138 @@
1
+ #!/usr/bin/env bun
2
+ // @bun
3
+ import{A as Gz,P as Az,S as bz,T as Nz,Y as Fz,Z as Tz,a as rz,ba as xz,t as n,u as p,w as i,y as Hz}from"./index-4w2t3b0m.js";async function m(z,W){let X=Bun.spawn(["git",...z],{cwd:W,stdout:"pipe",stderr:"pipe"}),Y=await new Response(X.stdout).text(),$=await new Response(X.stderr).text(),Q=await X.exited;return{stdout:Y.trim(),stderr:$.trim(),exitCode:Q}}async function Mz(z){let{exitCode:W}=await m(["rev-parse","--git-dir"],z);return W===0}async function jz(z){let{stdout:W,exitCode:X}=await m(["rev-parse","--abbrev-ref","HEAD"],z);if(X!==0)return"HEAD";return W||"HEAD"}async function wz(z){let{stdout:W,exitCode:X}=await m(["rev-list","--left-right","--count","@{upstream}...HEAD"],z);if(X!==0||!W)return{ahead:0,behind:0};let Y=W.split(/\s+/);if(Y.length>=2&&Y[0]!==void 0&&Y[1]!==void 0)return{ahead:parseInt(Y[0],10)||0,behind:parseInt(Y[1],10)||0};return{ahead:0,behind:0}}async function Pz(z){let{stdout:W,exitCode:X}=await m(["status","--porcelain"],z);if(X!==0||!W)return{staged:[],unstaged:[],untracked:[],conflicted:[]};let Y=[],$=[],Q=[],K=[],V=W.split(`
4
+ `);for(let U of V){if(!U)continue;let E=U[0],R=U[1],O=U.substring(3);if(O.includes(" -> ")){let A=O.split(" -> ");O=A[1]??A[0]??O}if(E==="U"||R==="U"||E==="A"&&R==="A"||E==="D"&&R==="D"||E==="A"&&R==="U"||E==="U"&&R==="A"||E==="D"&&R==="U"||E==="U"&&R==="D"){K.push(O);continue}if(E==="?"&&R==="?"){Q.push(O);continue}if(E!==" "&&E!=="?"&&E!=="!")Y.push(O);if(R!==" "&&R!=="?"&&R!=="!"){if(!Y.includes(O))$.push(O)}}return{staged:Y,unstaged:$,untracked:Q,conflicted:K}}async function k(z){try{if(!await Mz(z))return null;let[X,Y,$]=await Promise.all([jz(z),wz(z),Pz(z)]);return{branch:X,ahead:Y.ahead,behind:Y.behind,staged:$.staged,unstaged:$.unstaged,untracked:$.untracked,conflicted:$.conflicted}}catch(W){return console.error("Error getting git status:",W),null}}import{randomUUID as Dz}from"crypto";import{execSync as d}from"child_process";var h=process.env.CLAUDE_CHECKPOINTS_DIR||`${process.env.HOME}/.claude/checkpoints`;function vz(z){let W=0;for(let X=0;X<z.length;X++){let Y=z.charCodeAt(X);W=(W<<5)-W+Y,W=W&W}return Math.abs(W).toString(16)}function yz(z){try{d("git rev-parse --is-inside-work-tree",{cwd:z,encoding:"utf-8",stdio:["pipe","pipe","pipe"]});let W=d("git rev-parse --abbrev-ref HEAD",{cwd:z,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim(),X=0,Y=0;try{let U=d("git rev-list --left-right --count @{upstream}...HEAD 2>/dev/null || echo '0 0'",{cwd:z,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim().split(/\s+/);Y=parseInt(U[0]||"0",10),X=parseInt(U[1]||"0",10)}catch{}let $=d("git status --porcelain",{cwd:z,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim(),Q=[],K=[],V=[];for(let U of $.split(`
5
+ `)){if(!U.trim())continue;let E=U[0],R=U[1],O=U.slice(3);if(E==="?"&&R==="?")V.push(O);else if(E!==" "&&E!=="?")Q.push(O);else if(R!==" ")K.push(O)}return{branch:W,ahead:X,behind:Y,staged:Q,unstaged:K,untracked:V}}catch(W){return}}async function Sz(z,W){let X=[];for(let Y of W)try{let $=`${z}/${Y}`,Q=Bun.file($);if(await Q.exists()){let K=await Q.text();X.push({path:Y,content:K,hash:vz(K)})}}catch{}return X}async function Iz(z,W){let X=0,Y=0;for(let $ of W)try{let Q=`${z}/${$.path}`;await Bun.write(Q,$.content),X++}catch{Y++}return{restored:X,failed:Y}}async function r(){if(!await Bun.file(h).exists())await Bun.write(h+"/.gitkeep","")}function o(z){return`${h}/${z}.json`}async function S(z){let W=new Map;try{let X=o(z),Y=Bun.file(X);if(await Y.exists()){let $=await Y.text(),Q=JSON.parse($);for(let K of Q)W.set(K.id,K)}}catch(X){}return W}async function fz(z,W){await r();let X=o(z),Y=Array.from(W.values());await Bun.write(X,JSON.stringify(Y,null,2))}async function t(z,W,X={}){let Y=await S(z),$=X.workingDirectory||process.cwd(),Q=yz($),K=[];if(X.trackFiles!==!1&&Q){let U=[...Q.staged,...Q.unstaged,...Q.untracked];K=await Sz($,U)}let V={id:Dz().slice(0,8),sessionId:z,timestamp:Date.now(),label:X.label||`Checkpoint ${Y.size+1}`,description:X.description,messages:JSON.parse(JSON.stringify(W)),files:K,gitState:Q,metadata:{model:X.model,workingDirectory:$,totalCost:X.totalCost||0,messageCount:W.length,fileCount:K.length}};return Y.set(V.id,V),await fz(z,Y),V}async function g(z,W){return(await S(z)).get(W)||null}async function I(z,W={}){let X=W.workingDirectory||z.metadata.workingDirectory||process.cwd(),Y=0,$=0;if(W.restoreFiles!==!1&&z.files.length>0){let Q=await Iz(X,z.files);Y=Q.restored,$=Q.failed}return{messages:W.restoreMessages!==!1?z.messages:[],filesRestored:Y,filesFailed:$}}async function e(z){let W=await S(z);return Array.from(W.values()).sort((X,Y)=>Y.timestamp-X.timestamp)}function D(z,W=!1){let X=new Date(z.timestamp),Y=X.toLocaleTimeString(),$=X.toLocaleDateString(),Q=`\x1B[33m${z.id}\x1B[0m `;if(Q+=`\x1B[1m${z.label}\x1B[0m `,Q+=`\x1B[90m(${$} ${Y})\x1B[0m`,z.files.length>0)Q+=` \x1B[32m[${z.files.length} files]\x1B[0m`;if(z.gitState)Q+=` \x1B[34m(${z.gitState.branch})\x1B[0m`;if(W){if(Q+=`
6
+ Messages: ${z.metadata.messageCount}`,Q+=`
7
+ Files: ${z.metadata.fileCount}`,Q+=`
8
+ Cost: $${z.metadata.totalCost.toFixed(4)}`,z.gitState){let K=z.gitState.staged.length+z.gitState.unstaged.length+z.gitState.untracked.length;Q+=`
9
+ Git changes: ${K}`}if(z.description)Q+=`
10
+ ${z.description}`}return Q}function s(z){if(z.length===0){console.log("\x1B[90mNo checkpoints saved.\x1B[0m"),console.log("\x1B[90mUse /checkpoint <label> to create one.\x1B[0m");return}console.log(`
11
+ \x1B[1mCheckpoints (${z.length}):\x1B[0m`),console.log("\x1B[90m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m");for(let W of z)console.log(D(W));console.log("\x1B[90m\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\x1B[0m"),console.log("\x1B[90m/restore <id> - Restore checkpoint (files + chat)\x1B[0m"),console.log("\x1B[90m/restore-chat <id> - Restore chat only (no files)\x1B[0m"),console.log("\x1B[90m/checkpoint <label> - Create new checkpoint\x1B[0m")}function zz(z){let W=[];if(z.files.length>0)W.push(`${z.files.length} files`);if(W.push(`${z.metadata.messageCount} msgs`),z.gitState){let X=z.gitState.staged.length+z.gitState.unstaged.length+z.gitState.untracked.length;if(X>0)W.push(`${X} changes`)}return W.join(" | ")}var Wz=(z)=>`${h}/${z}-nav.json`;async function u(z){try{let W=Bun.file(Wz(z));if(await W.exists())return JSON.parse(await W.text())}catch{}return{sessionId:z,checkpointIds:[],currentIndex:-1,undoneIds:[]}}async function c(z){await r(),await Bun.write(Wz(z.sessionId),JSON.stringify(z,null,2))}async function Xz(z,W){let X=await u(z);if(X.currentIndex<X.checkpointIds.length-1)X.checkpointIds=X.checkpointIds.slice(0,X.currentIndex+1);X.checkpointIds.push(W),X.currentIndex=X.checkpointIds.length-1,X.undoneIds=[],await c(X)}async function Yz(z){let W=await u(z),X=await S(z);if(W.currentIndex<=0)return{checkpoint:null,canRedo:!1};let Y=W.checkpointIds[W.currentIndex];if(Y)W.undoneIds.push(Y);W.currentIndex--;let $=W.checkpointIds[W.currentIndex];return await c(W),{checkpoint:$?X.get($)||null:null,canRedo:W.undoneIds.length>0}}async function Zz(z){let W=await u(z),X=await S(z);if(W.undoneIds.length===0)return{checkpoint:null,canRedo:!1};let Y=W.undoneIds.pop();return W.currentIndex++,await c(W),{checkpoint:X.get(Y)||null,canRedo:W.undoneIds.length>0}}async function $z(z){let W=await u(z);return{total:W.checkpointIds.length,current:W.currentIndex+1,canUndo:W.currentIndex>0,canRedo:W.undoneIds.length>0,currentId:W.checkpointIds[W.currentIndex]}}import{readFile as Cz,access as mz}from"fs/promises";import{join as Qz}from"path";var kz={globalPath:`${process.env.HOME}/.claude/CLAUDE.md`,projectPath:".claude/CLAUDE.md",rootPath:"CLAUDE.md"};async function dz(z){try{return await mz(z),!0}catch{return!1}}async function a(z){try{if(await dz(z))return(await Cz(z,"utf-8")).trim()}catch(W){}return null}async function hz(z=process.cwd(),W={}){let X={...kz,...W},Y=[],$=null,Q=null,K=X.globalPath;if($=await a(K),$)Y.push(K);let V=Qz(z,X.projectPath),U=Qz(z,X.rootPath);if(Q=await a(V),Q)Y.push(V);else if(Q=await a(U),Q)Y.push(U);let E=[];if($)E.push(`# Global Instructions
12
+
13
+ ${$}`);if(Q)E.push(`# Project Instructions
14
+
15
+ ${Q}`);return{global:$,project:Q,merged:E.join(`
16
+
17
+ ---
18
+
19
+ `),sources:Y}}async function Jz(z=process.cwd()){let{merged:W,sources:X}=await hz(z);if(!W)return"";return`
20
+ ## Project Instructions
21
+
22
+ ${X.length>0?`Loaded from: ${X.join(", ")}`:""}
23
+
24
+ ${W}
25
+ `}import{readFile as uz,access as lz}from"fs/promises";import{join as f}from"path";var Bz=process.env.HOME||"",Vz=f(Bz,".claude"),M={main:f(Bz,".claude.json"),settings:f(Vz,"settings.json"),keybindings:f(Vz,"keybindings.json"),projectSettings:(z)=>f(z,".claude","settings.json")};async function pz(z){try{return await lz(z),!0}catch{return!1}}async function l(z,W){try{if(await pz(z)){let X=await uz(z,"utf-8");return{config:JSON.parse(X),loaded:!0}}}catch(X){}return{config:W,loaded:!1}}async function gz(){return l(M.main,{})}async function cz(){return l(M.settings,{})}async function az(){return l(M.keybindings,{bindings:[]})}async function nz(z){return l(M.projectSettings(z),{})}function iz(z,W){return z.projects?.[W]}async function Uz(z=process.cwd()){let W=[],{config:X,loaded:Y}=await gz();if(Y)W.push(M.main);let{config:$,loaded:Q}=await cz();if(Q)W.push(M.settings);let{config:K,loaded:V}=await az();if(V)W.push(M.keybindings);let{config:U,loaded:E}=await nz(z);if(E)W.push(M.projectSettings(z));return{main:X,settings:$,keybindings:K,projectSettings:U,sources:W}}function Kz(z,W){return{hooks:{...z.hooks,...W.hooks},permissions:{...z.permissions,...W.permissions}}}function Lz(z,W){let X={};if(z.mcpServers)Object.assign(X,z.mcpServers);let Y=iz(z,W);if(Y?.mcpServers)Object.assign(X,Y.mcpServers);return X}function Rz(z){let W={};if(!z.hooks)return W;for(let[X,Y]of Object.entries(z.hooks)){let $=[],Q=X;for(let K of Y)for(let V of K.hooks)$.push({event:Q,command:V.type==="command"?V.command||"":"",timeout:V.timeout||60000,enabled:!0,_matcher:K.matcher,_prompt:V.type==="prompt"?V.prompt:void 0});if($.length>0)W[Q]=$}return W}function Ez(z){return z.permissions?.defaultMode||"default"}function Oz(z){return new Set(z.permissions?.allowedTools||[])}function _z(z){return new Set(z.permissions?.disallowedTools||[])}async function oz(z){try{let X=await Bun.file(z).text(),Y=JSON.parse(X);if("servers"in Y&&typeof Y.servers==="object"&&Y.servers!==null)return Y.servers;if("type"in Y){let $={};return $.default=Y,$}return Y}catch(W){let X=W instanceof Error?W.message:String(W);throw Error(`Failed to load MCP config from ${z}: ${X}`)}}function tz(z){let W=[];for(let[X,Y]of z)for(let $ of Y.tools)W.push({name:`mcp__${X}__${$.name}`,description:$.description,input_schema:$.inputSchema,handler:async(Q,K)=>{if(!Y.connected)return{content:`Error: MCP server "${X}" is not connected`,is_error:!0};return Y.callTool($.name,Q)}});return W}function ez(){let z=process.argv.slice(2),W={model:"claude-sonnet-4-6",permissionMode:"default",maxTokens:4096};for(let X=0;X<z.length;X++)switch(z[X]){case"--model":case"-m":W.model=z[++X]??"claude-sonnet-4-6";break;case"--permission-mode":case"-p":W.permissionMode=z[++X]??"default";break;case"--max-tokens":W.maxTokens=parseInt(z[++X]??"4096",10);break;case"--system-prompt":W.systemPrompt=z[++X];break;case"--append-system-prompt":W.appendSystemPrompt=z[++X];break;case"--config":W.configFile=z[++X];break;case"--mcp-config":W.mcpConfig=z[++X];break;case"--resume":W.resumeSession=z[++X];break;case"--sessions":W.listSessions=!0;break;case"--teammate-mode":W.teammateMode=!0;break;case"--agent-id":W.agentId=z[++X];break;case"--agent-name":W.agentName=z[++X];break;case"--team-name":W.teamName=z[++X];break;case"--agent-color":W.agentColor=z[++X];break;case"--interleaved":W.interleaved=!0;break;case"--no-interleaved":W.interleaved=!1;break;case"--extended-thinking":case"-e":W.extendedThinking=!0;break;case"--effort":W.effort=z[++X]??"medium";break;case"--query":case"-q":W.query=z[++X];break;case"--help":case"-h":sz(),process.exit(0)}return W}function sz(){console.log(`
26
+ Claude Code Remake v0.1.0
27
+ A reimplementation of Claude Code CLI
28
+
29
+ USAGE:
30
+ claude-remake [OPTIONS] [QUERY]
31
+
32
+ OPTIONS:
33
+ -m, --model <model> Model to use (default: claude-sonnet-4-6)
34
+ -p, --permission-mode <mode> Permission mode (default, acceptEdits, bypassPermissions)
35
+ --max-tokens <tokens> Maximum output tokens (default: 4096)
36
+
37
+ Extended Thinking:
38
+ -e, --extended-thinking Enable extended thinking mode
39
+ --effort <level> Thinking effort: low, medium, high, max
40
+ --interleaved Enable interleaved thinking (default: true)
41
+ --no-interleaved Disable interleaved thinking
42
+ --system-prompt <prompt> Override system prompt
43
+ --append-system-prompt <p> Append to system prompt
44
+ --config <file> Configuration file path
45
+ --mcp-config <file> MCP server configuration file
46
+ --resume <session-id> Resume a previous session
47
+ --sessions List recent sessions
48
+ --teammate-mode Run as teammate agent
49
+ --agent-id <id> Agent identifier
50
+ --agent-name <name> Agent display name
51
+ --team-name <name> Team name
52
+ --agent-color <color> Agent color for UI
53
+ -q, --query <query> Single query to execute
54
+ -h, --help Show this help message
55
+
56
+ EXAMPLES:
57
+ claude-remake "What files are in this directory?"
58
+ claude-remake -m claude-opus-4-6 "Explain this codebase"
59
+ claude-remake --permission-mode acceptEdits "Add a test"
60
+ claude-remake --sessions
61
+ claude-remake --resume abc123-def456
62
+ `)}async function zW(){let z=ez(),W=new Hz;if(await W.init(),z.listSessions){let B=await W.listSessions(20);Gz(B),process.exit(0)}let X=process.env.ANTHROPIC_API_KEY||process.env.CLAUDE_API_KEY||process.env.ANTHROPIC_AUTH_TOKEN||process.env.Z_AI_API_KEY;if(!X)console.error("Error: ANTHROPIC_API_KEY, CLAUDE_API_KEY, ANTHROPIC_AUTH_TOKEN, or Z_AI_API_KEY environment variable required"),process.exit(1);console.log("\x1B[90mLoading configuration...\x1B[0m");let Y;try{Y=await Uz(process.cwd())}catch(B){let G=B instanceof Error?B.message:String(B);console.error(`\x1B[33mWarning: Failed to load config: ${G}\x1B[0m`),Y={main:{},settings:{},keybindings:{bindings:[]},projectSettings:{},sources:[]}}let $=Kz(Y.settings,Y.projectSettings);if(Y.sources.length>0)console.log(`\x1B[90m Config sources: ${Y.sources.length} files\x1B[0m`);if(z.permissionMode==="default"){let B=Ez($);if(B!=="default")z.permissionMode=B,console.log(`\x1B[90m Permission mode: ${B} (from config)\x1B[0m`)}let Q=Oz($),K=_z($),V=new Nz,U=new Fz,E=new xz,R=Rz($);for(let[B,G]of Object.entries(R))for(let H of G)V.register(B,H);if(Object.keys(R).length>0)console.log(`\x1B[90m Hooks registered: ${Object.keys(R).length} events\x1B[0m`);let O=process.cwd()+"/.claude/skills";U.loadFromDirectory(O,"project");let _=new Map,F=Lz(Y.main,process.cwd());if(z.mcpConfig)try{console.log(`\x1B[90mLoading MCP config from ${z.mcpConfig}...\x1B[0m`),F=await oz(z.mcpConfig)}catch(B){let G=B instanceof Error?B.message:String(B);console.error(`\x1B[33mWarning: Failed to load MCP config file: ${G}\x1B[0m`)}if(Object.keys(F).length>0){let G=Object.entries(F).filter(([H,q])=>!q.disabled).length;if(G>0){console.log(`\x1B[90m Connecting to ${G} MCP server(s)...\x1B[0m`);let H=await bz(F,(q)=>{console.log(`\x1B[90m ${q}\x1B[0m`)});for(let[q,y]of H)_.set(q,y);if(_.size>0)console.log(`\x1B[32m Connected to ${_.size} MCP server(s)\x1B[0m`);else console.log("\x1B[33m Warning: No MCP servers connected successfully\x1B[0m")}else if(Object.keys(F).length>0)console.log(`\x1B[90m MCP config loaded but all ${Object.keys(F).length} server(s) are disabled\x1B[0m`)}let j=[...Az,...tz(_)],v=await k(process.cwd()),T=z.systemPrompt||await YW(v);if(z.appendSystemPrompt)T+=`
63
+
64
+ ${z.appendSystemPrompt}`;if(z.teammateMode&&z.teamName)T+=`
65
+
66
+ You are running as a teammate agent in the "${z.teamName}" team.`,T+=`
67
+ Agent ID: ${z.agentId}`,T+=`
68
+ Agent Name: ${z.agentName}`;let L=[],b;if(z.resumeSession){let B=await W.resumeSession(z.resumeSession);if(!B)console.error(`Error: Session not found: ${z.resumeSession}`),process.exit(1);L=B.messages,b=z.resumeSession,z.model=B.metadata.model,z.agentName=B.metadata.agentName,z.agentColor=B.metadata.agentColor,z.teamName=B.metadata.teamName,console.log(`\x1B[90mResumed session: ${z.resumeSession}\x1B[0m`),console.log(`\x1B[90mModel: ${z.model} | Messages: ${L.length}\x1B[0m
69
+ `)}else b=await W.createSession({model:z.model,workingDirectory:process.cwd(),agentName:z.agentName,agentColor:z.agentColor,teamName:z.teamName});let N=z.query,x=process.argv[2];if(!N&&process.argv.length>2&&x&&!x.startsWith("-"))N=process.argv.slice(2).join(" ");if(!N)console.log("Claude Code Remake v0.1.0"),console.log(`Session: ${b}`),console.log(`Type your message or /help for commands.
70
+ `),await WW(X,z,T,j,V,U,W,L,b,_);else await XW(X,z,T,j,N,W,b)}async function WW(z,W,X,Y,$,Q,K,V,U,E){let R=process.stdin.isTTY,O=process.env.CLAUDE_FORCE_INTERACTIVE==="true";if(!R&&!O){console.error("Error: Interactive mode requires a TTY. Use -q for single query mode."),console.error(" Or set CLAUDE_FORCE_INTERACTIVE=true for testing.");return}let _=!0,A=0,F=await k(process.cwd()),j=rz("readline").createInterface({input:process.stdin,output:process.stdout,terminal:!0,historySize:1000,removeHistoryDuplicates:!0});process.on("SIGINT",()=>{console.log(`
71
+ \x1B[90mGoodbye!\x1B[0m`),j.close(),process.exit(0)});let v=(L)=>{return new Promise((b,N)=>{if(j.closed){N(Error("Readline closed"));return}j.question(L,(x)=>{b(x)})})},T=async(L)=>{if(console.log(`
72
+ \x1B[36m\u2501\u2501\u2501 Permission Required \u2501\u2501\u2501\x1B[0m`),console.log(`Tool: \x1B[1m${L.toolName}\x1B[0m`),console.log(`Risk: \x1B[32m${L.riskLevel.toUpperCase()}\x1B[0m`),console.log(`Action: ${L.description}`),L.file)console.log(`File: ${L.file}`);else if(L.command)console.log(`Command: ${L.command}`);else if(L.toolInput.file_path)console.log(`File: ${L.toolInput.file_path}`);else if(L.toolInput.command)console.log(`Command: ${L.toolInput.command}`);while(!0)try{switch((await v(`
73
+ Allow? [y]es / [n]o / [a]lways / [d]eny always: `)).trim().toLowerCase()){case"y":case"yes":case"":return{decision:"allow"};case"n":case"no":return{decision:"deny",reason:"User denied"};case"a":case"always":return{decision:"allowAlways"};case"d":case"deny":return{decision:"denyAlways",reason:"User denied always"};default:console.log("Please enter y, n, a, or d")}}catch{return{decision:"deny",reason:"Input error"}}};while(_)try{let L=await v(`
74
+ \x1B[1;36mYou:\x1B[0m `);if(!L.trim())continue;if(L.startsWith("/")){let G=L.slice(1).split(" ")[0]??"",H=L.slice(G.length+2);switch(G){case"exit":case"quit":case"q":_=!1,console.log("\x1B[90mGoodbye!\x1B[0m");continue;case"help":case"?":console.log(`
75
+ \x1B[1mCommands:\x1B[0m
76
+ /help, /? Show this help
77
+ /exit, /quit, /q Exit the session
78
+ /clear Clear conversation history
79
+ /compact Force context compaction
80
+ /model <model> Switch model
81
+ /tools List available tools
82
+ /mcp List MCP servers and tools
83
+ /skills List available skills
84
+ /cost Show total cost
85
+ /status Show session status
86
+
87
+ \x1B[1mCheckpoints (chat + code):\x1B[0m
88
+ /checkpoint <label> Save checkpoint (chat + files)
89
+ /checkpoints List saved checkpoints
90
+ /restore <id> Restore checkpoint (asks about files)
91
+ /restore-chat <id> Restore chat only (no files)
92
+ /undo Go back to previous checkpoint
93
+ /redo Go forward after undo
94
+ /cps-status Show checkpoint navigation status
95
+
96
+ \x1B[1mExport:\x1B[0m
97
+ /export [format] Export session (jsonl/json/md)
98
+ `);continue;case"clear":V.length=0,console.log("\x1B[90mConversation cleared.\x1B[0m");continue;case"compact":console.log("\x1B[90mForcing context compaction...\x1B[0m");continue;case"model":if(H)W.model=H,console.log(`\x1B[90mSwitched to model: ${H}\x1B[0m`);else console.log(`Current model: \x1B[1m${W.model}\x1B[0m`);continue;case"tools":console.log("\x1B[1mAvailable tools:\x1B[0m");for(let Z of Y){let J=Z.description.split(".")[0]??Z.description;console.log(` \x1B[33m${Z.name}\x1B[0m: ${J}`)}continue;case"mcp":if(E.size===0)console.log("\x1B[90mNo MCP servers connected.\x1B[0m"),console.log("\x1B[90mUse --mcp-config to specify a config file.\x1B[0m");else{console.log("\x1B[1mConnected MCP Servers:\x1B[0m");for(let[Z,J]of E){let w=J.connected?"\x1B[32m\u25CF\x1B[0m":"\x1B[31m\u25CB\x1B[0m";console.log(` ${w} \x1B[1m${Z}\x1B[0m (${J.tools.length} tools)`);for(let P of J.tools)console.log(` \x1B[33m${P.name}\x1B[0m: ${P.description.slice(0,50)}...`)}}continue;case"skills":let q=Q.getAll();if(q.length===0)console.log("\x1B[90mNo skills loaded.\x1B[0m");else{console.log("\x1B[1mAvailable skills:\x1B[0m");for(let Z of q){let J=Z.description??Z.prompt.slice(0,50);console.log(` \x1B[33m/${Z.name}\x1B[0m: ${J}...`)}}continue;case"cost":console.log(`Total cost: \x1B[1m${p(A)}\x1B[0m`);continue;case"status":case"session":console.log("\x1B[1mSession Status:\x1B[0m"),console.log(` ID: ${U}`),console.log(` Model: ${W.model}`),console.log(` Messages: ${V.length}`),console.log(` Total cost: ${p(A)}`),console.log(` Permission mode: ${W.permissionMode}`);continue;case"export":try{let Z=H||"markdown",J=await K.exportSession(U,Z);console.log(`\x1B[90mSession exported to: ${J}\x1B[0m`)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mExport failed: ${J}\x1B[0m`)}continue;case"checkpoint":case"cp":if(!H){console.log("\x1B[31mUsage: /checkpoint <label>\x1B[0m"),console.log("\x1B[90mExample: /checkpoint before-refactor\x1B[0m"),console.log("\x1B[90mCreates checkpoint with chat history + file snapshots\x1B[0m");continue}try{let Z=await t(U,V,{label:H,model:W.model,workingDirectory:process.cwd(),totalCost:A,trackFiles:!0});await Xz(U,Z.id);let J=zz(Z);if(console.log(`\x1B[32m\u2713 Checkpoint saved:\x1B[0m ${D(Z)}`),J)console.log(`\x1B[90m ${J}\x1B[0m`)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mFailed to create checkpoint: ${J}\x1B[0m`)}continue;case"checkpoints":case"cps":try{let Z=await e(U);s(Z)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mFailed to list checkpoints: ${J}\x1B[0m`)}continue;case"restore":case"rollback":case"rewind":if(!H){console.log("\x1B[31mUsage: /${command} <checkpoint-id>\x1B[0m"),console.log("\x1B[90mUse /checkpoints to see available checkpoints\x1B[0m");continue}try{let Z=H.trim(),J=await g(U,Z);if(!J){console.log(`\x1B[31mCheckpoint not found: ${Z}\x1B[0m`),console.log("\x1B[90mUse /checkpoints to see available checkpoints\x1B[0m");continue}console.log(`
99
+ \x1B[1mRestoring checkpoint:\x1B[0m ${D(J)}`);let w=J.files.length>0,P=!1;if(w){console.log(`\x1B[33m${J.files.length} file(s) saved in checkpoint:\x1B[0m`);for(let qz of J.files.slice(0,5))console.log(` - ${qz.path}`);if(J.files.length>5)console.log(` ... and ${J.files.length-5} more`);P=(await v(`
100
+ \x1B[36mRestore files too? [Y/n]: \x1B[0m`)).trim().toLowerCase()!=="n"}let C=await I(J,{restoreFiles:P,restoreMessages:!0,workingDirectory:process.cwd()});if(V.length=0,V.push(...C.messages),A=J.metadata.totalCost,console.log(`
101
+ \x1B[32m\u2713 Checkpoint restored:\x1B[0m`),console.log(` Messages: ${V.length}`),P&&w){if(console.log(` Files restored: ${C.filesRestored}`),C.filesFailed>0)console.log(` \x1B[33mFiles failed: ${C.filesFailed}\x1B[0m`)}console.log(` Cost reset to: $${A.toFixed(4)}`)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mFailed to restore checkpoint: ${J}\x1B[0m`)}continue;case"restore-chat":if(!H){console.log("\x1B[31mUsage: /restore-chat <checkpoint-id>\x1B[0m"),console.log("\x1B[90mRestores chat only, no files\x1B[0m");continue}try{let Z=H.trim(),J=await g(U,Z);if(!J){console.log(`\x1B[31mCheckpoint not found: ${Z}\x1B[0m`);continue}let w=await I(J,{restoreFiles:!1,restoreMessages:!0});V.length=0,V.push(...w.messages),A=J.metadata.totalCost,console.log(`\x1B[32m\u2713 Chat restored:\x1B[0m ${V.length} messages (no files changed)`)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mFailed to restore chat: ${J}\x1B[0m`)}continue;case"undo":try{let Z=await Yz(U);if(!Z.checkpoint){console.log("\x1B[33mNothing to undo\x1B[0m");continue}let J=await I(Z.checkpoint,{restoreFiles:!0,restoreMessages:!0,workingDirectory:process.cwd()});if(V.length=0,V.push(...J.messages),A=Z.checkpoint.metadata.totalCost,console.log(`\x1B[32m\u2713 Undone to:\x1B[0m ${D(Z.checkpoint)}`),console.log(`\x1B[90mMessages: ${V.length} | Files: ${J.filesRestored}\x1B[0m`),Z.canRedo)console.log("\x1B[90mUse /redo to go forward\x1B[0m")}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mUndo failed: ${J}\x1B[0m`)}continue;case"redo":try{let Z=await Zz(U);if(!Z.checkpoint){console.log("\x1B[33mNothing to redo\x1B[0m");continue}let J=await I(Z.checkpoint,{restoreFiles:!0,restoreMessages:!0,workingDirectory:process.cwd()});if(V.length=0,V.push(...J.messages),A=Z.checkpoint.metadata.totalCost,console.log(`\x1B[32m\u2713 Redone to:\x1B[0m ${D(Z.checkpoint)}`),console.log(`\x1B[90mMessages: ${V.length} | Files: ${J.filesRestored}\x1B[0m`),Z.canRedo)console.log("\x1B[90mUse /redo to go forward again\x1B[0m")}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mRedo failed: ${J}\x1B[0m`)}continue;case"checkpoint-status":case"cps-status":try{let Z=await $z(U);if(console.log("\x1B[1mCheckpoint Navigation:\x1B[0m"),console.log(` Position: ${Z.current}/${Z.total}`),console.log(` Can undo: ${Z.canUndo?"\x1B[32myes\x1B[0m":"\x1B[31mno\x1B[0m"}`),console.log(` Can redo: ${Z.canRedo?"\x1B[32myes\x1B[0m":"\x1B[31mno\x1B[0m"}`),Z.currentId)console.log(` Current: ${Z.currentId}`)}catch(Z){let J=Z instanceof Error?Z.message:String(Z);console.error(`\x1B[31mFailed to get status: ${J}\x1B[0m`)}continue;default:let y=Q.get(G);if(y){console.log(`\x1B[90mLoading skill: ${y.name}\x1B[0m`),X+=`
102
+
103
+ `+Tz(y);continue}console.log(`\x1B[31mUnknown command: /${G}\x1B[0m`),console.log("\x1B[90mType /help for available commands.\x1B[0m");continue}}V.push({role:"user",content:[{type:"text",text:L}]}),await K.saveMessage(V[V.length-1]),process.stdout.write(`
104
+ \x1B[1;35mClaude:\x1B[0m `);let b=W.extendedThinking?{enabled:!0,effort:W.effort??"medium",interleaved:W.interleaved??!0}:void 0,N=await n(V,{apiKey:z,model:W.model,maxTokens:W.maxTokens,systemPrompt:X,tools:Y,permissionMode:W.permissionMode,workingDirectory:process.cwd(),gitStatus:F,extendedThinking:b,onText:(B)=>{process.stdout.write(B)},onThinking:(B)=>{process.stdout.write(`\x1B[90m${B}\x1B[0m`)},onToolUse:(B)=>{process.stdout.write(`
105
+ \x1B[90m[Trying: ${B.name}]\x1B[0m `)},onToolResult:(B)=>{if(B.result.is_error)process.stdout.write("\x1B[31m[Error]\x1B[0m ")},onMetrics:async(B)=>{console.log(`
106
+ \x1B[90m${i(B)}\x1B[0m`),await K.saveMetrics(B)},onPermissionRequest:async(B)=>{return await T({toolName:B.toolName,toolInput:B.toolInput,riskLevel:B.riskLevel,description:B.description,file:B.file,command:B.command})}}),x=N.messages[N.messages.length-1];if(x&&x.role==="assistant")await K.saveMessage(x);V.length=0,V.push(...N.messages),A+=N.totalCost}catch(L){if(L instanceof Error&&L.message==="Readline closed")break;let b=L instanceof Error?L.message:String(L);console.error(`
107
+ \x1B[31mError: ${b}\x1B[0m`)}j.close()}async function XW(z,W,X,Y,$,Q,K){let V=[{role:"user",content:[{type:"text",text:$}]}];await Q.saveMessage(V[0]);let U=await k(process.cwd()),E=W.extendedThinking?{enabled:!0,effort:W.effort??"medium",interleaved:W.interleaved??!0}:void 0;try{let R=await n(V,{apiKey:z,model:W.model,maxTokens:W.maxTokens,systemPrompt:X,tools:Y,permissionMode:W.permissionMode,workingDirectory:process.cwd(),gitStatus:U,extendedThinking:E,onText:(_)=>{process.stdout.write(_)},onThinking:(_)=>{process.stdout.write(`\x1B[90m${_}\x1B[0m`)},onMetrics:async(_)=>{console.log(`
108
+ \x1B[90m${i(_)}\x1B[0m`),await Q.saveMetrics(_)}}),O=R.messages[R.messages.length-1];if(O&&O.role==="assistant")await Q.saveMessage(O);console.log(`
109
+ \x1B[90mSession: ${K}\x1B[0m`),console.log(`\x1B[90mTotal cost: ${p(R.totalCost)}\x1B[0m`)}catch(R){let O=R instanceof Error?R.message:String(R);console.error(`Error: ${O}`),process.exit(1)}}async function YW(z){let W=`You are Claude Code, an AI coding assistant created by Anthropic.
110
+
111
+ You help users with software engineering tasks:
112
+ - Reading, writing, and editing code
113
+ - Running commands and scripts
114
+ - Searching and exploring codebases
115
+ - Debugging and fixing issues
116
+
117
+ Guidelines:
118
+ 1. Be helpful, direct, and thorough
119
+ 2. Explain your reasoning when asked
120
+ 3. Follow user preferences and project conventions
121
+ 4. Use tools effectively to accomplish tasks
122
+ 5. Ask clarifying questions when needed
123
+
124
+ Available tools:
125
+ - Read: Read file contents
126
+ - Write: Write new files
127
+ - Edit: Make precise edits to files
128
+ - Bash: Execute shell commands
129
+ - Glob: Find files by pattern
130
+ - Grep: Search file contents
131
+
132
+ Working directory: ${process.cwd()}`;if(z){if(W+=`
133
+
134
+ Git Status:`,W+=`
135
+ Branch: ${z.branch}`,z.ahead>0||z.behind>0)W+=` (${z.ahead} ahead, ${z.behind} behind)`;if(z.staged.length>0||z.unstaged.length>0||z.untracked.length>0)W+=`
136
+ Changes: ${z.staged.length} staged, ${z.unstaged.length} unstaged, ${z.untracked.length} untracked`}let X=await Jz();if(X)W+=`
137
+
138
+ ${X}`;return W}zW().catch((z)=>{console.error("Fatal error:",z),process.exit(1)});