@getreka/cli 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/dist/api.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * API client for Reka CLI
3
+ */
4
+ import { AxiosInstance } from "axios";
5
+ import { RekaConfig } from "./config";
6
+ export declare function createClient(config: RekaConfig): AxiosInstance;
7
+ export declare function formatError(err: unknown): string;
package/dist/api.js ADDED
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ /**
3
+ * API client for Reka CLI
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.createClient = createClient;
40
+ exports.formatError = formatError;
41
+ const axios_1 = __importStar(require("axios"));
42
+ function createClient(config) {
43
+ const headers = {
44
+ "Content-Type": "application/json",
45
+ "X-Project-Name": config.project.name,
46
+ "X-Project-Path": config.project.path,
47
+ };
48
+ if (config.api.key) {
49
+ headers["Authorization"] = `Bearer ${config.api.key}`;
50
+ }
51
+ return axios_1.default.create({
52
+ baseURL: config.api.url,
53
+ timeout: 120000,
54
+ headers,
55
+ });
56
+ }
57
+ function formatError(err) {
58
+ if (err instanceof axios_1.AxiosError) {
59
+ if (err.code === "ECONNREFUSED") {
60
+ return `Cannot connect to Reka API at ${err.config?.baseURL}. Is it running?`;
61
+ }
62
+ if (err.response) {
63
+ const data = err.response.data;
64
+ return data?.error || data?.message || `HTTP ${err.response.status}`;
65
+ }
66
+ }
67
+ return err.message || String(err);
68
+ }
@@ -0,0 +1,6 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { RekaConfig } from "../config";
3
+ export declare function indexCommand(client: AxiosInstance, config: RekaConfig, opts: {
4
+ path?: string;
5
+ watch?: boolean;
6
+ }): Promise<void>;
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.indexCommand = indexCommand;
7
+ const ora_1 = __importDefault(require("ora"));
8
+ const api_1 = require("../api");
9
+ async function indexCommand(client, config, opts) {
10
+ const indexPath = opts.path || config.project.path;
11
+ const spinner = (0, ora_1.default)(`Indexing ${indexPath}...`).start();
12
+ try {
13
+ const { data } = await client.post("/api/index", {
14
+ path: indexPath,
15
+ projectName: config.project.name,
16
+ });
17
+ spinner.succeed(`Indexed ${data.filesProcessed || "N/A"} files`);
18
+ if (data.stats) {
19
+ console.log("");
20
+ console.log(` Chunks: ${data.stats.chunks || "N/A"}`);
21
+ console.log(` Symbols: ${data.stats.symbols || "N/A"}`);
22
+ console.log(` Duration: ${data.stats.duration || "N/A"}`);
23
+ }
24
+ }
25
+ catch (err) {
26
+ spinner.fail(`Index failed: ${(0, api_1.formatError)(err)}`);
27
+ process.exit(1);
28
+ }
29
+ console.log("");
30
+ }
@@ -0,0 +1,8 @@
1
+ export declare function initCommand(opts: {
2
+ project?: string;
3
+ path?: string;
4
+ force?: boolean;
5
+ cloud?: boolean;
6
+ key?: string;
7
+ apiUrl?: string;
8
+ }): Promise<void>;
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.initCommand = initCommand;
40
+ const fs = __importStar(require("fs"));
41
+ const path = __importStar(require("path"));
42
+ const chalk_1 = __importDefault(require("chalk"));
43
+ const api_1 = require("../api");
44
+ const config_1 = require("../config");
45
+ const MCP_TEMPLATE = `{
46
+ "mcpServers": {
47
+ "reka": {
48
+ "command": "npx",
49
+ "args": ["-y", "@getreka/mcp"],
50
+ "env": {
51
+ "REKA_API_KEY": "{{API_KEY}}"
52
+ }
53
+ }
54
+ }
55
+ }`;
56
+ async function initCommand(opts) {
57
+ const projectPath = opts.path || process.cwd();
58
+ const projectName = opts.project || path.basename(projectPath);
59
+ // Cloud mode: use provided key, skip keygen
60
+ if (opts.cloud || opts.key) {
61
+ if (!opts.key) {
62
+ console.log(chalk_1.default.red("\n --key is required for cloud mode. Get one at https://getreka.dev/dashboard\n"));
63
+ return;
64
+ }
65
+ writeMcpConfig(projectPath, opts.key, opts.force);
66
+ console.log(chalk_1.default.green(`\n ✓ Connected to Reka Cloud`));
67
+ console.log(` Project will be resolved from your API key.\n`);
68
+ return;
69
+ }
70
+ // Self-hosted: generate key via local API
71
+ const config = (0, config_1.loadConfig)({
72
+ api: { url: opts.apiUrl || "http://localhost:3100" },
73
+ project: { name: projectName, path: projectPath },
74
+ });
75
+ const client = (0, api_1.createClient)(config);
76
+ console.log(`\n Generating API key for project ${chalk_1.default.bold(projectName)}...`);
77
+ try {
78
+ const { data } = await client.post("/api/keys", {
79
+ projectName,
80
+ label: `init-${Date.now()}`,
81
+ });
82
+ const apiKey = data.key;
83
+ writeMcpConfig(projectPath, apiKey, opts.force);
84
+ console.log(chalk_1.default.green(` ✓ API key created: ${apiKey.slice(0, 20)}...`));
85
+ console.log(chalk_1.default.green(` ✓ .mcp.json written`));
86
+ console.log("");
87
+ console.log(" Your AI assistant now has memory. Try asking it about your codebase!");
88
+ console.log("");
89
+ }
90
+ catch (err) {
91
+ const msg = err.response?.data?.error || err.message;
92
+ console.log(chalk_1.default.red(`\n Failed to generate key: ${msg}`));
93
+ console.log(chalk_1.default.yellow(` Is the Reka API running? Start with: docker-compose up -d\n`));
94
+ }
95
+ }
96
+ function writeMcpConfig(projectPath, apiKey, force) {
97
+ const mcpPath = path.join(projectPath, ".mcp.json");
98
+ if (fs.existsSync(mcpPath) && !force) {
99
+ // Merge into existing .mcp.json
100
+ try {
101
+ const existing = JSON.parse(fs.readFileSync(mcpPath, "utf-8"));
102
+ existing.mcpServers = existing.mcpServers || {};
103
+ existing.mcpServers.reka = {
104
+ command: "npx",
105
+ args: ["-y", "@getreka/mcp"],
106
+ env: { REKA_API_KEY: apiKey },
107
+ };
108
+ fs.writeFileSync(mcpPath, JSON.stringify(existing, null, 2) + "\n", "utf-8");
109
+ return;
110
+ }
111
+ catch {
112
+ // Fall through to overwrite
113
+ }
114
+ }
115
+ const content = MCP_TEMPLATE.replace("{{API_KEY}}", apiKey);
116
+ fs.writeFileSync(mcpPath, content + "\n", "utf-8");
117
+ }
@@ -0,0 +1,3 @@
1
+ import { RekaConfig } from "../config";
2
+ export declare function modelsListCommand(config: RekaConfig): Promise<void>;
3
+ export declare function modelsTestCommand(config: RekaConfig): Promise<void>;
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.modelsListCommand = modelsListCommand;
7
+ exports.modelsTestCommand = modelsTestCommand;
8
+ const chalk_1 = __importDefault(require("chalk"));
9
+ const ora_1 = __importDefault(require("ora"));
10
+ const axios_1 = __importDefault(require("axios"));
11
+ const api_1 = require("../api");
12
+ async function checkProvider(name, url) {
13
+ const start = Date.now();
14
+ try {
15
+ if (name === "ollama") {
16
+ const { data } = await axios_1.default.get(`${url}/api/tags`, { timeout: 5000 });
17
+ return {
18
+ name,
19
+ url,
20
+ status: "healthy",
21
+ latency: Date.now() - start,
22
+ models: (data.models || []).map((m) => m.name),
23
+ };
24
+ }
25
+ else if (name === "bge-m3") {
26
+ await axios_1.default.get(`${url}/health`, { timeout: 5000 });
27
+ return { name, url, status: "healthy", latency: Date.now() - start };
28
+ }
29
+ else {
30
+ await axios_1.default.get(url, { timeout: 5000 });
31
+ return { name, url, status: "healthy", latency: Date.now() - start };
32
+ }
33
+ }
34
+ catch {
35
+ return { name, url, status: "unreachable", latency: Date.now() - start };
36
+ }
37
+ }
38
+ async function modelsListCommand(config) {
39
+ console.log(chalk_1.default.bold("\n Model Providers\n"));
40
+ const spinner = (0, ora_1.default)("Checking providers...").start();
41
+ const checks = [];
42
+ // Always check default providers
43
+ const ollamaUrl = config.models?.llm?.utility?.url || "http://localhost:11434";
44
+ const bgeUrl = config.models?.embeddings?.url || "http://localhost:8080";
45
+ checks.push(checkProvider("ollama", ollamaUrl));
46
+ checks.push(checkProvider("bge-m3", bgeUrl));
47
+ const results = await Promise.all(checks);
48
+ spinner.stop();
49
+ for (const r of results) {
50
+ const icon = r.status === "healthy" ? chalk_1.default.green("●") : chalk_1.default.red("●");
51
+ const latency = r.latency ? chalk_1.default.gray(`${r.latency}ms`) : "";
52
+ console.log(` ${icon} ${chalk_1.default.bold(r.name)} ${chalk_1.default.gray(r.url)} ${latency}`);
53
+ if (r.models && r.models.length > 0) {
54
+ for (const m of r.models.slice(0, 10)) {
55
+ console.log(` ${chalk_1.default.gray("→")} ${m}`);
56
+ }
57
+ if (r.models.length > 10) {
58
+ console.log(` ${chalk_1.default.gray(` ...and ${r.models.length - 10} more`)}`);
59
+ }
60
+ }
61
+ }
62
+ // Show configured routing
63
+ if (config.models?.llm) {
64
+ console.log(chalk_1.default.bold("\n Routing"));
65
+ const llm = config.models.llm;
66
+ if (llm.utility)
67
+ console.log(` Utility: ${llm.utility.provider} / ${llm.utility.model || "default"}`);
68
+ if (llm.standard)
69
+ console.log(` Standard: ${llm.standard.provider} / ${llm.standard.model || "default"}`);
70
+ if (llm.complex)
71
+ console.log(` Complex: ${llm.complex.provider} / ${llm.complex.model || "default"}`);
72
+ }
73
+ console.log("");
74
+ }
75
+ async function modelsTestCommand(config) {
76
+ console.log(chalk_1.default.bold("\n Testing Model Connections\n"));
77
+ const ollamaUrl = config.models?.llm?.utility?.url || "http://localhost:11434";
78
+ const bgeUrl = config.models?.embeddings?.url || "http://localhost:8080";
79
+ // Test embedding
80
+ const embedSpinner = (0, ora_1.default)("Testing embeddings...").start();
81
+ try {
82
+ const start = Date.now();
83
+ await axios_1.default.post(`${bgeUrl}/embed`, {
84
+ text: "test embedding connection",
85
+ }, { timeout: 10000 });
86
+ embedSpinner.succeed(`Embeddings OK (${Date.now() - start}ms)`);
87
+ }
88
+ catch (err) {
89
+ embedSpinner.fail(`Embeddings failed: ${(0, api_1.formatError)(err)}`);
90
+ }
91
+ // Test LLM
92
+ const llmSpinner = (0, ora_1.default)("Testing LLM...").start();
93
+ try {
94
+ const model = config.models?.llm?.utility?.model || "qwen3.5:35b";
95
+ const start = Date.now();
96
+ await axios_1.default.post(`${ollamaUrl}/api/generate`, {
97
+ model,
98
+ prompt: 'Say "ok" and nothing else.',
99
+ stream: false,
100
+ options: { num_predict: 10 },
101
+ }, { timeout: 30000 });
102
+ llmSpinner.succeed(`LLM OK — ${model} (${Date.now() - start}ms)`);
103
+ }
104
+ catch (err) {
105
+ llmSpinner.fail(`LLM failed: ${(0, api_1.formatError)(err)}`);
106
+ }
107
+ console.log("");
108
+ }
@@ -0,0 +1,6 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { RekaConfig } from "../config";
3
+ export declare function searchCommand(client: AxiosInstance, config: RekaConfig, query: string, opts: {
4
+ limit?: string;
5
+ type?: string;
6
+ }): Promise<void>;
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.searchCommand = searchCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const ora_1 = __importDefault(require("ora"));
9
+ const api_1 = require("../api");
10
+ async function searchCommand(client, config, query, opts) {
11
+ const limit = parseInt(opts.limit || "5", 10);
12
+ const spinner = (0, ora_1.default)("Searching...").start();
13
+ try {
14
+ const { data } = await client.post("/api/search", {
15
+ query,
16
+ limit,
17
+ collection: opts.type || "codebase",
18
+ });
19
+ spinner.stop();
20
+ const results = data.results || data;
21
+ if (!results || results.length === 0) {
22
+ console.log(chalk_1.default.yellow("\n No results found.\n"));
23
+ return;
24
+ }
25
+ console.log(chalk_1.default.bold(`\n ${results.length} results for "${query}"\n`));
26
+ for (const [i, r] of results.entries()) {
27
+ const score = r.score
28
+ ? chalk_1.default.gray(`(${(r.score * 100).toFixed(0)}%)`)
29
+ : "";
30
+ const filePath = r.metadata?.filePath || r.metadata?.file_path || "";
31
+ const lines = r.metadata?.startLine
32
+ ? `:${r.metadata.startLine}-${r.metadata.endLine || ""}`
33
+ : "";
34
+ console.log(` ${chalk_1.default.blue(`${i + 1}.`)} ${chalk_1.default.bold(filePath)}${lines} ${score}`);
35
+ // Show snippet (first 3 lines)
36
+ if (r.content || r.text) {
37
+ const text = (r.content || r.text);
38
+ const snippet = text.split("\n").slice(0, 3).join("\n");
39
+ console.log(chalk_1.default.gray(` ${snippet.replace(/\n/g, "\n ")}`));
40
+ }
41
+ console.log("");
42
+ }
43
+ }
44
+ catch (err) {
45
+ spinner.fail(`Search failed: ${(0, api_1.formatError)(err)}`);
46
+ process.exit(1);
47
+ }
48
+ }
@@ -0,0 +1,3 @@
1
+ import { AxiosInstance } from "axios";
2
+ import { RekaConfig } from "../config";
3
+ export declare function statusCommand(client: AxiosInstance, config: RekaConfig): Promise<void>;
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.statusCommand = statusCommand;
7
+ const chalk_1 = __importDefault(require("chalk"));
8
+ const api_1 = require("../api");
9
+ async function statusCommand(client, config) {
10
+ console.log(chalk_1.default.bold("\n Reka Status\n"));
11
+ console.log(` API: ${config.api.url}`);
12
+ console.log(` Project: ${config.project.name}`);
13
+ console.log(` Path: ${config.project.path}`);
14
+ console.log("");
15
+ // Check API health
16
+ try {
17
+ const { data } = await client.get("/health");
18
+ console.log(` API: ${chalk_1.default.green("● healthy")}`);
19
+ if (data.cache) {
20
+ console.log(` Cache: ${chalk_1.default.green("● connected")} (${data.cache.hitRate || "N/A"} hit rate)`);
21
+ }
22
+ }
23
+ catch (err) {
24
+ console.log(` API: ${chalk_1.default.red("● unreachable")} — ${(0, api_1.formatError)(err)}`);
25
+ return;
26
+ }
27
+ // Check services
28
+ try {
29
+ const { data } = await client.get("/api/project/stats");
30
+ const stats = data.stats || data;
31
+ console.log("");
32
+ console.log(chalk_1.default.bold(" Project Stats"));
33
+ if (stats.collections) {
34
+ console.log(` Collections: ${stats.collections}`);
35
+ }
36
+ if (stats.totalPoints !== undefined) {
37
+ console.log(` Vectors: ${stats.totalPoints.toLocaleString()}`);
38
+ }
39
+ if (stats.memoryCount !== undefined) {
40
+ console.log(` Memories: ${stats.memoryCount}`);
41
+ }
42
+ }
43
+ catch {
44
+ // Stats endpoint may not exist, that's ok
45
+ }
46
+ // Check index status
47
+ try {
48
+ const { data } = await client.get("/api/index/status");
49
+ if (data.status) {
50
+ const s = data.status;
51
+ console.log("");
52
+ console.log(chalk_1.default.bold(" Index"));
53
+ console.log(` Status: ${s.indexing ? chalk_1.default.yellow("● indexing") : chalk_1.default.green("● idle")}`);
54
+ if (s.totalFiles)
55
+ console.log(` Files: ${s.totalFiles}`);
56
+ if (s.lastIndexed)
57
+ console.log(` Last run: ${new Date(s.lastIndexed).toLocaleString()}`);
58
+ }
59
+ }
60
+ catch {
61
+ // Index status may not exist
62
+ }
63
+ console.log("");
64
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * CLI configuration loader
3
+ * Reads reka.config.yaml → env vars → defaults
4
+ */
5
+ export interface RekaConfig {
6
+ api: {
7
+ url: string;
8
+ key?: string;
9
+ };
10
+ project: {
11
+ name: string;
12
+ path: string;
13
+ };
14
+ models?: {
15
+ embeddings?: {
16
+ provider: string;
17
+ model?: string;
18
+ url?: string;
19
+ dimensions?: number;
20
+ };
21
+ llm?: {
22
+ utility?: {
23
+ provider: string;
24
+ model?: string;
25
+ url?: string;
26
+ };
27
+ standard?: {
28
+ provider: string;
29
+ model?: string;
30
+ url?: string;
31
+ };
32
+ complex?: {
33
+ provider: string;
34
+ model?: string;
35
+ url?: string;
36
+ };
37
+ };
38
+ };
39
+ }
40
+ export declare function loadConfig(overrides?: Partial<RekaConfig>): RekaConfig;
41
+ export declare function getConfigFilePath(): string | null;
package/dist/config.js ADDED
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+ /**
3
+ * CLI configuration loader
4
+ * Reads reka.config.yaml → env vars → defaults
5
+ */
6
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
7
+ if (k2 === undefined) k2 = k;
8
+ var desc = Object.getOwnPropertyDescriptor(m, k);
9
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
10
+ desc = { enumerable: true, get: function() { return m[k]; } };
11
+ }
12
+ Object.defineProperty(o, k2, desc);
13
+ }) : (function(o, m, k, k2) {
14
+ if (k2 === undefined) k2 = k;
15
+ o[k2] = m[k];
16
+ }));
17
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
18
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
19
+ }) : function(o, v) {
20
+ o["default"] = v;
21
+ });
22
+ var __importStar = (this && this.__importStar) || (function () {
23
+ var ownKeys = function(o) {
24
+ ownKeys = Object.getOwnPropertyNames || function (o) {
25
+ var ar = [];
26
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
27
+ return ar;
28
+ };
29
+ return ownKeys(o);
30
+ };
31
+ return function (mod) {
32
+ if (mod && mod.__esModule) return mod;
33
+ var result = {};
34
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
35
+ __setModuleDefault(result, mod);
36
+ return result;
37
+ };
38
+ })();
39
+ Object.defineProperty(exports, "__esModule", { value: true });
40
+ exports.loadConfig = loadConfig;
41
+ exports.getConfigFilePath = getConfigFilePath;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ const yaml = __importStar(require("js-yaml"));
45
+ const CONFIG_FILES = ["reka.config.yaml", "reka.config.yml", ".rekarc.yaml"];
46
+ function findConfigFile(startDir) {
47
+ let dir = startDir;
48
+ while (true) {
49
+ for (const name of CONFIG_FILES) {
50
+ const filePath = path.join(dir, name);
51
+ if (fs.existsSync(filePath))
52
+ return filePath;
53
+ }
54
+ const parent = path.dirname(dir);
55
+ if (parent === dir)
56
+ break;
57
+ dir = parent;
58
+ }
59
+ // Check home directory
60
+ const homeConfig = path.join(process.env.HOME || "~", ".config", "reka", "config.yaml");
61
+ if (fs.existsSync(homeConfig))
62
+ return homeConfig;
63
+ return null;
64
+ }
65
+ function loadConfig(overrides) {
66
+ const configFile = findConfigFile(process.cwd());
67
+ let fileConfig = {};
68
+ if (configFile) {
69
+ try {
70
+ const raw = fs.readFileSync(configFile, "utf-8");
71
+ fileConfig = yaml.load(raw) || {};
72
+ }
73
+ catch {
74
+ // Silently ignore malformed config
75
+ }
76
+ }
77
+ const projectName = overrides?.project?.name ||
78
+ fileConfig.project?.name ||
79
+ process.env.REKA_PROJECT ||
80
+ path.basename(process.cwd());
81
+ const config = {
82
+ api: {
83
+ url: overrides?.api?.url ||
84
+ fileConfig.api?.url ||
85
+ process.env.REKA_API_URL ||
86
+ process.env.RAG_API_URL ||
87
+ "http://localhost:3100",
88
+ key: overrides?.api?.key ||
89
+ fileConfig.api?.key ||
90
+ process.env.REKA_API_KEY ||
91
+ process.env.RAG_API_KEY,
92
+ },
93
+ project: {
94
+ name: projectName,
95
+ path: overrides?.project?.path ||
96
+ fileConfig.project?.path ||
97
+ process.env.REKA_PROJECT_PATH ||
98
+ process.cwd(),
99
+ },
100
+ models: fileConfig.models || overrides?.models,
101
+ };
102
+ return config;
103
+ }
104
+ function getConfigFilePath() {
105
+ return findConfigFile(process.cwd());
106
+ }
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Reka CLI — manage your self-hosted RAG infrastructure
4
+ */
5
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ /**
4
+ * Reka CLI — manage your self-hosted RAG infrastructure
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ const commander_1 = require("commander");
8
+ const config_1 = require("./config");
9
+ const api_1 = require("./api");
10
+ const status_1 = require("./commands/status");
11
+ const init_1 = require("./commands/init");
12
+ const index_1 = require("./commands/index");
13
+ const search_1 = require("./commands/search");
14
+ const models_1 = require("./commands/models");
15
+ const program = new commander_1.Command();
16
+ program
17
+ .name("reka")
18
+ .description("Reka — Memory your AI can trust")
19
+ .version("0.1.0")
20
+ .option("--api-url <url>", "RAG API URL")
21
+ .option("--api-key <key>", "API key")
22
+ .option("--project <name>", "Project name");
23
+ // reka init
24
+ program
25
+ .command("init")
26
+ .description("Initialize Reka for current project — generates API key and .mcp.json")
27
+ .option("--project <name>", "Project name (defaults to directory name)")
28
+ .option("-p, --path <path>", "Project path")
29
+ .option("-f, --force", "Overwrite existing .mcp.json")
30
+ .option("--cloud", "Connect to Reka Cloud instead of local")
31
+ .option("--key <key>", "API key (required for --cloud)")
32
+ .option("--api-url <url>", "RAG API URL (default: http://localhost:3100)")
33
+ .action(async (opts) => {
34
+ await (0, init_1.initCommand)(opts);
35
+ });
36
+ // reka status
37
+ program
38
+ .command("status")
39
+ .description("Show Reka API and project status")
40
+ .action(async () => {
41
+ const config = (0, config_1.loadConfig)(getOverrides());
42
+ const client = (0, api_1.createClient)(config);
43
+ await (0, status_1.statusCommand)(client, config);
44
+ });
45
+ // reka index [path]
46
+ program
47
+ .command("index [path]")
48
+ .description("Index a codebase for search")
49
+ .option("-w, --watch", "Watch for file changes")
50
+ .action(async (indexPath, opts) => {
51
+ const config = (0, config_1.loadConfig)(getOverrides());
52
+ const client = (0, api_1.createClient)(config);
53
+ await (0, index_1.indexCommand)(client, config, { path: indexPath, ...opts });
54
+ });
55
+ // reka search <query>
56
+ program
57
+ .command("search <query>")
58
+ .description("Search indexed codebase")
59
+ .option("-l, --limit <n>", "Number of results", "5")
60
+ .option("-t, --type <type>", "Collection type (codebase, docs, memory)")
61
+ .action(async (query, opts) => {
62
+ const config = (0, config_1.loadConfig)(getOverrides());
63
+ const client = (0, api_1.createClient)(config);
64
+ await (0, search_1.searchCommand)(client, config, query, opts);
65
+ });
66
+ // reka models
67
+ const models = program.command("models").description("Manage model providers");
68
+ models
69
+ .command("list")
70
+ .description("List configured model providers and their status")
71
+ .action(async () => {
72
+ const config = (0, config_1.loadConfig)(getOverrides());
73
+ await (0, models_1.modelsListCommand)(config);
74
+ });
75
+ models
76
+ .command("test")
77
+ .description("Test connection to all model providers")
78
+ .action(async () => {
79
+ const config = (0, config_1.loadConfig)(getOverrides());
80
+ await (0, models_1.modelsTestCommand)(config);
81
+ });
82
+ // Helper to extract global overrides
83
+ function getOverrides() {
84
+ const opts = program.opts();
85
+ const overrides = {};
86
+ if (opts.apiUrl || opts.apiKey) {
87
+ overrides.api = {};
88
+ if (opts.apiUrl)
89
+ overrides.api.url = opts.apiUrl;
90
+ if (opts.apiKey)
91
+ overrides.api.key = opts.apiKey;
92
+ }
93
+ if (opts.project) {
94
+ overrides.project = { name: opts.project };
95
+ }
96
+ return overrides;
97
+ }
98
+ program.parse();
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@getreka/cli",
3
+ "version": "0.1.0",
4
+ "description": "Reka CLI — manage self-hosted RAG infrastructure for AI coding agents",
5
+ "bin": {
6
+ "reka": "./dist/index.js"
7
+ },
8
+ "main": "dist/index.js",
9
+ "files": ["dist", "README.md"],
10
+ "publishConfig": {
11
+ "access": "public"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/getreka/reka.git",
16
+ "directory": "cli"
17
+ },
18
+ "homepage": "https://getreka.dev",
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "ts-node src/index.ts",
22
+ "start": "node dist/index.js"
23
+ },
24
+ "dependencies": {
25
+ "axios": "^1.7.0",
26
+ "chalk": "^4.1.2",
27
+ "commander": "^12.1.0",
28
+ "js-yaml": "^4.1.0",
29
+ "ora": "^5.4.1"
30
+ },
31
+ "devDependencies": {
32
+ "@types/js-yaml": "^4.0.9",
33
+ "@types/node": "^20.14.0",
34
+ "typescript": "^5.5.0",
35
+ "ts-node": "^10.9.2"
36
+ },
37
+ "engines": {
38
+ "node": ">=18"
39
+ },
40
+ "license": "BSL-1.1",
41
+ "keywords": ["reka", "rag", "mcp", "ai", "cli", "coding-agent", "memory"]
42
+ }