@optiqcode/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.
@@ -0,0 +1,4 @@
1
+ export declare function index(path: string, repoId?: string, embed?: boolean, incremental?: boolean, fresh?: boolean): Promise<any>;
2
+ export declare function indexStatus(jobId: string): Promise<any>;
3
+ export declare function search(query: string, repoId?: string, limit?: number, intent?: string): Promise<any>;
4
+ export declare function repos(): Promise<any>;
@@ -0,0 +1,55 @@
1
+ import { getAccessToken, refreshAccessToken } from "./auth.js";
2
+ const BASE_URL = process.env.OPTIQ_API_URL || "https://optiqcode.com";
3
+ async function request(path, options) {
4
+ const token = getAccessToken();
5
+ const headers = {
6
+ "Content-Type": "application/json",
7
+ ...options?.headers,
8
+ };
9
+ if (token)
10
+ headers["Authorization"] = `Bearer ${token}`;
11
+ let res = await fetch(`${BASE_URL}${path}`, { ...options, headers });
12
+ // Auto-refresh on 401
13
+ if (res.status === 401 && token) {
14
+ const newToken = await refreshAccessToken();
15
+ if (newToken) {
16
+ headers["Authorization"] = `Bearer ${newToken}`;
17
+ res = await fetch(`${BASE_URL}${path}`, { ...options, headers });
18
+ }
19
+ }
20
+ if (!res.ok) {
21
+ const text = await res.text().catch(() => "");
22
+ throw new Error(`API ${res.status}: ${text}`);
23
+ }
24
+ return res.json();
25
+ }
26
+ export async function index(path, repoId, embed = true, incremental = true, fresh = false) {
27
+ return request("/api/v1/index", {
28
+ method: "POST",
29
+ body: JSON.stringify({
30
+ path,
31
+ repo_id: repoId,
32
+ embed,
33
+ incremental,
34
+ fresh,
35
+ }),
36
+ });
37
+ }
38
+ export async function indexStatus(jobId) {
39
+ return request(`/api/v1/index/status/${encodeURIComponent(jobId)}`);
40
+ }
41
+ export async function search(query, repoId, limit = 10, intent) {
42
+ return request("/api/v1/query", {
43
+ method: "POST",
44
+ body: JSON.stringify({
45
+ query,
46
+ repo_id: repoId,
47
+ limit,
48
+ intent,
49
+ }),
50
+ });
51
+ }
52
+ export async function repos() {
53
+ return request("/api/v1/repos");
54
+ }
55
+ //# sourceMappingURL=api-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-client.js","sourceRoot":"","sources":["../src/api-client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/D,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,uBAAuB,CAAC;AAEtE,KAAK,UAAU,OAAO,CAAC,IAAY,EAAE,OAAqB;IACxD,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,OAAO,GAA2B;QACtC,cAAc,EAAE,kBAAkB;QAClC,GAAI,OAAO,EAAE,OAAkC;KAChD,CAAC;IACF,IAAI,KAAK;QAAE,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,KAAK,EAAE,CAAC;IAExD,IAAI,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;IAErE,sBAAsB;IACtB,IAAI,GAAG,CAAC,MAAM,KAAK,GAAG,IAAI,KAAK,EAAE,CAAC;QAChC,MAAM,QAAQ,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAC5C,IAAI,QAAQ,EAAE,CAAC;YACb,OAAO,CAAC,eAAe,CAAC,GAAG,UAAU,QAAQ,EAAE,CAAC;YAChD,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,GAAG,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;QACnE,CAAC;IACH,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,OAAO,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,CAAC,IAAI,EAAE,CAAC;AACpB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,IAAY,EACZ,MAAe,EACf,KAAK,GAAG,IAAI,EACZ,WAAW,GAAG,IAAI,EAClB,KAAK,GAAG,KAAK;IAEb,OAAO,OAAO,CAAC,eAAe,EAAE;QAC9B,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,IAAI;YACJ,OAAO,EAAE,MAAM;YACf,KAAK;YACL,WAAW;YACX,KAAK;SACN,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,KAAa;IAC7C,OAAO,OAAO,CAAC,wBAAwB,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,KAAa,EACb,MAAe,EACf,KAAK,GAAG,EAAE,EACV,MAAe;IAEf,OAAO,OAAO,CAAC,eAAe,EAAE;QAC9B,MAAM,EAAE,MAAM;QACd,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;YACnB,KAAK;YACL,OAAO,EAAE,MAAM;YACf,KAAK;YACL,MAAM;SACP,CAAC;KACH,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,OAAO,OAAO,CAAC,eAAe,CAAC,CAAC;AAClC,CAAC"}
package/dist/auth.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ interface AuthTokens {
2
+ access_token: string;
3
+ refresh_token: string;
4
+ email: string;
5
+ }
6
+ export declare function getTokens(): AuthTokens | null;
7
+ export declare function saveTokens(tokens: AuthTokens): void;
8
+ export declare function clearTokens(): void;
9
+ export declare function getAccessToken(): string | null;
10
+ export declare function isLoggedIn(): boolean;
11
+ export declare function login(): Promise<void>;
12
+ export declare function refreshAccessToken(): Promise<string | null>;
13
+ export declare function logout(): Promise<void>;
14
+ export declare function requireAuth(): string;
15
+ export {};
package/dist/auth.js ADDED
@@ -0,0 +1,165 @@
1
+ import { readFileSync, writeFileSync, mkdirSync, existsSync, unlinkSync } from "node:fs";
2
+ import { join } from "node:path";
3
+ import { homedir } from "node:os";
4
+ import { createInterface } from "node:readline";
5
+ import { banner, step, info, success, warn, error, spinner, divider } from "./ui.js";
6
+ const CONFIG_DIR = join(homedir(), ".optiq");
7
+ const TOKEN_FILE = join(CONFIG_DIR, "auth.json");
8
+ export function getTokens() {
9
+ if (!existsSync(TOKEN_FILE))
10
+ return null;
11
+ try {
12
+ return JSON.parse(readFileSync(TOKEN_FILE, "utf-8"));
13
+ }
14
+ catch {
15
+ return null;
16
+ }
17
+ }
18
+ export function saveTokens(tokens) {
19
+ mkdirSync(CONFIG_DIR, { recursive: true });
20
+ writeFileSync(TOKEN_FILE, JSON.stringify(tokens, null, 2), { mode: 0o600 });
21
+ }
22
+ export function clearTokens() {
23
+ if (existsSync(TOKEN_FILE))
24
+ unlinkSync(TOKEN_FILE);
25
+ }
26
+ export function getAccessToken() {
27
+ return getTokens()?.access_token ?? null;
28
+ }
29
+ export function isLoggedIn() {
30
+ return getTokens() !== null;
31
+ }
32
+ function prompt(question) {
33
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
34
+ return new Promise((resolve) => {
35
+ rl.question(` ${question}`, (answer) => {
36
+ rl.close();
37
+ resolve(answer.trim());
38
+ });
39
+ });
40
+ }
41
+ const BASE_URL = process.env.OPTIQ_API_URL || "https://optiqcode.com";
42
+ export async function login() {
43
+ banner();
44
+ const existing = getTokens();
45
+ if (existing) {
46
+ success(`Already logged in as ${existing.email}`);
47
+ info("Run `optiq logout` first to switch accounts.");
48
+ return;
49
+ }
50
+ step("Sign in");
51
+ const email = await prompt("Enter your email: ");
52
+ if (!email)
53
+ throw new Error("Email is required");
54
+ divider();
55
+ const s1 = spinner("Sending verification code...");
56
+ const sendRes = await fetch(`${BASE_URL}/api/v1/auth/send-code`, {
57
+ method: "POST",
58
+ headers: { "Content-Type": "application/json" },
59
+ body: JSON.stringify({ email }),
60
+ });
61
+ if (!sendRes.ok) {
62
+ s1.stop();
63
+ const text = await sendRes.text().catch(() => "");
64
+ throw new Error(`Failed to send code: ${text}`);
65
+ }
66
+ s1.stop(`Verification code sent to ${email}`);
67
+ step("Verify");
68
+ info("Check your inbox for a 6-digit code.");
69
+ const code = await prompt("Enter code: ");
70
+ if (!code)
71
+ throw new Error("Code is required");
72
+ const s2 = spinner("Verifying...");
73
+ const verifyRes = await fetch(`${BASE_URL}/api/v1/auth/verify-code`, {
74
+ method: "POST",
75
+ headers: { "Content-Type": "application/json" },
76
+ body: JSON.stringify({ email, code }),
77
+ });
78
+ if (!verifyRes.ok) {
79
+ s2.stop();
80
+ const text = await verifyRes.text().catch(() => "");
81
+ throw new Error(`Verification failed: ${text}`);
82
+ }
83
+ const data = await verifyRes.json();
84
+ s2.stop("Code verified");
85
+ if (data.mfa_required) {
86
+ step("Two-factor authentication");
87
+ const totp = await prompt("Enter MFA code: ");
88
+ const s3 = spinner("Verifying MFA...");
89
+ const mfaRes = await fetch(`${BASE_URL}/api/v1/auth/mfa/login`, {
90
+ method: "POST",
91
+ headers: { "Content-Type": "application/json" },
92
+ body: JSON.stringify({ mfa_token: data.mfa_token, totp_code: totp }),
93
+ });
94
+ if (!mfaRes.ok) {
95
+ s3.stop();
96
+ const text = await mfaRes.text().catch(() => "");
97
+ throw new Error(`MFA failed: ${text}`);
98
+ }
99
+ const mfaData = await mfaRes.json();
100
+ saveTokens({ access_token: mfaData.access_token, refresh_token: mfaData.refresh_token, email });
101
+ s3.stop("MFA verified");
102
+ }
103
+ else {
104
+ saveTokens({ access_token: data.access_token, refresh_token: data.refresh_token, email });
105
+ }
106
+ divider();
107
+ success(`Welcome back, ${email}`);
108
+ info("You're all set. Run `optiq --help` to get started.\n");
109
+ }
110
+ export async function refreshAccessToken() {
111
+ const tokens = getTokens();
112
+ if (!tokens?.refresh_token)
113
+ return null;
114
+ try {
115
+ const res = await fetch(`${BASE_URL}/api/v1/auth/refresh`, {
116
+ method: "POST",
117
+ headers: { "Content-Type": "application/json" },
118
+ body: JSON.stringify({ refresh_token: tokens.refresh_token }),
119
+ });
120
+ if (!res.ok) {
121
+ clearTokens();
122
+ return null;
123
+ }
124
+ const data = await res.json();
125
+ saveTokens({ ...tokens, access_token: data.access_token });
126
+ return data.access_token;
127
+ }
128
+ catch {
129
+ return null;
130
+ }
131
+ }
132
+ export async function logout() {
133
+ const tokens = getTokens();
134
+ if (!tokens) {
135
+ warn("Not currently logged in.");
136
+ return;
137
+ }
138
+ const s = spinner("Logging out...");
139
+ if (tokens.refresh_token) {
140
+ try {
141
+ await fetch(`${BASE_URL}/api/v1/auth/logout`, {
142
+ method: "POST",
143
+ headers: {
144
+ "Content-Type": "application/json",
145
+ Authorization: `Bearer ${tokens.access_token}`,
146
+ },
147
+ body: JSON.stringify({ refresh_token: tokens.refresh_token }),
148
+ });
149
+ }
150
+ catch {
151
+ // Best-effort server-side logout
152
+ }
153
+ }
154
+ clearTokens();
155
+ s.stop(`Logged out of ${tokens.email}`);
156
+ }
157
+ export function requireAuth() {
158
+ const token = getAccessToken();
159
+ if (!token) {
160
+ error("Not logged in. Run `optiq login` first.");
161
+ process.exit(1);
162
+ }
163
+ return token;
164
+ }
165
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,126 @@
1
+ #!/usr/bin/env node
2
+ import { Command } from "commander";
3
+ import { resolve } from "node:path";
4
+ import * as api from "./api-client.js";
5
+ import { deriveRepoId, waitForIndex } from "./utils.js";
6
+ import { startMcpServer } from "./mcp-server.js";
7
+ import { login, logout, requireAuth, isLoggedIn, getTokens } from "./auth.js";
8
+ import { success, error } from "./ui.js";
9
+ const program = new Command()
10
+ .name("optiq")
11
+ .description("Optiq Code CLI and MCP Server")
12
+ .version("0.1.0");
13
+ program
14
+ .command("login")
15
+ .description("Log in to Optiq (email OTP)")
16
+ .action(async () => {
17
+ try {
18
+ await login();
19
+ }
20
+ catch (e) {
21
+ console.error(`Error: ${e.message}`);
22
+ process.exit(1);
23
+ }
24
+ });
25
+ program
26
+ .command("logout")
27
+ .description("Log out of Optiq")
28
+ .action(async () => {
29
+ await logout();
30
+ });
31
+ program
32
+ .command("mcp")
33
+ .description("Start MCP server (stdio transport)")
34
+ .action(async () => {
35
+ if (!isLoggedIn()) {
36
+ console.error("Not logged in. Run `optiq login` first.");
37
+ process.exit(1);
38
+ }
39
+ await startMcpServer();
40
+ });
41
+ program
42
+ .command("index [path]")
43
+ .description("Index a directory for code search")
44
+ .option("--repo-id <id>", "Repository identifier")
45
+ .option("--fresh", "Re-index from scratch")
46
+ .option("--no-incremental", "Disable incremental indexing")
47
+ .action(async (path, opts) => {
48
+ requireAuth();
49
+ const dir = resolve(path || ".");
50
+ const repoId = opts.repoId || deriveRepoId(dir);
51
+ console.log(`Indexing ${dir} as ${repoId}...`);
52
+ try {
53
+ const result = await api.index(dir, repoId, true, opts.incremental, opts.fresh);
54
+ const jobId = result.job_id;
55
+ if (jobId) {
56
+ console.log(`Job started: ${jobId}`);
57
+ const final = await waitForIndex(jobId, 2000, (s) => process.stdout.write(`\rStatus: ${s} `));
58
+ console.log(`\nIndexing ${final.status}.`);
59
+ }
60
+ else {
61
+ console.log(JSON.stringify(result, null, 2));
62
+ }
63
+ }
64
+ catch (e) {
65
+ console.error(`Error: ${e.message}`);
66
+ process.exit(1);
67
+ }
68
+ });
69
+ program
70
+ .command("search <query>")
71
+ .description("Search indexed code")
72
+ .option("--repo-id <id>", "Filter by repository")
73
+ .option("--limit <n>", "Max results", "10")
74
+ .option("--intent <intent>", "Search intent hint")
75
+ .action(async (query, opts) => {
76
+ requireAuth();
77
+ try {
78
+ const result = await api.search(query, opts.repoId, Number(opts.limit), opts.intent);
79
+ console.log(JSON.stringify(result, null, 2));
80
+ }
81
+ catch (e) {
82
+ console.error(`Error: ${e.message}`);
83
+ process.exit(1);
84
+ }
85
+ });
86
+ program
87
+ .command("repos")
88
+ .description("List indexed repositories")
89
+ .action(async () => {
90
+ requireAuth();
91
+ try {
92
+ const result = await api.repos();
93
+ console.log(JSON.stringify(result, null, 2));
94
+ }
95
+ catch (e) {
96
+ console.error(`Error: ${e.message}`);
97
+ process.exit(1);
98
+ }
99
+ });
100
+ program
101
+ .command("status <job_id>")
102
+ .description("Check indexing job status")
103
+ .action(async (jobId) => {
104
+ requireAuth();
105
+ try {
106
+ const result = await api.indexStatus(jobId);
107
+ console.log(JSON.stringify(result, null, 2));
108
+ }
109
+ catch (e) {
110
+ console.error(`Error: ${e.message}`);
111
+ process.exit(1);
112
+ }
113
+ });
114
+ program
115
+ .command("whoami")
116
+ .description("Show current logged-in account")
117
+ .action(() => {
118
+ const tokens = getTokens();
119
+ if (!tokens) {
120
+ error("Not logged in. Run `optiq login` first.");
121
+ process.exit(1);
122
+ }
123
+ success(`Logged in as ${tokens.email}`);
124
+ });
125
+ program.parse();
126
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function startMcpServer(): Promise<void>;
@@ -0,0 +1,44 @@
1
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
2
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
3
+ import { z } from "zod";
4
+ import { resolve } from "node:path";
5
+ import * as api from "./api-client.js";
6
+ import { deriveRepoId } from "./utils.js";
7
+ export async function startMcpServer() {
8
+ const server = new McpServer({
9
+ name: "optiq",
10
+ version: "0.1.0",
11
+ });
12
+ server.tool("optiq_index", "Index a directory for code search", {
13
+ path: z.string().describe("Directory path to index"),
14
+ repo_id: z.string().optional().describe("Repository identifier"),
15
+ fresh: z.boolean().optional().describe("Re-index from scratch"),
16
+ incremental: z.boolean().optional().describe("Incremental indexing"),
17
+ }, async ({ path, repo_id, fresh, incremental }) => {
18
+ const repoId = repo_id || deriveRepoId(path);
19
+ const result = await api.index(resolve(path), repoId, true, incremental ?? true, fresh ?? false);
20
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
21
+ });
22
+ server.tool("optiq_search", "Search indexed code", {
23
+ query: z.string().describe("Search query"),
24
+ repo_id: z.string().optional().describe("Filter by repository"),
25
+ limit: z.number().optional().describe("Max results"),
26
+ intent: z.string().optional().describe("Search intent hint"),
27
+ }, async ({ query, repo_id, limit, intent }) => {
28
+ const result = await api.search(query, repo_id, limit ?? 10, intent);
29
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
30
+ });
31
+ server.tool("optiq_status", "Check indexing job status", {
32
+ job_id: z.string().describe("Job ID from indexing request"),
33
+ }, async ({ job_id }) => {
34
+ const result = await api.indexStatus(job_id);
35
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
36
+ });
37
+ server.tool("optiq_repos", "List all indexed repositories", {}, async () => {
38
+ const result = await api.repos();
39
+ return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
40
+ });
41
+ const transport = new StdioServerTransport();
42
+ await server.connect(transport);
43
+ }
44
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../src/mcp-server.ts"],"names":[],"mappings":"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"}
package/dist/ui.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ export declare function banner(): void;
2
+ export declare function info(msg: string): void;
3
+ export declare function success(msg: string): void;
4
+ export declare function warn(msg: string): void;
5
+ export declare function error(msg: string): void;
6
+ export declare function step(label: string): void;
7
+ export declare function spinner(message: string): {
8
+ stop: (finalMsg?: string) => void;
9
+ };
10
+ export declare function divider(): void;
package/dist/ui.js ADDED
@@ -0,0 +1,65 @@
1
+ const ESC = "\x1b";
2
+ const BOLD = `${ESC}[1m`;
3
+ const DIM = `${ESC}[2m`;
4
+ const RESET = `${ESC}[0m`;
5
+ const GREEN = `${ESC}[32m`;
6
+ const YELLOW = `${ESC}[33m`;
7
+ const RED = `${ESC}[31m`;
8
+ const WHITE = `${ESC}[97m`;
9
+ const WARM = `${ESC}[38;2;230;220;195m`; // #E6DCC3 accent
10
+ const MUTED = `${ESC}[38;2;115;113;106m`; // #73716A muted
11
+ const HIDE_CURSOR = `${ESC}[?25l`;
12
+ const SHOW_CURSOR = `${ESC}[?25h`;
13
+ const CLEAR_LINE = `${ESC}[2K\r`;
14
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
15
+ export function banner() {
16
+ const title = "◆ optiq code";
17
+ const pad = 6;
18
+ const inner = pad + title.length + pad;
19
+ const top = `┌${"─".repeat(inner)}┐`;
20
+ const mid = `│${" ".repeat(pad)}${title}${" ".repeat(pad)}│`;
21
+ const bot = `└${"─".repeat(inner)}┘`;
22
+ const lines = [
23
+ "",
24
+ ` ${WARM}${top}${RESET}`,
25
+ ` ${WARM}${mid}${RESET}`,
26
+ ` ${WARM}${bot}${RESET}`,
27
+ "",
28
+ ];
29
+ process.stderr.write(lines.join("\n") + "\n");
30
+ }
31
+ export function info(msg) {
32
+ process.stderr.write(` ${MUTED}${msg}${RESET}\n`);
33
+ }
34
+ export function success(msg) {
35
+ process.stderr.write(` ${GREEN}✔${RESET} ${msg}\n`);
36
+ }
37
+ export function warn(msg) {
38
+ process.stderr.write(` ${YELLOW}⚠${RESET} ${msg}\n`);
39
+ }
40
+ export function error(msg) {
41
+ process.stderr.write(` ${RED}✖${RESET} ${msg}\n`);
42
+ }
43
+ export function step(label) {
44
+ process.stderr.write(`\n ${WHITE}${BOLD}${label}${RESET}\n`);
45
+ }
46
+ export function spinner(message) {
47
+ let i = 0;
48
+ process.stderr.write(HIDE_CURSOR);
49
+ const id = setInterval(() => {
50
+ process.stderr.write(`${CLEAR_LINE} ${WARM}${FRAMES[i % FRAMES.length]}${RESET} ${MUTED}${message}${RESET}`);
51
+ i++;
52
+ }, 80);
53
+ return {
54
+ stop(finalMsg) {
55
+ clearInterval(id);
56
+ process.stderr.write(`${CLEAR_LINE}${SHOW_CURSOR}`);
57
+ if (finalMsg)
58
+ success(finalMsg);
59
+ },
60
+ };
61
+ }
62
+ export function divider() {
63
+ process.stderr.write(` ${MUTED}${"─".repeat(24)}${RESET}\n`);
64
+ }
65
+ //# sourceMappingURL=ui.js.map
package/dist/ui.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function deriveRepoId(dirPath: string): string;
2
+ export declare function waitForIndex(jobId: string, intervalMs?: number, onStatus?: (status: string) => void): Promise<{
3
+ status: string;
4
+ [key: string]: unknown;
5
+ }>;
package/dist/utils.js ADDED
@@ -0,0 +1,20 @@
1
+ import { createHash } from "node:crypto";
2
+ import { basename, resolve } from "node:path";
3
+ import { indexStatus } from "./api-client.js";
4
+ export function deriveRepoId(dirPath) {
5
+ const abs = resolve(dirPath);
6
+ const hash = createHash("sha256").update(abs).digest("hex").slice(0, 8);
7
+ return `${basename(abs)}-${hash}`;
8
+ }
9
+ export async function waitForIndex(jobId, intervalMs = 2000, onStatus) {
10
+ while (true) {
11
+ const result = await indexStatus(jobId);
12
+ const status = result.status;
13
+ if (onStatus)
14
+ onStatus(status);
15
+ if (status === "completed" || status === "failed")
16
+ return result;
17
+ await new Promise((r) => setTimeout(r, intervalMs));
18
+ }
19
+ }
20
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE9C,MAAM,UAAU,YAAY,CAAC,OAAe;IAC1C,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACxE,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;AACpC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,KAAa,EACb,UAAU,GAAG,IAAI,EACjB,QAAmC;IAEnC,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,KAAK,CAAC,CAAC;QACxC,MAAM,MAAM,GAAG,MAAM,CAAC,MAAgB,CAAC;QACvC,IAAI,QAAQ;YAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,WAAW,IAAI,MAAM,KAAK,QAAQ;YAAE,OAAO,MAAM,CAAC;QACjE,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,CAAC;IACtD,CAAC;AACH,CAAC"}
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@optiqcode/cli",
3
+ "version": "0.1.0",
4
+ "description": "Optiq Code CLI and MCP Server",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "homepage": "https://optiqcode.com",
8
+ "repository": {
9
+ "type": "git",
10
+ "url": "https://github.com/optiqcode/optiq"
11
+ },
12
+ "keywords": ["optiq", "code-search", "mcp", "cli", "ai"],
13
+ "bin": {
14
+ "optiq": "./dist/index.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsc",
21
+ "dev": "tsc --watch",
22
+ "test": "node --test tests/test_cli.js"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.12.1",
26
+ "commander": "^13.1.0"
27
+ },
28
+ "devDependencies": {
29
+ "@types/node": "^22.0.0",
30
+ "typescript": "^5.7.0"
31
+ }
32
+ }