lunel-cli 0.1.121 → 0.1.122

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,109 @@
1
+ # Lunel CLI
2
+
3
+ Node.js CLI that connects a local machine to the Lunel mobile app through the Lunel gateway. It runs from the project directory you want to expose and keeps filesystem, terminal, process, port, git, and AI actions scoped to that working tree.
4
+
5
+ ## Requirements
6
+
7
+ - Node.js 18 or newer
8
+ - npm
9
+ - Lunel mobile app for QR/session pairing
10
+
11
+ ## Usage
12
+
13
+ Run the published package:
14
+
15
+ ```bash
16
+ npx lunel-cli
17
+ ```
18
+
19
+ The CLI prints a QR code and session details. Scan the QR code with the Lunel app to connect to the current working directory.
20
+
21
+ Common options:
22
+
23
+ ```bash
24
+ npx lunel-cli --help
25
+ npx lunel-cli --new
26
+ npx lunel-cli --debug
27
+ npx lunel-cli --extra-ports 3000,8080
28
+ ```
29
+
30
+ Options:
31
+
32
+ | Option | Description |
33
+ | --- | --- |
34
+ | `-h`, `--help` | Show CLI help |
35
+ | `-n`, `--new` | Create a fresh session code instead of reusing the saved one |
36
+ | `-d`, `--debug` | Enable verbose CLI and AI backend logs |
37
+ | `--extra-ports` | Comma-separated local ports to expose through Lunel |
38
+
39
+ ## Configuration
40
+
41
+ By default, the CLI uses the public Lunel services:
42
+
43
+ - Gateway: `https://gateway.lunel.dev`
44
+ - Manager: `https://manager.lunel.dev`
45
+
46
+ Override them with environment variables when developing against local or custom infrastructure:
47
+
48
+ ```bash
49
+ LUNEL_PROXY_URL=http://localhost:3001 \
50
+ LUNEL_MANAGER_URL=http://localhost:3002 \
51
+ npx lunel-cli
52
+ ```
53
+
54
+ Other useful environment variables:
55
+
56
+ | Variable | Description |
57
+ | --- | --- |
58
+ | `LUNEL_PROXY_URL` | Gateway/proxy URL |
59
+ | `LUNEL_MANAGER_URL` | Manager URL |
60
+ | `LUNEL_DEBUG` | Set to `1` for debug logging |
61
+ | `LUNEL_DEBUG_AI` | Set to `1` for AI backend debug logging |
62
+ | `NO_COLOR` | Disable colored terminal output |
63
+ | `FORCE_COLOR` | Force colored terminal output |
64
+
65
+ Session config is saved per project root in the OS-specific Lunel config directory:
66
+
67
+ - macOS: `~/Library/Application Support/lunel/config.json`
68
+ - Windows: `%APPDATA%\lunel\config.json`
69
+ - Linux: `$XDG_CONFIG_HOME/lunel/config.json` or `~/.config/lunel/config.json`
70
+
71
+ ## Development
72
+
73
+ Install dependencies:
74
+
75
+ ```bash
76
+ npm install
77
+ ```
78
+
79
+ Build the CLI:
80
+
81
+ ```bash
82
+ npm run build
83
+ ```
84
+
85
+ Run from source output:
86
+
87
+ ```bash
88
+ npm run dev
89
+ ```
90
+
91
+ The package entrypoint is `dist/index.js`, generated from `src/index.ts`. `npm run build` compiles TypeScript and marks the generated entrypoint executable.
92
+
93
+ ## Project Layout
94
+
95
+ ```text
96
+ src/
97
+ index.ts CLI entrypoint and local machine bridge
98
+ ai/ Codex/OpenCode provider integration
99
+ transport/ Session transport protocol
100
+ libsodium-wrappers.d.ts
101
+ ```
102
+
103
+ ## Publishing
104
+
105
+ The package is published as `lunel-cli`. `prepublishOnly` runs the production build before publishing.
106
+
107
+ ```bash
108
+ npm publish
109
+ ```
@@ -29,6 +29,9 @@ export declare class AiManager {
29
29
  getMessages(backend: AiBackend, sessionId: string): Promise<{
30
30
  messages: import("./interface.js").MessageInfo[];
31
31
  }>;
32
+ statuses(backend: AiBackend): Promise<{
33
+ statuses: Record<string, unknown>;
34
+ }>;
32
35
  prompt(backend: AiBackend, sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
33
36
  ack: true;
34
37
  }>;
package/dist/ai/index.js CHANGED
@@ -74,6 +74,12 @@ export class AiManager {
74
74
  deleteSession(backend, id) { return this.get(backend).deleteSession(id); }
75
75
  renameSession(backend, id, title) { return this.get(backend).renameSession(id, title); }
76
76
  getMessages(backend, sessionId) { return this.get(backend).getMessages(sessionId); }
77
+ async statuses(backend) {
78
+ const provider = this.get(backend);
79
+ if (!provider.statuses)
80
+ return { statuses: {} };
81
+ return provider.statuses();
82
+ }
77
83
  prompt(backend, sessionId, text, model, agent, files, codexOptions) {
78
84
  this.get(backend).setActiveSession?.(sessionId);
79
85
  return this.get(backend).prompt(sessionId, text, model, agent, files, codexOptions);
@@ -67,6 +67,9 @@ export interface AIProvider {
67
67
  getMessages(sessionId: string): Promise<{
68
68
  messages: MessageInfo[];
69
69
  }>;
70
+ statuses?(): Promise<{
71
+ statuses: Record<string, unknown>;
72
+ }>;
70
73
  prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
71
74
  ack: true;
72
75
  }>;
@@ -33,6 +33,9 @@ export declare class OpenCodeProvider implements AIProvider {
33
33
  getMessages(sessionId: string): Promise<{
34
34
  messages: MessageInfo[];
35
35
  }>;
36
+ statuses(): Promise<{
37
+ statuses: Record<string, unknown>;
38
+ }>;
36
39
  prompt(sessionId: string, text: string, model?: ModelSelector, agent?: string, files?: FileAttachment[], codexOptions?: CodexPromptOptions): Promise<{
37
40
  ack: true;
38
41
  }>;
@@ -62,6 +65,7 @@ export declare class OpenCodeProvider implements AIProvider {
62
65
  private refreshPendingQuestions;
63
66
  private fetchOpenCodeJson;
64
67
  private refreshSessionStatuses;
68
+ private fetchSessionStatuses;
65
69
  private trackPermissionEvent;
66
70
  private readString;
67
71
  private asRecord;
@@ -402,6 +402,9 @@ export class OpenCodeProvider {
402
402
  throw err;
403
403
  }
404
404
  }
405
+ async statuses() {
406
+ return { statuses: await this.fetchSessionStatuses() };
407
+ }
405
408
  // -------------------------------------------------------------------------
406
409
  // Interaction
407
410
  // -------------------------------------------------------------------------
@@ -806,10 +809,22 @@ export class OpenCodeProvider {
806
809
  return response.json().catch(() => null);
807
810
  }
808
811
  async refreshSessionStatuses() {
812
+ const payload = await this.fetchSessionStatuses();
813
+ for (const [sessionId, status] of Object.entries(payload)) {
814
+ this.emitter?.({
815
+ type: "session.status",
816
+ properties: {
817
+ sessionID: sessionId,
818
+ status: status,
819
+ },
820
+ });
821
+ }
822
+ }
823
+ async fetchSessionStatuses() {
809
824
  const server = this.server;
810
825
  const authHeader = this.authHeader;
811
826
  if (!server || !authHeader) {
812
- return;
827
+ return {};
813
828
  }
814
829
  const url = new URL("/session/status", server.url);
815
830
  const response = await fetch(url, {
@@ -819,21 +834,13 @@ export class OpenCodeProvider {
819
834
  },
820
835
  });
821
836
  if (!response.ok) {
822
- return;
837
+ return {};
823
838
  }
824
839
  const payload = await response.json().catch(() => null);
825
840
  if (!payload || typeof payload !== "object") {
826
- return;
827
- }
828
- for (const [sessionId, status] of Object.entries(payload)) {
829
- this.emitter?.({
830
- type: "session.status",
831
- properties: {
832
- sessionID: sessionId,
833
- status: status,
834
- },
835
- });
841
+ return {};
836
842
  }
843
+ return payload;
837
844
  }
838
845
  trackPermissionEvent(type, properties) {
839
846
  if (type === "permission.updated") {
package/dist/index.js CHANGED
@@ -2728,6 +2728,9 @@ async function processMessage(message) {
2728
2728
  case "getMessages":
2729
2729
  result = await aiManager.getMessages(backend, payload.id);
2730
2730
  break;
2731
+ case "statuses":
2732
+ result = await aiManager.statuses(backend);
2733
+ break;
2731
2734
  case "abort":
2732
2735
  result = await aiManager.abort(backend, payload.sessionId);
2733
2736
  break;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lunel-cli",
3
- "version": "0.1.121",
3
+ "version": "0.1.122",
4
4
  "author": [
5
5
  {
6
6
  "name": "Soham Bharambe",