@axplusb/kepler 1.0.0 → 1.0.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axplusb/kepler",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Kepler — AI coding agent CLI. 30.7% on SWE-bench Lite. Powered by axplusb.tech",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1,6 +1,6 @@
1
1
  /**
2
- * Orca Authentication — GitHub OAuth + config management.
3
- * Reads/writes ~/.orca/config.json (shared with Python CLI).
2
+ * Kepler Authentication — GitHub OAuth + config management.
3
+ * Reads/writes ~/.kepler/config.json.
4
4
  */
5
5
 
6
6
  import * as fs from 'node:fs';
@@ -10,7 +10,7 @@ import * as http from 'node:http';
10
10
  import { getLoginSuccessHTML } from '../ui/banner.mjs';
11
11
  import { resolveBackendUrl } from '../core/backend-url.mjs';
12
12
 
13
- const CONFIG_DIR = path.join(os.homedir(), '.orca');
13
+ const CONFIG_DIR = process.env.KEPLER_HOME || process.env.ORCA_HOME || path.join(os.homedir(), '.kepler');
14
14
  const CONFIG_PATH = path.join(CONFIG_DIR, 'config.json');
15
15
 
16
16
  export class TarangAuth {
@@ -18,7 +18,7 @@ export class TarangAuth {
18
18
  this._config = null;
19
19
  }
20
20
 
21
- /** Ensure ~/.orca/ directory exists with secure permissions. */
21
+ /** Ensure ~/.kepler/ directory exists with secure permissions. */
22
22
  _ensureConfigDir() {
23
23
  if (!fs.existsSync(CONFIG_DIR)) {
24
24
  fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
@@ -134,7 +134,7 @@ export class TarangAuth {
134
134
  async syncSettings() {
135
135
  const { fetchRemoteSettings, mergeRemoteSettings } = await import('../core/settings-sync.mjs');
136
136
  const creds = this.loadCredentials();
137
- if (!creds.token) throw new Error('Not logged in. Run `orca login` first.');
137
+ if (!creds.token) throw new Error('Not logged in. Run `kepler login` first.');
138
138
 
139
139
  const remote = await fetchRemoteSettings(creds.token);
140
140
  if (!remote) throw new Error('Failed to fetch settings from server.');
@@ -162,7 +162,7 @@ export class TarangAuth {
162
162
 
163
163
  const env = process.env.TARANG_ENV || process.env.NODE_ENV || 'production';
164
164
 
165
- process.stderr.write(`\n${BOLD}Orca Configuration${RESET}\n`);
165
+ process.stderr.write(`\n${BOLD}Kepler Configuration${RESET}\n`);
166
166
  process.stderr.write(`${'─'.repeat(50)}\n`);
167
167
  process.stderr.write(` Auth: ${creds.token ? `${check} logged in` : `${cross} not logged in ${DIM}(/login)${RESET}`}\n`);
168
168
  process.stderr.write(` Environment: ${DIM}${env}${RESET}\n`);
@@ -188,8 +188,8 @@ export class TarangAuth {
188
188
  process.stderr.write(` Last synced: ${DIM}${new Date(raw.last_synced_at).toLocaleString()}${RESET}\n`);
189
189
  }
190
190
 
191
- process.stderr.write(`\n ${DIM}Run ${RESET}${CYAN}orca sync${RESET}${DIM} to sync settings from web.${RESET}\n`);
192
- process.stderr.write(` ${DIM}Run ${RESET}${CYAN}orca configure${RESET}${DIM} to open settings in browser.${RESET}\n`);
191
+ process.stderr.write(`\n ${DIM}Run ${RESET}${CYAN}kepler sync${RESET}${DIM} to sync settings from web.${RESET}\n`);
192
+ process.stderr.write(` ${DIM}Run ${RESET}${CYAN}kepler configure${RESET}${DIM} to open settings in browser.${RESET}\n`);
193
193
  process.stderr.write('\n');
194
194
  }
195
195
 
@@ -202,7 +202,7 @@ export class TarangAuth {
202
202
  * 3. Web checks Supabase session (if none → GitHub OAuth → Supabase)
203
203
  * 4. Web generates CLI token via /api/cli/token
204
204
  * 5. Web redirects browser to CLI callback with token
205
- * 6. CLI receives token, saves to ~/.orca/config.json
205
+ * 6. CLI receives token, saves to ~/.kepler/config.json
206
206
  */
207
207
  async login() {
208
208
  const { resolveWebUrl } = await import('../core/backend-url.mjs');
@@ -27,8 +27,8 @@ export const ENV_SCHEMA = {
27
27
  CLAUDE_CODE_BRIEF: { type: 'boolean', default: false, description: 'Brief output mode' },
28
28
  CLAUDE_CODE_DISABLE_CRON: { type: 'boolean', default: false, description: 'Disable cron tasks' },
29
29
  CLAUDE_CODE_ENABLE_TASKS: { type: 'boolean', default: false, description: 'Enable task system' },
30
- ORCA_STAGNATION_DETECTION: { type: 'boolean', default: false, description: 'Detect consecutive identical tool-call loops' },
31
- ORCA_STAGNATION_THRESHOLD: { type: 'number', default: 3, description: 'Consecutive identical calls before warning' },
30
+ KEPLER_STAGNATION_DETECTION: { type: 'boolean', default: false, description: 'Detect consecutive identical tool-call loops' },
31
+ KEPLER_STAGNATION_THRESHOLD: { type: 'number', default: 3, description: 'Consecutive identical calls before warning' },
32
32
  CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS: { type: 'boolean', default: false, description: 'Enable agent teams' },
33
33
  CLAUDE_CODE_DEBUG: { type: 'boolean', default: false, description: 'Debug mode' },
34
34
  CLAUDE_CODE_DISABLE_TELEMETRY: { type: 'boolean', default: false, description: 'Disable telemetry' },
@@ -118,13 +118,13 @@ function applyEnvOverrides(settings) {
118
118
  if (process.env.CLAUDE_CODE_THINKING === '1') settings.alwaysThinkingEnabled = true;
119
119
  if (process.env.CLAUDE_CODE_DISABLE_CRON === '1') settings.cronEnabled = false;
120
120
  if (process.env.CLAUDE_CODE_ENABLE_TASKS === '1') settings.enableTeams = true;
121
- const stagnationEnabled = process.env.ORCA_STAGNATION_DETECTION;
121
+ const stagnationEnabled = process.env.KEPLER_STAGNATION_DETECTION;
122
122
  if (stagnationEnabled !== undefined) {
123
123
  settings.stagnationDetection = ['1', 'true', 'yes', 'on'].includes(
124
124
  stagnationEnabled.toLowerCase(),
125
125
  );
126
126
  }
127
- const stagnationThreshold = process.env.ORCA_STAGNATION_THRESHOLD;
127
+ const stagnationThreshold = process.env.KEPLER_STAGNATION_THRESHOLD;
128
128
  if (stagnationThreshold) {
129
129
  const n = parseInt(stagnationThreshold, 10);
130
130
  if (Number.isInteger(n) && n >= 2) settings.stagnationThreshold = n;
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Before any file edit, a checkpoint is created containing the
5
5
  * original file content. The /undo command restores the last checkpoint.
6
- * Checkpoints are stored in ~/.orca/projects/{hash}/checkpoints/
6
+ * Checkpoints are stored in ~/.kepler/projects/{hash}/checkpoints/
7
7
  */
8
8
 
9
9
  import fs from 'fs';
@@ -6,9 +6,9 @@
6
6
  * stderr gets minimal progress (optional with --verbose).
7
7
  *
8
8
  * Usage:
9
- * orca --headless "Fix the bug in auth.py"
10
- * orca --headless --timeout 300 --max-cost 2.00 "Refactor the login flow"
11
- * orca --headless --model deepseek/deepseek-chat-v3-0324 "Add tests"
9
+ * kepler --headless "Fix the bug in auth.py"
10
+ * kepler --headless --timeout 300 --max-cost 2.00 "Refactor the login flow"
11
+ * kepler --headless --model deepseek/deepseek-chat-v3-0324 "Add tests"
12
12
  */
13
13
 
14
14
  import { TarangStreamClient } from './stream-client.mjs';
@@ -42,7 +42,7 @@ export async function runHeadless({ instruction, model, timeout = 300, maxCost,
42
42
  const auth = new TarangAuth();
43
43
  const creds = auth.loadCredentials();
44
44
  if (!creds.token) {
45
- emit({ type: 'error', error: 'Not logged in. Run: orca login' });
45
+ emit({ type: 'error', error: 'Not logged in. Run: kepler login' });
46
46
  process.exit(1);
47
47
  }
48
48
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * JSONL Writer — writes cc-lens compatible session transcripts to ~/.orca/.
2
+ * JSONL Writer — writes cc-lens compatible session transcripts to ~/.kepler/.
3
3
  *
4
4
  * Format mirrors Claude Code's ~/.claude/ JSONL structure so that
5
5
  * cc-lens (CLAUDE_CONFIG_DIR=~/.orca npx cc-lens) can read Orca sessions.
@@ -17,13 +17,13 @@ import * as os from 'node:os';
17
17
  import { randomUUID } from 'node:crypto';
18
18
  import * as childProcessModule from 'node:child_process';
19
19
 
20
- const ORCA_DIR = process.env.ORCA_HOME || path.join(os.homedir(), '.orca');
20
+ const KEPLER_DIR = process.env.KEPLER_HOME || path.join(os.homedir(), '.kepler');
21
21
  const FLUSH_INTERVAL_MS = 500;
22
22
 
23
23
  /**
24
24
  * Sanitize a cwd path into a project slug for the directory name.
25
25
  * /Users/sree/Sites/myproject → -Users-sree-Sites-myproject
26
- * Mirrors the Claude Code / orca-cli convention.
26
+ * Mirrors the Claude Code / kepler-cli convention.
27
27
  */
28
28
  function sanitizePath(p) {
29
29
  return p.replace(/\//g, '-').replace(/^-/, '-');
@@ -50,7 +50,7 @@ export class JsonlWriter {
50
50
  this.version = version;
51
51
  this.sessionId = null; // set by setSessionId() when backend assigns it
52
52
  this.slug = sanitizePath(cwd);
53
- this.projectDir = path.join(ORCA_DIR, 'projects', this.slug);
53
+ this.projectDir = path.join(KEPLER_DIR, 'projects', this.slug);
54
54
 
55
55
  // UUID chain for parent linking (cc-lens replay)
56
56
  this.lastUuid = null;
@@ -238,7 +238,7 @@ export class JsonlWriter {
238
238
  }
239
239
 
240
240
  /**
241
- * Write a prompt entry to ~/.orca/history.jsonl.
241
+ * Write a prompt entry to ~/.kepler/history.jsonl.
242
242
  */
243
243
  writeHistory(prompt) {
244
244
  const entry = {
@@ -248,7 +248,7 @@ export class JsonlWriter {
248
248
  project: this.cwd,
249
249
  sessionId: this.sessionId,
250
250
  };
251
- const historyPath = path.join(ORCA_DIR, 'history.jsonl');
251
+ const historyPath = path.join(KEPLER_DIR, 'history.jsonl');
252
252
  fs.promises.appendFile(historyPath, JSON.stringify(entry) + '\n', { mode: 0o600 })
253
253
  .catch(() => {}); // best effort
254
254
  }
@@ -327,7 +327,7 @@ export class JsonlWriter {
327
327
  fs.mkdirSync(this.projectDir, { recursive: true, mode: 0o700 });
328
328
  } catch { /* ignore */ }
329
329
  try {
330
- fs.mkdirSync(path.join(ORCA_DIR, 'projects'), { recursive: true, mode: 0o700 });
330
+ fs.mkdirSync(path.join(KEPLER_DIR, 'projects'), { recursive: true, mode: 0o700 });
331
331
  } catch { /* ignore */ }
332
332
  }
333
333
 
@@ -402,7 +402,7 @@ export class LocalAgent {
402
402
  }
403
403
 
404
404
  const parts = [
405
- 'You are Orca, an AI coding agent running in local mode.',
405
+ 'You are Kepler, an AI coding agent running in local mode.',
406
406
  'You have access to tools for reading, writing, and executing code.',
407
407
  'Use tools to accomplish the user\'s request. Be concise and direct.',
408
408
  ];
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Local Store Reader — scans ~/.orca/ JSONL files for historical stats.
2
+ * Local Store Reader — scans ~/.kepler/ JSONL files for historical stats.
3
3
  *
4
4
  * Provides read helpers for CLI commands (/stats, /history, /tokens, /tools, /sessions).
5
5
  * All data comes from local JSONL files — no cloud dependency.
@@ -10,8 +10,8 @@ import * as path from 'node:path';
10
10
  import * as os from 'node:os';
11
11
  import * as readline from 'node:readline';
12
12
 
13
- const ORCA_DIR = process.env.ORCA_HOME || path.join(os.homedir(), '.orca');
14
- const PROJECTS_DIR = path.join(ORCA_DIR, 'projects');
13
+ const KEPLER_DIR = process.env.KEPLER_HOME || path.join(os.homedir(), '.kepler');
14
+ const PROJECTS_DIR = path.join(KEPLER_DIR, 'projects');
15
15
 
16
16
  function normalizeBlock(block) {
17
17
  if (!block || typeof block !== 'object') {
@@ -302,7 +302,7 @@ export async function getModelBreakdown(days = 30) {
302
302
  * @param {number} n — max entries to return (most recent first)
303
303
  */
304
304
  export function getHistory(n = 50) {
305
- const historyPath = path.join(ORCA_DIR, 'history.jsonl');
305
+ const historyPath = path.join(KEPLER_DIR, 'history.jsonl');
306
306
  try {
307
307
  const content = fs.readFileSync(historyPath, 'utf-8');
308
308
  const lines = content.trim().split('\n').filter(Boolean);
@@ -318,8 +318,8 @@ export function getHistory(n = 50) {
318
318
 
319
319
  export function getStorePaths() {
320
320
  return {
321
- orcaDir: ORCA_DIR,
321
+ keplerDir: KEPLER_DIR,
322
322
  projectsDir: PROJECTS_DIR,
323
- historyPath: path.join(ORCA_DIR, 'history.jsonl'),
323
+ historyPath: path.join(KEPLER_DIR, 'history.jsonl'),
324
324
  };
325
325
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
- * Orca Paths — centralized path resolution for all Orca data.
2
+ * Kepler Paths — centralized path resolution for all Kepler data.
3
3
  *
4
- * Everything lives under ~/.orca/:
5
- * ~/.orca/
4
+ * Everything lives under ~/.kepler/:
5
+ * ~/.kepler/
6
6
  * config.json — auth credentials + settings
7
7
  * history.jsonl — prompt history
8
8
  * hooks.json — global hooks
@@ -22,7 +22,7 @@ import * as path from 'node:path';
22
22
  import * as os from 'node:os';
23
23
  import * as crypto from 'node:crypto';
24
24
 
25
- const ORCA_HOME = process.env.ORCA_HOME || path.join(os.homedir(), '.orca');
25
+ const KEPLER_HOME = process.env.KEPLER_HOME || process.env.ORCA_HOME || path.join(os.homedir(), '.kepler');
26
26
 
27
27
  /**
28
28
  * Hash a project path to a short directory name.
@@ -42,57 +42,60 @@ export function projectHash(projectDir) {
42
42
  .slice(0, 16);
43
43
  }
44
44
 
45
- /** Root ~/.orca/ directory. */
46
- export function orcaHome() {
47
- return ORCA_HOME;
45
+ /** Root ~/.kepler/ directory. */
46
+ export function keplerHome() {
47
+ return KEPLER_HOME;
48
48
  }
49
49
 
50
- /** ~/.orca/projects/{hash}/ for a given project path. */
50
+ /** @deprecated Use keplerHome() */
51
+ export const orcaHome = keplerHome;
52
+
53
+ /** ~/.kepler/projects/{hash}/ for a given project path. */
51
54
  export function projectDir(projectPath) {
52
- return path.join(ORCA_HOME, 'projects', projectHash(projectPath));
55
+ return path.join(KEPLER_HOME, 'projects', projectHash(projectPath));
53
56
  }
54
57
 
55
- /** ~/.orca/projects/{hash}/index/ — BM25 search index. */
58
+ /** ~/.kepler/projects/{hash}/index/ — BM25 search index. */
56
59
  export function indexDir(projectPath) {
57
60
  return path.join(projectDir(projectPath), 'index');
58
61
  }
59
62
 
60
- /** ~/.orca/projects/{hash}/checkpoints/ — file undo. */
63
+ /** ~/.kepler/projects/{hash}/checkpoints/ — file undo. */
61
64
  export function checkpointsDir(projectPath) {
62
65
  return path.join(projectDir(projectPath), 'checkpoints');
63
66
  }
64
67
 
65
- /** ~/.orca/projects/{hash}/state.json — current session. */
68
+ /** ~/.kepler/projects/{hash}/state.json — current session. */
66
69
  export function statePath(projectPath) {
67
70
  return path.join(projectDir(projectPath), 'state.json');
68
71
  }
69
72
 
70
- /** ~/.orca/projects/{hash}/sessions/ — session archive. */
73
+ /** ~/.kepler/projects/{hash}/sessions/ — session archive. */
71
74
  export function sessionsDir(projectPath) {
72
75
  return path.join(projectDir(projectPath), 'sessions');
73
76
  }
74
77
 
75
- /** ~/.orca/projects/{hash}/hooks.json — project hooks. */
78
+ /** ~/.kepler/projects/{hash}/hooks.json — project hooks. */
76
79
  export function projectHooksPath(projectPath) {
77
80
  return path.join(projectDir(projectPath), 'hooks.json');
78
81
  }
79
82
 
80
- /** ~/.orca/conversations/ — central conversation storage. */
83
+ /** ~/.kepler/conversations/ — central conversation storage. */
81
84
  export function conversationsDir() {
82
- return path.join(ORCA_HOME, 'conversations');
85
+ return path.join(KEPLER_HOME, 'conversations');
83
86
  }
84
87
 
85
- /** ~/.orca/conversations/{sessionId}.jsonl */
88
+ /** ~/.kepler/conversations/{sessionId}.jsonl */
86
89
  export function conversationPath(sessionId) {
87
90
  return path.join(conversationsDir(), `${sessionId}.jsonl`);
88
91
  }
89
92
 
90
- /** ~/.orca/hooks.json — global hooks. */
93
+ /** ~/.kepler/hooks.json — global hooks. */
91
94
  export function globalHooksPath() {
92
- return path.join(ORCA_HOME, 'hooks.json');
95
+ return path.join(KEPLER_HOME, 'hooks.json');
93
96
  }
94
97
 
95
- /** ~/.orca/history.jsonl — prompt history. */
98
+ /** ~/.kepler/history.jsonl — prompt history. */
96
99
  export function historyPath() {
97
- return path.join(ORCA_HOME, 'history.jsonl');
100
+ return path.join(KEPLER_HOME, 'history.jsonl');
98
101
  }
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Session Manager — persist session state, history, and conversation messages.
3
3
  *
4
- * All data lives under ~/.orca/:
5
- * ~/.orca/
4
+ * All data lives under ~/.kepler/:
5
+ * ~/.kepler/
6
6
  * projects/{hash}/
7
7
  * state.json — current session metadata
8
8
  * sessions/ — session metadata archive
@@ -29,7 +29,7 @@ const MAX_SESSIONS = 100;
29
29
  export class SessionManager {
30
30
  constructor(projectPath = process.cwd()) {
31
31
  this.projectPath = projectPath;
32
- this.projectOrcaDir = getProjectDir(projectPath);
32
+ this.projectKeplerDir = getProjectDir(projectPath);
33
33
  this.statePath = getStatePath(projectPath);
34
34
  this.sessionsDir = getSessionsDir(projectPath);
35
35
  this.conversationsDir = getConversationsDir();
@@ -37,7 +37,7 @@ export class SessionManager {
37
37
  }
38
38
 
39
39
  _ensureDirs() {
40
- fs.mkdirSync(this.projectOrcaDir, { recursive: true });
40
+ fs.mkdirSync(this.projectKeplerDir, { recursive: true });
41
41
  fs.mkdirSync(this.sessionsDir, { recursive: true });
42
42
  fs.mkdirSync(this.conversationsDir, { recursive: true });
43
43
  }
@@ -2,14 +2,14 @@
2
2
  * Settings Sync — fetch user settings from Tarang web and cache locally.
3
3
  *
4
4
  * Syncs: gateway_type, model preferences, configured providers.
5
- * Cached in ~/.orca/config.json alongside auth token.
5
+ * Cached in ~/.kepler/config.json alongside auth token.
6
6
  */
7
7
 
8
8
  import { resolveWebUrl } from './backend-url.mjs';
9
9
 
10
10
  /**
11
11
  * Fetch user settings from the web API using CLI token.
12
- * @param {string} token - CLI auth token (orca_xxx)
12
+ * @param {string} token - CLI auth token (kepler_xxx)
13
13
  * @returns {Promise<Object|null>} Settings object or null on failure
14
14
  */
15
15
  export async function fetchRemoteSettings(token) {
@@ -29,7 +29,7 @@ export async function fetchRemoteSettings(token) {
29
29
 
30
30
  if (!resp.ok) {
31
31
  if (resp.status === 401) {
32
- process.stderr.write('\x1b[33mSettings sync: token expired or invalid. Run `orca login` to re-authenticate.\x1b[0m\n');
32
+ process.stderr.write('\x1b[33mSettings sync: token expired or invalid. Run `kepler login` to re-authenticate.\x1b[0m\n');
33
33
  }
34
34
  return null;
35
35
  }
@@ -44,7 +44,7 @@ export async function fetchRemoteSettings(token) {
44
44
  /**
45
45
  * Merge remote settings into local config.
46
46
  * Remote settings override local only for fields that are set.
47
- * @param {Object} localConfig - Current ~/.orca/config.json content
47
+ * @param {Object} localConfig - Current ~/.kepler/config.json content
48
48
  * @param {Object} remote - Settings from fetchRemoteSettings()
49
49
  * @returns {Object} Merged config to save
50
50
  */
@@ -106,7 +106,7 @@ export class TarangStreamClient {
106
106
  }
107
107
 
108
108
  if (response.status === 401) {
109
- yield { type: EVENT_TYPES.ERROR, data: { message: 'Authentication failed. Run `orca login` to re-authenticate.', fatal: true } };
109
+ yield { type: EVENT_TYPES.ERROR, data: { message: 'Authentication failed. Run `kepler login` to re-authenticate.', fatal: true } };
110
110
  return;
111
111
  }
112
112
  if (!response.ok) {
package/src/index.mjs CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * @devtarang/orca v1.0.1 — Orca AI Coding Agent CLI
3
+ * @axplusb/kepler v1.0.1 — Kepler AI Coding Agent CLI
4
4
  *
5
5
  * Phase 3: Hybrid local/remote/auto + advanced features.
6
6
  */
7
7
 
8
- // Load .env file from cwd or ~/.orca/.env
8
+ // Load .env file from cwd or ~/.kepler/.env
9
9
  import { readFileSync, existsSync } from 'node:fs';
10
10
  import { join } from 'node:path';
11
11
  import { homedir } from 'node:os';
12
12
 
13
- for (const envPath of [join(process.cwd(), '.env'), join(homedir(), '.orca', '.env')]) {
13
+ for (const envPath of [join(process.cwd(), '.env'), join(homedir(), '.kepler', '.env')]) {
14
14
  if (existsSync(envPath)) {
15
15
  for (const line of readFileSync(envPath, 'utf-8').split('\n')) {
16
16
  const match = line.match(/^\s*([\w]+)\s*=\s*(.+?)\s*$/);
@@ -117,12 +117,12 @@ function printUsage() {
117
117
  const B = '\x1b[1m', C = '\x1b[36m', D = '\x1b[2m', G = '\x1b[32m', R = '\x1b[0m';
118
118
 
119
119
  process.stderr.write(`${B}USAGE${R}\n`);
120
- process.stderr.write(` ${C}orca "instruction"${R} Execute instruction\n`);
121
- process.stderr.write(` ${C}orca${R} Interactive mode (REPL)\n`);
122
- process.stderr.write(` ${C}orca login${R} Authenticate via GitHub OAuth\n`);
123
- process.stderr.write(` ${C}orca configure${R} Open settings in browser\n`);
124
- process.stderr.write(` ${C}orca config --show${R} Display local configuration\n`);
125
- process.stderr.write(` ${C}orca resume${R} Resume a paused session\n`);
120
+ process.stderr.write(` ${C}kepler "instruction"${R} Execute instruction\n`);
121
+ process.stderr.write(` ${C}kepler${R} Interactive mode (REPL)\n`);
122
+ process.stderr.write(` ${C}kepler login${R} Authenticate via GitHub OAuth\n`);
123
+ process.stderr.write(` ${C}kepler configure${R} Open settings in browser\n`);
124
+ process.stderr.write(` ${C}kepler config --show${R} Display local configuration\n`);
125
+ process.stderr.write(` ${C}kepler resume${R} Resume a paused session\n`);
126
126
  process.stderr.write('\n');
127
127
  process.stderr.write(`${B}MODE FLAGS${R}\n`);
128
128
  process.stderr.write(` ${G}--local${R} Direct LLM API ${D}(<100ms, offline)${R}\n`);
@@ -133,7 +133,7 @@ function printUsage() {
133
133
  process.stderr.write(`${B}MODEL FLAGS${R}\n`);
134
134
  process.stderr.write(` ${G}--system-prompt <text>${R} Override system prompt\n`);
135
135
  process.stderr.write(` ${G}--max-turns <n>${R} Maximum conversation turns\n`);
136
- process.stderr.write(` ${D}Models are configured via: orca configure${R}\n`);
136
+ process.stderr.write(` ${D}Models are configured via: kepler configure${R}\n`);
137
137
  process.stderr.write('\n');
138
138
  process.stderr.write(`${B}PERMISSION FLAGS${R}\n`);
139
139
  process.stderr.write(` ${G}--yes, -y${R} Auto-approve all operations\n`);
@@ -187,7 +187,7 @@ import { startTerminalRepl } from './terminal/repl.mjs';
187
187
 
188
188
  async function main() {
189
189
  const args = parseArgs(process.argv.slice(2));
190
- if (args.version) { console.log(`@devtarang/orca ${VERSION}`); process.exit(0); }
190
+ if (args.version) { console.log(`@axplusb/kepler ${VERSION}`); process.exit(0); }
191
191
  if (args.help) { printUsage(); process.exit(0); }
192
192
 
193
193
  const auth = new TarangAuth();
@@ -219,7 +219,7 @@ async function main() {
219
219
  if (remote.models?.reasoning) process.stderr.write(`\x1b[32m✓ Coding:\x1b[0m ${remote.models.reasoning}\n`);
220
220
  if (remote.models?.local) process.stderr.write(`\x1b[32m✓ Local:\x1b[0m ${remote.models.local}\n`);
221
221
  if (remote.configured_providers?.length) process.stderr.write(`\x1b[32m✓ Providers:\x1b[0m ${remote.configured_providers.join(', ')}\n`);
222
- process.stderr.write('\n\x1b[32m✓ Settings saved to ~/.orca/config.json\x1b[0m\n');
222
+ process.stderr.write('\n\x1b[32m✓ Settings saved to ~/.kepler/config.json\x1b[0m\n');
223
223
  } catch (err) {
224
224
  process.stderr.write(`\x1b[31m✗ ${err.message}\x1b[0m\n`);
225
225
  }
@@ -72,12 +72,12 @@ function extractPrompt(entry) {
72
72
 
73
73
  export function formatSessionsReport(sessions, limit) {
74
74
  if (!sessions.length) {
75
- return 'No local sessions found in ~/.orca/projects.\n';
75
+ return 'No local sessions found in ~/.kepler/projects.\n';
76
76
  }
77
77
 
78
78
  const lines = [];
79
- lines.push(`ORCA SESSIONS ${sessions.length} shown`);
80
- lines.push(`Recent local transcripts from ~/.orca/projects (limit ${limit})`);
79
+ lines.push(`KEPLER SESSIONS ${sessions.length} shown`);
80
+ lines.push(`Recent local transcripts from ~/.kepler/projects (limit ${limit})`);
81
81
  lines.push('');
82
82
 
83
83
  for (const session of sessions) {
@@ -96,8 +96,8 @@ export function formatSessionsReport(sessions, limit) {
96
96
 
97
97
  export function formatStatsReport(stats, tools, models, days, paths) {
98
98
  const lines = [];
99
- lines.push(`ORCA STATS ${relativeDaysLabel(days)}`);
100
- lines.push(`Store: ${paths.orcaDir}`);
99
+ lines.push(`KEPLER STATS ${relativeDaysLabel(days)}`);
100
+ lines.push(`Store: ${paths.keplerDir}`);
101
101
  lines.push('');
102
102
  lines.push(`Sessions ${formatNumber(stats.totalSessions)}`);
103
103
  lines.push(`Messages ${formatNumber(stats.totalUserMessages + stats.totalAssistantMessages)} (${formatNumber(stats.totalUserMessages)} user, ${formatNumber(stats.totalAssistantMessages)} assistant)`);
@@ -131,12 +131,12 @@ export function formatStatsReport(stats, tools, models, days, paths) {
131
131
 
132
132
  export function formatHistoryReport(entries, limit) {
133
133
  if (!entries.length) {
134
- return 'No local prompt history found in ~/.orca/history.jsonl.\n';
134
+ return 'No local prompt history found in ~/.kepler/history.jsonl.\n';
135
135
  }
136
136
 
137
137
  const lines = [];
138
- lines.push(`ORCA HISTORY ${entries.length} shown`);
139
- lines.push(`Recent prompts from ~/.orca/history.jsonl (limit ${limit})`);
138
+ lines.push(`KEPLER HISTORY ${entries.length} shown`);
139
+ lines.push(`Recent prompts from ~/.kepler/history.jsonl (limit ${limit})`);
140
140
  lines.push('');
141
141
 
142
142
  for (const entry of entries) {
@@ -202,7 +202,7 @@ export async function runHistoryCommand(args = []) {
202
202
  process.stdout.write(formatHistoryReport(history, limit));
203
203
  }
204
204
 
205
- // Dashboard removed — now using Orca Pulse (pulse/cli.js)
205
+ // Dashboard removed — now using Kepler Pulse (pulse/cli.js)
206
206
 
207
207
  export async function _runDashboardCommand_REMOVED() { /* see pulse/cli.js */ }
208
208
 
@@ -272,8 +272,8 @@ export async function _OLD_runDashboardCommand(args = []) {
272
272
  const actualPort = typeof address === 'object' && address ? address.port : requestedPort;
273
273
  const url = `http://${host}:${actualPort}`;
274
274
 
275
- process.stderr.write(`\x1b[36mOrca dashboard\x1b[0m ${url}\n`);
276
- process.stderr.write(`\x1b[2mReading local analytics from ${getStorePaths().orcaDir}\x1b[0m\n`);
275
+ process.stderr.write(`\x1b[36mKepler dashboard\x1b[0m ${url}\n`);
276
+ process.stderr.write(`\x1b[2mReading local analytics from ${getStorePaths().keplerDir}\x1b[0m\n`);
277
277
  process.stderr.write(`\x1b[2mPress Ctrl+C to stop the dashboard server.\x1b[0m\n`);
278
278
 
279
279
  if (shouldOpen) {
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /**
3
- * Orca CLI — ANSI Terminal UI.
3
+ * Kepler CLI — ANSI Terminal UI.
4
4
  * Zero React. Zero Ink. Zero flickering.
5
5
  */
6
6
 
@@ -19,7 +19,7 @@ const subcommandArgs = process.argv.slice(3);
19
19
 
20
20
  async function main() {
21
21
  if (subcommand === 'dashboard') {
22
- // Launch Orca Pulse Next.js dashboard
22
+ // Launch Kepler Pulse Next.js dashboard
23
23
  const { spawn } = await import('node:child_process');
24
24
  const { fileURLToPath } = await import('node:url');
25
25
  const path = await import('node:path');
@@ -76,28 +76,28 @@ async function main() {
76
76
  const { createRequire } = await import('node:module');
77
77
  const require = createRequire(import.meta.url);
78
78
  const { version } = require('../../package.json');
79
- process.stdout.write(`orca v${version}\n`);
79
+ process.stdout.write(`kepler v${version}\n`);
80
80
  return;
81
81
  }
82
82
 
83
83
  if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') {
84
84
  process.stderr.write(`
85
- \x1b[1m\x1b[36morca\x1b[0m — Orchestration of Composable Agents
85
+ \x1b[1m\x1b[36mkepler\x1b[0m — AI Coding Agent — codekepler.ai
86
86
 
87
87
  \x1b[1mUsage:\x1b[0m
88
- orca Start interactive REPL
89
- orca "instruction" Run a single instruction
90
- orca --headless -p "x" Non-interactive: auto-approve, JSONL output
91
- orca --resume Resume last conversation
92
- orca dashboard Open Orca Pulse analytics dashboard
93
- orca login Sign in via browser
94
- orca logout Sign out and clear credentials
95
- orca version Show version
88
+ kepler Start interactive REPL
89
+ kepler "instruction" Run a single instruction
90
+ kepler --headless -p "x" Non-interactive: auto-approve, JSONL output
91
+ kepler --resume Resume last conversation
92
+ kepler dashboard Open Kepler Pulse analytics dashboard
93
+ kepler login Sign in via browser
94
+ kepler logout Sign out and clear credentials
95
+ kepler version Show version
96
96
 
97
97
  \x1b[1mAnalytics:\x1b[0m
98
- orca sessions List recent local sessions
99
- orca stats Show aggregate local session stats
100
- orca history Show recent prompt history
98
+ kepler sessions List recent local sessions
99
+ kepler stats Show aggregate local session stats
100
+ kepler history Show recent prompt history
101
101
 
102
102
  \x1b[1mREPL Commands:\x1b[0m
103
103
  /help Show available commands
@@ -121,7 +121,7 @@ async function main() {
121
121
  TARANG_ENV Set backend (local, development, production)
122
122
  ANTHROPIC_API_KEY Direct Anthropic API key
123
123
  OPENROUTER_API_KEY OpenRouter API key
124
- ORCA_CONFIG_DIR Override config directory (default: ~/.orca)
124
+ KEPLER_CONFIG_DIR Override config directory (default: ~/.kepler)
125
125
 
126
126
  \x1b[2mDocs: https://devtarang.ai/docs\x1b[0m
127
127
  `);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Orca REPL — Full Claude-like terminal UX.
2
+ * Kepler REPL — Full Claude-like terminal UX.
3
3
  *
4
4
  * Pure ANSI. No React. No Ink. No flickering.
5
5
  *
@@ -148,12 +148,12 @@ function printBanner(auth) {
148
148
  //
149
149
  // ✓ 3 tools · 1.2s · $0.02 ctx 21% · 42k tok
150
150
  // ╶─────────────────────────────────────────────────────────────────╴
151
- // orca
151
+ // kepler
152
152
  //
153
153
  // Layout on first prompt (no stats yet):
154
154
  //
155
155
  // ╶─────────────────────────────────────────────────────────────────╴
156
- // orca
156
+ // kepler
157
157
 
158
158
  /**
159
159
  * Build the contextual status strip — compact, one line.
@@ -765,7 +765,7 @@ async function handleCommand(input, ctx) {
765
765
 
766
766
  switch (cmd) {
767
767
  case '/help':
768
- process.stderr.write(`\n ${c.bold('Orca Commands')}\n`);
768
+ process.stderr.write(`\n ${c.bold('Kepler Commands')}\n`);
769
769
  process.stderr.write(` ${c.gray('─'.repeat(44))}\n`);
770
770
  for (const [name, desc] of Object.entries(COMMANDS)) {
771
771
  process.stderr.write(` ${c.brand(name.padEnd(14))} ${desc}\n`);
@@ -937,7 +937,7 @@ async function handleCommand(input, ctx) {
937
937
  process.stderr.write(`\n ${c.bold('Conversation')} (${session.history.length} messages)\n`);
938
938
  process.stderr.write(` ${c.gray('─'.repeat(40))}\n`);
939
939
  for (const msg of session.history.slice(-20)) {
940
- const role = msg.role === 'user' ? c.white('You') : c.brand('Orca');
940
+ const role = msg.role === 'user' ? c.white('You') : c.brand('Kepler');
941
941
  process.stderr.write(` ${role}: ${msg.content.slice(0, 80)}${msg.content.length > 80 ? '...' : ''}\n`);
942
942
  }
943
943
  process.stderr.write('\n');
@@ -1016,7 +1016,7 @@ async function handleCommand(input, ctx) {
1016
1016
  const instr = s.instruction ? s.instruction.slice(0, 40) : '(no instruction)';
1017
1017
  process.stderr.write(` ${c.brand(s.sessionId)} ${c.dim(date)} ${s.messageCount} msgs ${c.dim(instr)}\n`);
1018
1018
  }
1019
- process.stderr.write(`\n ${c.dim('Resume with:')} orca --resume <sessionId>\n`);
1019
+ process.stderr.write(`\n ${c.dim('Resume with:')} kepler --resume <sessionId>\n`);
1020
1020
  return;
1021
1021
  }
1022
1022
 
@@ -1123,7 +1123,7 @@ async function handleCommand(input, ctx) {
1123
1123
  case '/logout': {
1124
1124
  const success = ctx.auth.logout();
1125
1125
  if (success) {
1126
- process.stderr.write(` ${c.green('✓')} ${c.dim('Signed out. Credentials cleared from ~/.orca/config.json')}\n`);
1126
+ process.stderr.write(` ${c.green('✓')} ${c.dim('Signed out. Credentials cleared from ~/.kepler/config.json')}\n`);
1127
1127
  process.stderr.write(` ${c.dim('Run /login to sign in again.')}\n`);
1128
1128
  } else {
1129
1129
  process.stderr.write(` ${c.yellow('!')} ${c.dim('No credentials to clear.')}\n`);
@@ -1172,11 +1172,11 @@ export async function startTerminalRepl() {
1172
1172
  const skipPerms = cliArgs.freeswim;
1173
1173
  const approval = new ApprovalManager({ autoApprove: skipPerms });
1174
1174
 
1175
- // Session manager — persists conversation messages to .orca/conversations/
1175
+ // Session manager — persists conversation messages to .kepler/conversations/
1176
1176
  const sessionMgr = new SessionManager(safeCwd());
1177
1177
  _sessionMgr = sessionMgr; // expose to renderEvent
1178
1178
 
1179
- // Local JSONL writer — writes cc-lens compatible session data to ~/.orca/
1179
+ // Local JSONL writer — writes cc-lens compatible session data to ~/.kepler/
1180
1180
  const jsonlWriter = new JsonlWriter(safeCwd(), VERSION);
1181
1181
 
1182
1182
  // Persistent stream client — session_id captured from backend on first turn
@@ -1261,7 +1261,7 @@ export async function startTerminalRepl() {
1261
1261
 
1262
1262
  process.stderr.write(`\n ${c.dim('Press')} ${c.brand('Enter')} ${c.dim('to start, or type a prompt below.')}\n`);
1263
1263
 
1264
- const PROMPT = `${c.brand('orca')} ${c.dim('›')} `;
1264
+ const PROMPT = `${c.brand('kepler')} ${c.dim('›')} `;
1265
1265
 
1266
1266
  const rl = readline.createInterface({
1267
1267
  input: process.stdin,
@@ -1326,8 +1326,8 @@ export async function startTerminalRepl() {
1326
1326
  return;
1327
1327
  }
1328
1328
 
1329
- // Orca response label
1330
- process.stderr.write(`\n${c.bold(c.brand('orca'))}\n`);
1329
+ // Kepler response label
1330
+ process.stderr.write(`\n${c.bold(c.brand('kepler'))}\n`);
1331
1331
 
1332
1332
  // Create or reuse stream client — sessionId persists across turns
1333
1333
  if (!streamClient || streamClient.baseUrl !== creds.backendUrl || streamClient.token !== creds.token) {
@@ -87,10 +87,10 @@ export const AgentTool = {
87
87
  settings: {
88
88
  stream: false,
89
89
  stagnationDetection: !['0', 'false', 'no', 'off'].includes(
90
- (process.env.ORCA_STAGNATION_DETECTION ?? '0').toLowerCase(),
90
+ (process.env.KEPLER_STAGNATION_DETECTION ?? '0').toLowerCase(),
91
91
  ),
92
92
  stagnationThreshold: Number.parseInt(
93
- process.env.ORCA_STAGNATION_THRESHOLD
93
+ process.env.KEPLER_STAGNATION_THRESHOLD
94
94
  ?? '3',
95
95
  10,
96
96
  ),
package/src/ui/banner.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Banner & Branding — Tarang CLI startup display.
2
+ * Banner & Branding — Kepler CLI startup display.
3
3
  */
4
4
 
5
5
  import { execSync } from 'node:child_process';
@@ -17,13 +17,13 @@ const BLUE = '\x1b[34m';
17
17
  const BOLD_GREEN = '\x1b[1;32m';
18
18
  const BOLD_CYAN = '\x1b[1;36m';
19
19
 
20
- const BANNER_ORCA = [
21
- ' ██████╗ ██████╗ ██████╗ █████╗ ',
22
- '██╔═══██╗ ██╔══██╗ ██╔════╝ ██╔══██╗',
23
- '██║ ██║ ██████╔╝ ██║ ███████║',
24
- '██║ ██║ ██╔══██╗ ██║ ██╔══██║',
25
- '╚██████╔╝ ██║ ██║ ╚██████╗ ██║ ██║',
26
- ' ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝',
20
+ const BANNER_KEPLER = [
21
+ '██╗ ██╗ ███████╗ ██████╗ ██╗ ███████╗ ██████╗ ',
22
+ '██║ ██╔╝ ██╔════╝ ██╔══██╗ ██║ ██╔════╝ ██╔══██╗',
23
+ '█████╔╝ █████╗ ██████╔╝ ██║ █████╗ ██████╔╝',
24
+ '██╔═██╗ ██╔══╝ ██╔═══╝ ██║ ██╔══╝ ██╔══██╗',
25
+ '██║ ██╗ ███████╗ ██║ ███████╗ ███████╗ ██║ ██║',
26
+ '╚═╝ ╚═╝ ╚══════╝ ╚═╝ ╚══════╝ ╚══════╝ ╚═╝ ╚═╝',
27
27
  ];
28
28
 
29
29
  /**
@@ -31,10 +31,10 @@ const BANNER_ORCA = [
31
31
  */
32
32
  export function printBanner() {
33
33
  process.stderr.write('\n');
34
- for (const line of BANNER_ORCA) {
34
+ for (const line of BANNER_KEPLER) {
35
35
  process.stderr.write(` ${BOLD_CYAN}${line}${RESET}\n`);
36
36
  }
37
- process.stderr.write(` ${DIM}Orchestration of Composable Agents${RESET}\n`);
37
+ process.stderr.write(` ${DIM}AI Coding Agent — codekepler.ai${RESET}\n`);
38
38
  process.stderr.write('\n');
39
39
  }
40
40
 
@@ -105,7 +105,7 @@ export function printStyledConfig(creds) {
105
105
  return `${check} ${val.slice(0, 6)}...${val.slice(-4)}`;
106
106
  };
107
107
 
108
- process.stderr.write(`\n${BOLD}Orca Configuration${RESET} ${DIM}(~/.orca/config.json)${RESET}\n`);
108
+ process.stderr.write(`\n${BOLD}Kepler Configuration${RESET} ${DIM}(~/.kepler/config.json)${RESET}\n`);
109
109
  process.stderr.write(`${'─'.repeat(50)}\n`);
110
110
  process.stderr.write(` Token: ${mask(creds.token)}\n`);
111
111
  process.stderr.write(` OpenRouter: ${mask(creds.openRouterKey)}\n`);
@@ -167,7 +167,7 @@ export function getLoginSuccessHTML() {
167
167
  <html>
168
168
  <head>
169
169
  <meta charset="utf-8">
170
- <title>Orca - Login Successful</title>
170
+ <title>Kepler - Login Successful</title>
171
171
  <style>
172
172
  body {
173
173
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
@@ -189,7 +189,7 @@ export function getLoginSuccessHTML() {
189
189
  margin-bottom: 8px;
190
190
  }
191
191
  .dev { color: #3fb950; }
192
- .orca { color: #58a6ff; }
192
+ .kepler { color: #58a6ff; }
193
193
  .check {
194
194
  font-size: 64px;
195
195
  color: #3fb950;
@@ -222,14 +222,14 @@ export function getLoginSuccessHTML() {
222
222
  <body>
223
223
  <div class="container">
224
224
  <div class="logo">
225
- <span class="orca">ORCA</span>
225
+ <span class="kepler">KEPLER</span>
226
226
  </div>
227
227
  <div class="check">&#10003;</div>
228
228
  <h1>Login Successful!</h1>
229
229
  <p>You can close this tab and return to your terminal.</p>
230
230
  <div class="hint">
231
231
  <p>Next step: set your API key</p>
232
- <code>orca config --openrouter-key YOUR_KEY</code>
232
+ <code>kepler config --openrouter-key YOUR_KEY</code>
233
233
  </div>
234
234
  </div>
235
235
  </body>
@@ -41,7 +41,7 @@ function cmdHelp(ctx) {
41
41
  const BOLD = '\x1b[1m', CYAN = '\x1b[36m', DIM = '\x1b[2m', GREEN = '\x1b[32m', BLUE = '\x1b[34m', RESET = '\x1b[0m';
42
42
 
43
43
  process.stderr.write(`\n${BLUE}┌──────────────────────────────────────────────┐${RESET}\n`);
44
- process.stderr.write(`${BLUE}│${RESET} ${BOLD}Orca Help${RESET} ${BLUE}│${RESET}\n`);
44
+ process.stderr.write(`${BLUE}│${RESET} ${BOLD}Kepler Help${RESET} ${BLUE}│${RESET}\n`);
45
45
  process.stderr.write(`${BLUE}├──────────────────────────────────────────────┤${RESET}\n`);
46
46
  process.stderr.write(`${BLUE}│${RESET} ${BLUE}│${RESET}\n`);
47
47
  process.stderr.write(`${BLUE}│${RESET} ${BOLD}Commands:${RESET} ${BLUE}│${RESET}\n`);
@@ -94,7 +94,7 @@ function cmdClear(ctx) {
94
94
  }
95
95
 
96
96
  function cmdSessions() {
97
- const sessDir = path.join(process.cwd(), '.orca', 'sessions');
97
+ const sessDir = path.join(process.cwd(), '.kepler', 'sessions');
98
98
  if (!fs.existsSync(sessDir)) {
99
99
  process.stderr.write('No sessions found.\n');
100
100
  return;
@@ -131,7 +131,7 @@ async function cmdIndex() {
131
131
  const retriever = new ContextRetriever(cwd);
132
132
  const result = await retriever.buildIndex();
133
133
  process.stderr.write(`\x1b[32m✓ Index built: ${result.fileCount} files, ${result.chunkCount} chunks\x1b[0m\n`);
134
- process.stderr.write(`\x1b[2m Stored at: ${path.join(cwd, '.orca', 'index')}\x1b[0m\n`);
134
+ process.stderr.write(`\x1b[2m Stored at: ${path.join(cwd, '.kepler', 'index')}\x1b[0m\n`);
135
135
  } catch (err) {
136
136
  process.stderr.write(`\x1b[31mIndex build failed: ${err.message}\x1b[0m\n`);
137
137
  }
@@ -186,7 +186,7 @@ function cmdRefresh(ctx) {
186
186
  process.stderr.write('\x1b[31mNo auth module available.\x1b[0m\n');
187
187
  return;
188
188
  }
189
- // Force re-read from ~/.orca/config.json
189
+ // Force re-read from ~/.kepler/config.json
190
190
  ctx.auth._config = null;
191
191
  const creds = ctx.auth.loadCredentials();
192
192
  const GREEN = '\x1b[32m', DIM = '\x1b[2m', CYAN = '\x1b[36m', RESET = '\x1b[0m';