@hemacharanpyla/infinitycli 1.0.5 → 1.0.6
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 +143 -0
- package/chat.js +46 -25
- package/package.json +1 -1
package/README.md
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# ∞ Infinity CLI
|
|
2
|
+
|
|
3
|
+
**Terminal AI chat with ChatGPT via Puppeteer — real-time response timing, box-drawn UI, zero-config setup.**
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+

|
|
7
|
+

|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @hemacharanpyla/infinitycli
|
|
15
|
+
infinity
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
The server **auto-starts** on first launch — no manual `node server.js`.
|
|
19
|
+
|
|
20
|
+
## Requirements
|
|
21
|
+
|
|
22
|
+
- **Node.js >= 18**
|
|
23
|
+
- **Chrome** at default path: `C:\Program Files\Google\Chrome\Application\chrome.exe`
|
|
24
|
+
- **ChatGPT cookies** (see [Cookie Setup](#cookie-setup))
|
|
25
|
+
|
|
26
|
+
## Cookie Setup
|
|
27
|
+
|
|
28
|
+
Infinity CLI uses your ChatGPT session cookies to interact with ChatGPT on your behalf.
|
|
29
|
+
|
|
30
|
+
### Export your cookies
|
|
31
|
+
|
|
32
|
+
1. Install a cookie export extension (e.g. [EditThisCookie](https://www.editthiscookie.com/))
|
|
33
|
+
2. Log in to [chatgpt.com](https://chatgpt.com)
|
|
34
|
+
3. Export cookies as JSON
|
|
35
|
+
4. Save the file to one of these locations:
|
|
36
|
+
|
|
37
|
+
**Recommended (home dir):**
|
|
38
|
+
```
|
|
39
|
+
%USERPROFILE%\.infinitycli\cookies\chatgpt.json
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
**Or via environment variable:**
|
|
43
|
+
```bash
|
|
44
|
+
set COOKIES_PATH=C:\path\to\chatgpt.json
|
|
45
|
+
infinity
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Features
|
|
49
|
+
|
|
50
|
+
### Dashboard
|
|
51
|
+
- Welcome message with username
|
|
52
|
+
- Current model (GPT-4o), plan, and working directory
|
|
53
|
+
- Tips list and recent activity
|
|
54
|
+
|
|
55
|
+
### Chat
|
|
56
|
+
- Send messages to ChatGPT via the terminal
|
|
57
|
+
- Response timing displayed per message (`╰ 1.4s`)
|
|
58
|
+
- Message history with scrolling
|
|
59
|
+
- Loading spinner during responses
|
|
60
|
+
|
|
61
|
+
### Commands
|
|
62
|
+
|
|
63
|
+
| Command | Description |
|
|
64
|
+
|---------|-------------|
|
|
65
|
+
| `/help` or `/h` or `/?` | Show help panel |
|
|
66
|
+
| `/clear` or `/cls` | Clear conversation |
|
|
67
|
+
| `/exit` or `/quit` | Exit session |
|
|
68
|
+
| `/status` | Show session & connection info |
|
|
69
|
+
| `?` | Toggle help panel |
|
|
70
|
+
|
|
71
|
+
### Keyboard Shortcuts
|
|
72
|
+
|
|
73
|
+
| Key | Action |
|
|
74
|
+
|-----|--------|
|
|
75
|
+
| `Enter` | Send message |
|
|
76
|
+
| `Shift+Enter` | Newline in input |
|
|
77
|
+
| `↑` / `↓` | History navigation |
|
|
78
|
+
| `Ctrl+L` | Clear chat |
|
|
79
|
+
| `Ctrl+U` | Clear current input |
|
|
80
|
+
| `Ctrl+C` | Exit application |
|
|
81
|
+
|
|
82
|
+
## Environment Variables
|
|
83
|
+
|
|
84
|
+
| Variable | Default | Description |
|
|
85
|
+
|----------|---------|-------------|
|
|
86
|
+
| `API_BASE` | `http://localhost:3000` | Backend server URL |
|
|
87
|
+
| `MODEL` | `GPT-4o` | Displayed model name |
|
|
88
|
+
| `COOKIES_PATH` | — | Path to ChatGPT cookies JSON |
|
|
89
|
+
| `CHROME_PATH` | `C:\Program Files\...\chrome.exe` | Chrome executable path |
|
|
90
|
+
| `CHROME_DEBUG_PORT` | `9222` | Remote debugging port |
|
|
91
|
+
| `PORT` | `3000` | Server port |
|
|
92
|
+
| `MAX_SESSIONS` | `20` | Max concurrent ChatGPT sessions |
|
|
93
|
+
| `MAX_CONCURRENT_PAGE_CREATES` | `3` | Max concurrent page opens |
|
|
94
|
+
| `MAX_CONCURRENT_MESSAGES` | `5` | Max concurrent messages |
|
|
95
|
+
|
|
96
|
+
## Architecture
|
|
97
|
+
|
|
98
|
+
```
|
|
99
|
+
┌─────────────────────────────────────────────┐
|
|
100
|
+
│ CLI (Node.js) │
|
|
101
|
+
│ ┌──────────────┐ ┌──────────────────┐ │
|
|
102
|
+
│ │ bin/ │───▶│ express + │ │
|
|
103
|
+
│ │ infinity.js │ │ puppeteer-core │ │
|
|
104
|
+
│ │ (auto-start) │ │ server │ │
|
|
105
|
+
│ └──────────────┘ └────────┬─────────┘ │
|
|
106
|
+
│ │ │
|
|
107
|
+
│ ┌──────────────────┐ │ │
|
|
108
|
+
│ │ chat.js │◀────────┘ │
|
|
109
|
+
│ │ (TTY UI) │ │
|
|
110
|
+
│ └──────────────────┘ │
|
|
111
|
+
│ │ │
|
|
112
|
+
└───────────────────────────────┼──────────────┘
|
|
113
|
+
│
|
|
114
|
+
┌───────────▼───────────┐
|
|
115
|
+
│ Chrome (headless) │
|
|
116
|
+
│ → chatgpt.com │
|
|
117
|
+
└───────────────────────┘
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- `bin/infinity.js` — Entry point; auto-starts the server
|
|
121
|
+
- `chat.js` — Full-screen box-drawn TTY UI (zero dependencies)
|
|
122
|
+
- `server.js` — Express + Puppeteer backend for ChatGPT
|
|
123
|
+
|
|
124
|
+
## Development
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
git clone https://github.com/hemacharanpyla/infinity-cli.git
|
|
128
|
+
cd infinity-cli
|
|
129
|
+
npm install
|
|
130
|
+
node bin/infinity.js # run CLI (auto-starts server)
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## Package
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npm install -g @hemacharanpyla/infinitycli
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Published to [npm](https://www.npmjs.com/package/@hemacharanpyla/infinitycli).
|
|
140
|
+
|
|
141
|
+
## License
|
|
142
|
+
|
|
143
|
+
MIT © [Charan](https://github.com/hemacharanpyla)
|
package/chat.js
CHANGED
|
@@ -112,23 +112,35 @@ const SEP = `${GR}${"─".repeat(W)}${R}`;
|
|
|
112
112
|
// ─── Dashboard content ────────────────────────────────────
|
|
113
113
|
function buildDashboard() {
|
|
114
114
|
const lines = [];
|
|
115
|
+
const logoW = Math.min(W - 4, 38);
|
|
116
|
+
const padL = " ".repeat(Math.floor((W - 4 - logoW) / 2));
|
|
117
|
+
|
|
118
|
+
// ── Logo banner ──
|
|
115
119
|
lines.push("");
|
|
116
|
-
lines.push(` ${
|
|
117
|
-
lines.push(
|
|
118
|
-
lines.push(` ${
|
|
119
|
-
lines.push(` ${
|
|
120
|
-
lines.push(` ${GR}Plan:${R} ${P}Pro${R}`);
|
|
121
|
-
lines.push(` ${GR}Path:${R} ${C}${process.cwd()}${R}`);
|
|
120
|
+
lines.push(` ${padL}${BO}╔${"═".repeat(logoW)}╗${R}`);
|
|
121
|
+
lines.push(` ${padL}${BO}║${R} ${O}∞${R} ${B}I N F I N I T Y${R} ${O}∞${R} ${BO}║${R}`);
|
|
122
|
+
lines.push(` ${padL}${BO}║${R} ${GR}Terminal AI Chat${R} ${BO}║${R}`);
|
|
123
|
+
lines.push(` ${padL}${BO}╚${"═".repeat(logoW)}╝${R}`);
|
|
122
124
|
lines.push("");
|
|
123
|
-
|
|
125
|
+
|
|
126
|
+
// ── User info row ──
|
|
127
|
+
lines.push(` ${GR}Welcome,${R} ${BC}${USER}${R}`);
|
|
128
|
+
lines.push(` ${GR}Model:${R} ${BO}${MODEL}${R} ${GR}Plan:${R} ${BP}Pro${R} ${GR}v1.0.5${R}`);
|
|
129
|
+
lines.push(` ${GR}Path:${R} ${C}${process.cwd()}${R}`);
|
|
124
130
|
lines.push("");
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
lines.push(` ${O}
|
|
128
|
-
lines.push(` ${
|
|
129
|
-
lines.push(` ${O}
|
|
131
|
+
|
|
132
|
+
// ── Tips section ──
|
|
133
|
+
lines.push(` ${O}${"─".repeat(Math.min(W - 2, 54))}${R}`);
|
|
134
|
+
lines.push(` ${B}Quick Tips${R}`);
|
|
135
|
+
lines.push(` ${O}●${R} ${G}/help${R} ${GR}Show available commands${R}`);
|
|
136
|
+
lines.push(` ${O}●${R} ${G}/clear${R} ${GR}Clear conversation${R}`);
|
|
137
|
+
lines.push(` ${O}●${R} ${G}/exit${R} ${GR}Exit the session${R}`);
|
|
138
|
+
lines.push(` ${O}●${R} ${G}/status${R} ${GR}Show session & connection info${R}`);
|
|
130
139
|
lines.push("");
|
|
131
|
-
|
|
140
|
+
|
|
141
|
+
// ── Activity section ──
|
|
142
|
+
lines.push(` ${O}${"─".repeat(Math.min(W - 2, 54))}${R}`);
|
|
143
|
+
lines.push(` ${B}Recent Activity${R}`);
|
|
132
144
|
lines.push(` ${GR} No recent activity${R}`);
|
|
133
145
|
lines.push("");
|
|
134
146
|
|
|
@@ -156,18 +168,21 @@ function buildHelpPanel() {
|
|
|
156
168
|
|
|
157
169
|
const lines = [];
|
|
158
170
|
lines.push("");
|
|
159
|
-
lines.push(` ${
|
|
160
|
-
lines.push(` ${
|
|
171
|
+
lines.push(` ${O}${"═".repeat(30)}${R}`);
|
|
172
|
+
lines.push(` ${BO}╔═ Commands ═══════════════════╗${R}`);
|
|
161
173
|
for (const [k, v] of cmds) {
|
|
162
|
-
lines.push(` ${O}●${R} ${G}${k}${R}
|
|
174
|
+
lines.push(` ${BO}║${R} ${O}●${R} ${G}${k.padEnd(10)}${R}${GR}${v}${R} ${BO}║${R}`);
|
|
163
175
|
}
|
|
176
|
+
lines.push(` ${BO}╚══════════════════════════════╝${R}`);
|
|
164
177
|
lines.push("");
|
|
165
|
-
lines.push(` ${
|
|
178
|
+
lines.push(` ${BO}╔═ Shortcuts ══════════════════╗${R}`);
|
|
166
179
|
for (const [k, v] of sc) {
|
|
167
|
-
lines.push(` ${O}●${R} ${BC}${k}${R}
|
|
180
|
+
lines.push(` ${BO}║${R} ${O}●${R} ${BC}${k.padEnd(14)}${R}${GR}${v}${R} ${BO}║${R}`);
|
|
168
181
|
}
|
|
182
|
+
lines.push(` ${BO}╚══════════════════════════════╝${R}`);
|
|
169
183
|
lines.push("");
|
|
170
|
-
lines.push(` ${
|
|
184
|
+
lines.push(` ${O}${"═".repeat(30)}${R}`);
|
|
185
|
+
lines.push(` ${GR}Press ${O}?${R}${GR} again or type a message to close${R}`);
|
|
171
186
|
lines.push("");
|
|
172
187
|
|
|
173
188
|
while (lines.length < CONTENT_H) lines.push("");
|
|
@@ -179,14 +194,20 @@ function buildHelpPanel() {
|
|
|
179
194
|
function buildChat() {
|
|
180
195
|
const entries = [];
|
|
181
196
|
|
|
182
|
-
for (
|
|
197
|
+
for (let i = 0; i < state.messages.length; i++) {
|
|
198
|
+
const msg = state.messages[i];
|
|
183
199
|
const role = msg.role === "user" ? `${BC}You${R}` : `${BP}Infinity${R}`;
|
|
184
|
-
|
|
200
|
+
|
|
201
|
+
if (i > 0) {
|
|
202
|
+
entries.push(` ${GR}${"─".repeat(Math.min(W - 2, 56))}${R}`);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
entries.push(` ${role} ${GR}${msg.ts}${R}`);
|
|
185
206
|
for (const line of msg.content.split("\n")) {
|
|
186
207
|
entries.push(` ${line}`);
|
|
187
208
|
}
|
|
188
209
|
if (msg.meta) {
|
|
189
|
-
entries.push(` ${GR}
|
|
210
|
+
entries.push(` ${O}╰${R}${GR} ${msg.meta}${R}`);
|
|
190
211
|
}
|
|
191
212
|
entries.push("");
|
|
192
213
|
}
|
|
@@ -209,7 +230,7 @@ function buildChat() {
|
|
|
209
230
|
// ─── Full render ──────────────────────────────────────────
|
|
210
231
|
function render(focusInput = true) {
|
|
211
232
|
const content = state.showHelp ? buildHelpPanel() : (state.view === "dashboard" ? buildDashboard() : buildChat());
|
|
212
|
-
const title = `${BO}Infinity CLI${R} ${GR}v1.0${R}`;
|
|
233
|
+
const title = `${D}∞${R} ${BO}Infinity CLI${R} ${GR}v1.0.5${R}`;
|
|
213
234
|
|
|
214
235
|
const statusIcon = state.loading ? `${Y}●${R}` : state.connected ? `${G}●${R}` : `${R2}○${R}`;
|
|
215
236
|
const statusRight = `${GR}${MODEL}${R} ${statusIcon} ${GR}${state.status}${R}`;
|
|
@@ -231,7 +252,7 @@ function render(focusInput = true) {
|
|
|
231
252
|
const promptText = `${P}>${R} ${state.input}`;
|
|
232
253
|
out += pos(R_PROMPT) + BOX.line(promptText);
|
|
233
254
|
|
|
234
|
-
const shortcuts = `${
|
|
255
|
+
const shortcuts = `${D}∞${R} ${GR}? help${R} ${GR}│${R} ${GR}↑↓ history${R} ${GR}│${R} ${GR}Ctrl+C exit${R}`;
|
|
235
256
|
out += pos(R_SHORTCUTS) + BOX.lineR(shortcuts, state.loading ? `${Y}● ${state.status}${R}` : `${GR}${state.messages.length} msgs${R}`);
|
|
236
257
|
|
|
237
258
|
out += pos(R_BOTTOM) + BOX.bot;
|
|
@@ -256,7 +277,7 @@ function renderPrompt() {
|
|
|
256
277
|
function updateStatus() {
|
|
257
278
|
const statusIcon = state.loading ? `${Y}●${R}` : state.connected ? `${G}●${R}` : `${R2}○${R}`;
|
|
258
279
|
const statusRight = `${GR}${MODEL}${R} ${statusIcon} ${GR}${state.status}${R}`;
|
|
259
|
-
const title = `${BO}Infinity CLI${R} ${GR}v1.0${R}`;
|
|
280
|
+
const title = `${D}∞${R} ${BO}Infinity CLI${R} ${GR}v1.0.5${R}`;
|
|
260
281
|
const titleLine = `${" ".repeat(1)}${title}${" ".repeat(Math.max(0, W - vis(title).length - vis(statusRight).length))}${statusRight}`;
|
|
261
282
|
stdout.write(`${pos(R_TITLE)}${CL}${BOX.line(titleLine)}`);
|
|
262
283
|
}
|