ikie-cli 0.1.32 → 0.1.33
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 +168 -22
- package/dist/agent.js +14 -8
- package/dist/repl.js +18 -0
- package/dist/tools.js +62 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,43 +1,189 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Ikie
|
|
2
2
|
|
|
3
|
-
**Agentic coding CLI
|
|
3
|
+
**Agentic coding CLI — your AI pair programmer in the terminal.**
|
|
4
|
+
|
|
5
|
+
Ikie reads, writes, and refactors code, runs commands, searches the web, and
|
|
6
|
+
drives multi-step engineering tasks autonomously — all from your shell, with a
|
|
7
|
+
polished interactive REPL and a one-shot mode for quick jobs.
|
|
4
8
|
|
|
5
9
|
```bash
|
|
6
10
|
npm install -g ikie-cli
|
|
7
11
|
ikie login
|
|
8
|
-
ikie "write a rust web server"
|
|
12
|
+
ikie "write a rust web server with graceful shutdown"
|
|
9
13
|
```
|
|
10
14
|
|
|
11
|
-
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Highlights
|
|
18
|
+
|
|
19
|
+
- **Autonomous agent loop** — Ikie plans, edits files, runs builds/tests, reads
|
|
20
|
+
the errors, and self-corrects until the task is done.
|
|
21
|
+
- **Plan mode & agent mode** — research read-only and propose a plan, or execute
|
|
22
|
+
with full tool access. Toggle live with **Shift+Tab**.
|
|
23
|
+
- **28 built-in tools** — files, shell, search, git, web, memory, sub-agents.
|
|
24
|
+
- **Skills** — installable instruction packs that give Ikie expert knowledge for
|
|
25
|
+
a specific kind of task (UI/UX, research, framework conventions, …).
|
|
26
|
+
- **MCP support** — extend Ikie with Model Context Protocol servers (GitHub,
|
|
27
|
+
databases, browser automation, and any custom MCP).
|
|
28
|
+
- **Polished terminal UX** — markdown rendering, slash-command menu, 7 color
|
|
29
|
+
themes, image paste (Ctrl+V), session save/load, and live token/usage tracking.
|
|
30
|
+
- **Safe by default** — mutating actions ask for permission once (press `a` to
|
|
31
|
+
always-allow for the session); reads of secret files (`.env`, keys) are guarded.
|
|
12
32
|
|
|
13
|
-
|
|
14
|
-
- Interactive REPL with slash commands, markdown rendering, and session management
|
|
15
|
-
- One-shot mode: `ikie "your prompt"`
|
|
16
|
-
- Image paste support (Ctrl+V)
|
|
17
|
-
- Theming (7 color schemes)
|
|
33
|
+
---
|
|
18
34
|
|
|
19
35
|
## Quick start
|
|
20
36
|
|
|
21
37
|
```bash
|
|
22
|
-
# Install
|
|
23
|
-
npm install -g ikie
|
|
38
|
+
# 1. Install globally
|
|
39
|
+
npm install -g ikie-cli
|
|
24
40
|
|
|
25
|
-
# Sign in to your
|
|
41
|
+
# 2. Sign in to your Ikie account
|
|
26
42
|
ikie login
|
|
27
43
|
|
|
28
|
-
#
|
|
29
|
-
ikie "
|
|
44
|
+
# 3a. One-shot — run a single task and exit
|
|
45
|
+
ikie "add input validation to src/api/users.ts and write tests"
|
|
46
|
+
|
|
47
|
+
# 3b. Interactive — start a REPL session
|
|
48
|
+
ikie
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Requirements:** Node.js 20+ and an Ikie account (`ikie login`).
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Modes
|
|
56
|
+
|
|
57
|
+
Ikie runs in one of two modes, shown in the prompt header:
|
|
58
|
+
|
|
59
|
+
| Mode | What it can do |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| **agent** *(default)* | Full access — edit files, run commands, everything. |
|
|
62
|
+
| **plan** | Read-only research. Ikie explores and proposes a plan but makes no changes until you approve. |
|
|
63
|
+
|
|
64
|
+
Switch any time with **Shift+Tab** (toggles in place), or with `/plan`, `/agent`,
|
|
65
|
+
and `/mode`. When a plan is approved, Ikie automatically switches to agent mode
|
|
66
|
+
and carries it out.
|
|
67
|
+
|
|
68
|
+
---
|
|
69
|
+
|
|
70
|
+
## Tools
|
|
71
|
+
|
|
72
|
+
Ikie has 28 built-in tools, grouped by purpose:
|
|
73
|
+
|
|
74
|
+
- **Files** — `read_file`, `write_file`, `edit_file` (surgical exact-string edits), `list_dir`
|
|
75
|
+
- **Search** — `search_files` (glob), `grep` (regex over contents)
|
|
76
|
+
- **Shell** — `bash` (builds, tests, package managers; `&` backgrounds long-running processes)
|
|
77
|
+
- **Git** — `git_status`, `git_diff`, `git_log`, `git_commit`, `git_branch`
|
|
78
|
+
- **Web** — `fetch_url` (read any page as text), `web_search` (no extra API key — your login is enough)
|
|
79
|
+
- **Memory** — `memory_write` (persist notes across sessions, project- or global-scoped)
|
|
80
|
+
- **Delegation** — `spawn_agent` (hand isolated/parallel work to a focused sub-agent), `ask_user`
|
|
81
|
+
- **Skills** — `use_skill`, `install_skill`, `remove_skill`
|
|
82
|
+
- **MCP** — `mcp_list`, `mcp_add`, `mcp_install`, `mcp_start`, `mcp_stop`, `mcp_call`, `mcp_uninstall`
|
|
83
|
+
- **Mode** — `switch_mode`
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Skills
|
|
88
|
+
|
|
89
|
+
Skills are curated instruction packs (and optional bundled scripts) that load on
|
|
90
|
+
demand when a task matches them. Install from a git URL or local path:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
ikie skills install https://github.com/user/some-skill.git
|
|
94
|
+
ikie skills list
|
|
95
|
+
ikie skills remove some-skill
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Inside a session, Ikie loads a matching skill automatically before doing the work.
|
|
99
|
+
You can also manage them with `/skills`.
|
|
100
|
+
|
|
101
|
+
---
|
|
102
|
+
|
|
103
|
+
## MCP (Model Context Protocol)
|
|
104
|
+
|
|
105
|
+
Extend Ikie with external MCP servers. Paste a Claude/Cline-style config and Ikie
|
|
106
|
+
will wire it up:
|
|
107
|
+
|
|
108
|
+
```
|
|
109
|
+
claude mcp add magic --scope user --env API_KEY="…" -- npx -y @21st-dev/magic@latest
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
Then start it and its tools become available:
|
|
113
|
+
|
|
114
|
+
```
|
|
115
|
+
/ (use the slash menu) → mcp_start magic
|
|
30
116
|
```
|
|
31
117
|
|
|
32
|
-
|
|
118
|
+
Built-in MCPs include **filesystem**, **github**, **database** (SQLite/Postgres),
|
|
119
|
+
and **puppeteer** (browser automation).
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## In-session commands
|
|
124
|
+
|
|
125
|
+
Type `/` to open the command menu. Highlights:
|
|
126
|
+
|
|
127
|
+
| Command | Description |
|
|
128
|
+
| --- | --- |
|
|
129
|
+
| `/help` | Show all commands |
|
|
130
|
+
| `/plan` · `/agent` · `/mode` | Switch or show mode *(Shift+Tab toggles)* |
|
|
131
|
+
| `/clear` | Clear conversation history |
|
|
132
|
+
| `/compact` | Summarize the conversation to free up context |
|
|
133
|
+
| `/session list\|load\|new\|delete` | Manage saved sessions |
|
|
134
|
+
| `/memory [save]` | View or save persistent notes |
|
|
135
|
+
| `/context` | Show the detected project context |
|
|
136
|
+
| `/model <name>` · `/models` | Switch or list models |
|
|
137
|
+
| `/settings [show\|model\|reset]` | View/change persisted settings |
|
|
138
|
+
| `/skills` | List, show, install, or remove skills |
|
|
139
|
+
| `/theme [name]` | Change the color theme |
|
|
140
|
+
| `/usage` · `/tokens` | Account usage/credit and token estimate |
|
|
141
|
+
| `/rpm <n>` | Set the model request-per-minute limit |
|
|
142
|
+
| `/onboarding` | Re-run the first-time tutorial |
|
|
143
|
+
| `!<cmd>` | Run a shell command directly (output lands in the session) |
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## CLI usage
|
|
148
|
+
|
|
149
|
+
```text
|
|
150
|
+
ikie "<message>" One-shot command
|
|
151
|
+
ikie Start an interactive session
|
|
152
|
+
ikie login Sign in to your Ikie account
|
|
153
|
+
ikie logout Sign out
|
|
154
|
+
ikie skills <…> Manage skills (list / install / remove)
|
|
155
|
+
|
|
156
|
+
Flags:
|
|
157
|
+
-m, --model <id> Use a specific model
|
|
158
|
+
-y, --yes Auto-approve all tool executions
|
|
159
|
+
--rpm <n> Max model requests per minute (default: 10)
|
|
160
|
+
--verbose Debug output
|
|
161
|
+
--onboarding Re-run first-time onboarding
|
|
162
|
+
-h, --help Show help
|
|
163
|
+
-v, --version Show version
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Themes
|
|
169
|
+
|
|
170
|
+
Seven built-in color schemes: **nebula**, **cyberpunk**, **dracula**, **forest**,
|
|
171
|
+
**slate**, **amber**, and **aurora**. Switch with `/theme <name>`.
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
## Permissions & safety
|
|
33
176
|
|
|
34
|
-
|
|
177
|
+
- `bash`, `write_file`, and `edit_file` ask before running. Press `y` to allow
|
|
178
|
+
once, `a` to always-allow that tool for the session, `n`/`!` to deny.
|
|
179
|
+
- Reading project files is silent; reading credential files (`.env`, `.ssh`, keys,
|
|
180
|
+
`.npmrc`, …) prompts first.
|
|
181
|
+
- Ikie warns before any command that could terminate its own session by killing
|
|
182
|
+
processes on its host port.
|
|
183
|
+
- Run with `-y` / `--yes` to auto-approve everything (use with care).
|
|
35
184
|
|
|
36
|
-
|
|
37
|
-
- **`web_search`** — search the web and get back titles, URLs, and snippets. Powered by the ikie
|
|
38
|
-
server — no separate search API key needed; your ikie login is enough.
|
|
185
|
+
---
|
|
39
186
|
|
|
40
|
-
##
|
|
187
|
+
## License
|
|
41
188
|
|
|
42
|
-
|
|
43
|
-
- An ikie account — sign in with `ikie login`
|
|
189
|
+
MIT — see [LICENSE](./LICENSE).
|
package/dist/agent.js
CHANGED
|
@@ -1000,13 +1000,19 @@ to disambiguate. Make the smallest edit that fixes the root cause; don't reflow
|
|
|
1000
1000
|
untouched code. Use \`write_file\` only for brand-new files or deliberate full rewrites,
|
|
1001
1001
|
and always write the COMPLETE content.
|
|
1002
1002
|
|
|
1003
|
-
**5. bash hygiene.**
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1003
|
+
**5. bash hygiene.** By default it's non-interactive, so prefer flags that skip
|
|
1004
|
+
prompts (\`-y\`/\`--yes\`, or pass every option explicitly, e.g. \`create-next-app\`'s
|
|
1005
|
+
\`--ts --tailwind --eslint --app\`). But when a command shows an **interactive
|
|
1006
|
+
arrow-key menu or prompt that has no flag** (e.g. \`shadcn init\`'s component-library
|
|
1007
|
+
picker), do NOT keep retrying with piped input — call bash with \`interactive: true\`.
|
|
1008
|
+
That hands the real terminal to the command so the **user answers directly**; output
|
|
1009
|
+
isn't captured, so afterward read any files it created to see the result. Also: quote
|
|
1010
|
+
paths with spaces; chain with \`&&\` so a failure stops the chain; background
|
|
1011
|
+
long-running servers with a trailing \`&\`; raise \`timeout_ms\` for slow installs. Check
|
|
1012
|
+
the exit code — a non-zero exit means it failed, so read the error rather than moving
|
|
1013
|
+
on. **Avoid killing processes by port** (\`kill $(lsof -ti:PORT)\`, \`fuser -k\`): it can
|
|
1014
|
+
match ikie's own connection and end the session — target a specific PID, or stop the
|
|
1015
|
+
process you started, instead.
|
|
1010
1016
|
|
|
1011
1017
|
**6. Recover from errors deliberately.** When a tool fails, read the actual message,
|
|
1012
1018
|
form a hypothesis, and change your approach — never re-run the identical failing call
|
|
@@ -1024,7 +1030,7 @@ only the non-obvious. Use \`ask_user\` only when truly blocked on a decision you
|
|
|
1024
1030
|
- \`write_file\`: Create new files or full rewrites
|
|
1025
1031
|
- \`edit_file\`: Replace exact strings (preferred for modifications)
|
|
1026
1032
|
- \`bash\`: Run shell commands (build, test, git, etc.). Commands ending with & run detached in background.
|
|
1027
|
-
**IMPORTANT:**
|
|
1033
|
+
**IMPORTANT:** By default it's non-interactive — for commands that ask questions (create-next-app, npm init, etc.), skip prompts with \`--yes\`/\`-y\` or explicit flags. For prompts with no flag (e.g. an arrow-key menu), set \`interactive: true\` so the user answers in the real terminal. For long-running downloads (npx installs), request \`timeout_ms\` up to 300000.
|
|
1028
1034
|
- \`list_dir\`: Explore directory structure
|
|
1029
1035
|
- \`search_files\`: Find files by glob pattern
|
|
1030
1036
|
- \`grep\`: Search file contents by regex
|
package/dist/repl.js
CHANGED
|
@@ -981,6 +981,16 @@ export async function startREPL(agent, config, projectContext, oneShot) {
|
|
|
981
981
|
historySize: MAX_HISTORY,
|
|
982
982
|
prompt: PROMPT,
|
|
983
983
|
});
|
|
984
|
+
// Enable bracketed-paste mode so the terminal wraps pasted text in
|
|
985
|
+
// \x1b[200~ … \x1b[201~ markers. This lets a multi-chunk paste (a long
|
|
986
|
+
// paragraph the TTY delivers across several reads) be coalesced into ONE
|
|
987
|
+
// paste instead of being split into several. Disabled again on exit.
|
|
988
|
+
const setBracketedPaste = (on) => {
|
|
989
|
+
if (process.stdout.isTTY)
|
|
990
|
+
process.stdout.write(on ? '\x1b[?2004h' : '\x1b[?2004l');
|
|
991
|
+
};
|
|
992
|
+
setBracketedPaste(true);
|
|
993
|
+
process.on('exit', () => setBracketedPaste(false));
|
|
984
994
|
let multilineBuffer = '';
|
|
985
995
|
let busy = false;
|
|
986
996
|
let ctrlCCount = 0;
|
|
@@ -1083,6 +1093,13 @@ export async function startREPL(agent, config, projectContext, oneShot) {
|
|
|
1083
1093
|
const normalized = content.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
|
|
1084
1094
|
if (!normalized)
|
|
1085
1095
|
return;
|
|
1096
|
+
// Short, single-line pastes (a word, a path, a URL) belong inline as if
|
|
1097
|
+
// typed — only collapse multi-line or long pastes into a [Pasted #N] block.
|
|
1098
|
+
if (!normalized.includes('\n') && normalized.length <= 200) {
|
|
1099
|
+
forwardToReadline(Buffer.from(normalized, 'utf8'));
|
|
1100
|
+
updateMenu();
|
|
1101
|
+
return;
|
|
1102
|
+
}
|
|
1086
1103
|
const token = `[Pasted #${++pasteSeq}: ${pasteSummary(normalized)}]`;
|
|
1087
1104
|
pastedBlocks.set(token, normalized);
|
|
1088
1105
|
rl.write(token);
|
|
@@ -1250,6 +1267,7 @@ export async function startREPL(agent, config, projectContext, oneShot) {
|
|
|
1250
1267
|
rl.prompt();
|
|
1251
1268
|
};
|
|
1252
1269
|
rl.on('close', () => {
|
|
1270
|
+
setBracketedPaste(false);
|
|
1253
1271
|
printGoodbye(sessionState, agent, config);
|
|
1254
1272
|
process.exit(0);
|
|
1255
1273
|
});
|
package/dist/tools.js
CHANGED
|
@@ -64,6 +64,7 @@ export const TOOL_DEFS = [
|
|
|
64
64
|
command: { type: 'string', description: 'Shell command' },
|
|
65
65
|
timeout_ms: { type: 'number', description: 'Timeout ms (default 30000)' },
|
|
66
66
|
cwd: { type: 'string', description: 'Working directory' },
|
|
67
|
+
interactive: { type: 'boolean', description: 'Set true for commands that need an interactive terminal — ones that show arrow-key menus or prompts that cannot be skipped with flags (e.g. `shadcn init`, `create-next-app`, `npm init` without -y). The command is connected to the real terminal so the USER answers the prompts directly. Output is shown live, not captured, so the result only reports the exit status — read any files it creates afterward.' },
|
|
67
68
|
},
|
|
68
69
|
required: ['command'],
|
|
69
70
|
},
|
|
@@ -623,6 +624,9 @@ async function bash(input) {
|
|
|
623
624
|
cwd = resolve(input.cwd);
|
|
624
625
|
}
|
|
625
626
|
const command = input.command.trim();
|
|
627
|
+
if (input.interactive) {
|
|
628
|
+
return bashInteractive(command, cwd);
|
|
629
|
+
}
|
|
626
630
|
if (command.endsWith('&')) {
|
|
627
631
|
const bgCmd = command.slice(0, -1).trim();
|
|
628
632
|
try {
|
|
@@ -670,6 +674,64 @@ async function bash(input) {
|
|
|
670
674
|
return `Exit ${e.code ?? 1}\n${parts.join('\n')}`;
|
|
671
675
|
}
|
|
672
676
|
}
|
|
677
|
+
/**
|
|
678
|
+
* Runs a command attached to the real terminal (stdio: 'inherit') so the USER
|
|
679
|
+
* can answer interactive prompts (arrow-key menus, y/N questions) that the
|
|
680
|
+
* non-interactive path cannot handle. Temporarily detaches the REPL's own stdin
|
|
681
|
+
* listeners and raw mode while the child owns the terminal, then restores them.
|
|
682
|
+
* Output is not captured — only the exit status is reported back to the agent.
|
|
683
|
+
*/
|
|
684
|
+
function bashInteractive(command, cwd) {
|
|
685
|
+
return new Promise((resolvePromise) => {
|
|
686
|
+
const stdin = process.stdin;
|
|
687
|
+
const isTTY = Boolean(stdin.isTTY);
|
|
688
|
+
const wasRaw = isTTY ? Boolean(stdin.isRaw) : false;
|
|
689
|
+
// Save and detach whatever the REPL has on stdin (cancel handler, etc.) so
|
|
690
|
+
// the child receives keystrokes directly.
|
|
691
|
+
const saved = isTTY ? stdin.rawListeners('data').slice() : [];
|
|
692
|
+
for (const l of saved)
|
|
693
|
+
stdin.removeListener('data', l);
|
|
694
|
+
const restore = () => {
|
|
695
|
+
if (isTTY) {
|
|
696
|
+
try {
|
|
697
|
+
stdin.setRawMode(wasRaw);
|
|
698
|
+
}
|
|
699
|
+
catch { /* ignore */ }
|
|
700
|
+
if (process.stdout.isTTY)
|
|
701
|
+
process.stdout.write('\x1b[?2004h'); // re-arm bracketed paste
|
|
702
|
+
}
|
|
703
|
+
for (const l of saved)
|
|
704
|
+
stdin.on('data', l);
|
|
705
|
+
};
|
|
706
|
+
if (isTTY) {
|
|
707
|
+
try {
|
|
708
|
+
stdin.setRawMode(false);
|
|
709
|
+
}
|
|
710
|
+
catch { /* ignore */ }
|
|
711
|
+
if (process.stdout.isTTY)
|
|
712
|
+
process.stdout.write('\x1b[?2004l'); // disable bracketed paste for the child
|
|
713
|
+
}
|
|
714
|
+
process.stdout.write('\n');
|
|
715
|
+
try {
|
|
716
|
+
const isWindows = process.platform === 'win32';
|
|
717
|
+
const child = spawn(isWindows ? 'cmd.exe' : 'bash', isWindows ? ['/d', '/s', '/c', command] : ['-c', command], { cwd, stdio: 'inherit' });
|
|
718
|
+
child.on('error', (err) => {
|
|
719
|
+
restore();
|
|
720
|
+
resolvePromise(`Error running interactive command: ${sanitizeError(err)}`);
|
|
721
|
+
});
|
|
722
|
+
child.on('exit', (code) => {
|
|
723
|
+
restore();
|
|
724
|
+
resolvePromise(code === 0
|
|
725
|
+
? '(interactive command completed — output was shown to the user; read any created/changed files to see the result)'
|
|
726
|
+
: `Exit ${code ?? 1} (interactive command)`);
|
|
727
|
+
});
|
|
728
|
+
}
|
|
729
|
+
catch (err) {
|
|
730
|
+
restore();
|
|
731
|
+
resolvePromise(`Error running interactive command: ${sanitizeError(err)}`);
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
}
|
|
673
735
|
function listDir(input) {
|
|
674
736
|
const root = resolve(input.path ?? '.');
|
|
675
737
|
if (!existsSync(root))
|