wispy-cli 2.7.4 → 2.7.5
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 +354 -439
- package/bin/wispy-mjs +3 -0
- package/bin/wispy.mjs +74 -11
- package/lib/commands/ws.mjs +36 -27
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,571 +1,486 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Wispy CLI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Wispy CLI is a terminal-first AI workspace assistant for operators who want one place to chat, delegate, automate, audit, remember, and hand work across local and remote sessions.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[](https://nodejs.org)
|
|
7
|
-
[](LICENSE)
|
|
5
|
+
Version `2.7.4` centers the product around an interactive workflow: onboarding, setup, and operator-facing commands guide you through menus instead of dropping you into brittle flag-heavy flows. The chat stack combines a REPL, a six-view TUI workspace, long-term memory, sub-agent orchestration, MCP, multi-channel messaging, scheduling, and a trust model built for real execution.
|
|
8
6
|
|
|
9
|
-
|
|
7
|
+
## Highlights
|
|
10
8
|
|
|
11
|
-
|
|
9
|
+
| Area | What ships in v2.7.4 |
|
|
10
|
+
| --- | --- |
|
|
11
|
+
| Model access | 29 AI providers across hosted, aggregator, OAuth, and local/self-hosted routes, including Google, Anthropic, OpenAI, Groq, DeepSeek, Ollama, OpenRouter, Mistral, Cohere, Perplexity, Together, Fireworks, Replicate, Anyscale, and GitHub Copilot |
|
|
12
|
+
| Auth | API key flows plus OAuth-based auth, including GitHub Copilot support introduced in `v2.6.0` |
|
|
13
|
+
| Interaction | Interactive command flows since `v2.7.0`; no-arg command entry routes into menus instead of dead-ending |
|
|
14
|
+
| Terminal UX | REPL with autocomplete and inline preview hints, plus shell completion auto-installed during setup |
|
|
15
|
+
| TUI | Multi-panel workspace OS with 6 views: `chat`, `overview`, `agents`, `memory`, `audit`, `settings` |
|
|
16
|
+
| Trust | `careful`, `balanced`, `yolo`, dry-run previews, receipts, approval prompts, permissions, audit trail, replay |
|
|
17
|
+
| Continuity | `where`, `handoff`, `sync` for local/remote awareness and state transfer |
|
|
18
|
+
| Memory | `remember`, `recall`, `forget`, `memories` plus persistent memory files |
|
|
19
|
+
| Skills | `teach`, `improve`, skill loading, reusable learned workflows |
|
|
20
|
+
| Orchestration | Agents, sub-agents, pipeline-style delegation, MCP integration, 18+ built-in tools |
|
|
21
|
+
| Channels | Telegram, Discord, Slack, WhatsApp, Signal, Email |
|
|
22
|
+
| Scheduling | Cron-based task scheduling with persisted jobs and history |
|
|
23
|
+
| Quality | Test suite passing: `91/91` |
|
|
12
24
|
|
|
13
|
-
|
|
14
|
-
- 🤖 **7 AI providers** — Gemini, Claude, OpenAI, Groq, DeepSeek, Ollama, OpenRouter
|
|
15
|
-
- 🔧 **18+ built-in tools** — files, shell commands, git, web search, and more
|
|
16
|
-
- 🔌 **MCP server integration** — connect any Model Context Protocol server
|
|
17
|
-
- 📱 **Multi-channel bot** — Telegram, Discord, Slack with session isolation
|
|
18
|
-
- 🧠 **Long-term memory** — persistent facts, daily logs, project notes
|
|
19
|
-
- ⏰ **Cron scheduler** — scheduled tasks with channel delivery
|
|
20
|
-
- 🤝 **Sub-agent orchestration** — spawn parallel agents, steer them, collect results
|
|
21
|
-
- 📂 **Workstream isolation** — separate contexts per project
|
|
25
|
+
## Installation
|
|
22
26
|
|
|
23
|
-
|
|
27
|
+
### Requirements
|
|
28
|
+
|
|
29
|
+
| Requirement | Version |
|
|
30
|
+
| --- | --- |
|
|
31
|
+
| Node.js | `>= 18` |
|
|
32
|
+
| Package manager | `npm` |
|
|
24
33
|
|
|
25
|
-
|
|
34
|
+
### Install globally
|
|
26
35
|
|
|
27
36
|
```bash
|
|
28
|
-
# Install globally
|
|
29
37
|
npm install -g wispy-cli
|
|
38
|
+
```
|
|
30
39
|
|
|
31
|
-
|
|
32
|
-
export GOOGLE_AI_KEY=your_key # Gemini (recommended, has free tier)
|
|
33
|
-
export ANTHROPIC_API_KEY=your_key # Claude
|
|
34
|
-
export OPENAI_API_KEY=your_key # OpenAI / GPT
|
|
40
|
+
### Run
|
|
35
41
|
|
|
36
|
-
|
|
42
|
+
```bash
|
|
37
43
|
wispy
|
|
38
44
|
```
|
|
39
45
|
|
|
40
|
-
Wispy
|
|
46
|
+
On first run, Wispy launches guided setup, helps configure a provider, and installs shell completion automatically for supported shells.
|
|
41
47
|
|
|
42
|
-
|
|
48
|
+
## Quick Start
|
|
43
49
|
|
|
44
|
-
|
|
50
|
+
### Start the main REPL
|
|
45
51
|
|
|
46
|
-
### Requirements
|
|
47
|
-
- **Node.js >= 18** (ESM modules required)
|
|
48
|
-
|
|
49
|
-
### Global install
|
|
50
52
|
```bash
|
|
51
|
-
|
|
53
|
+
wispy
|
|
52
54
|
```
|
|
53
55
|
|
|
54
|
-
###
|
|
56
|
+
### Send a one-shot message
|
|
57
|
+
|
|
55
58
|
```bash
|
|
56
|
-
|
|
57
|
-
npx wispy
|
|
59
|
+
wispy "Summarize the current repository and suggest next steps."
|
|
58
60
|
```
|
|
59
61
|
|
|
60
|
-
|
|
62
|
+
### Open a specific workstream
|
|
61
63
|
|
|
62
|
-
## 🗣️ Chat Modes
|
|
63
|
-
|
|
64
|
-
### REPL (default)
|
|
65
64
|
```bash
|
|
66
|
-
wispy
|
|
67
|
-
wispy -w myproject # start in a specific workstream
|
|
68
|
-
wispy --session my-ses # resume a named session
|
|
65
|
+
wispy -w infra
|
|
69
66
|
```
|
|
70
67
|
|
|
71
|
-
|
|
72
|
-
```
|
|
73
|
-
/help — show all slash commands
|
|
74
|
-
/clear — reset conversation history
|
|
75
|
-
/sessions — list recent sessions
|
|
76
|
-
/memory — show memory files
|
|
77
|
-
/tools — list available tools
|
|
78
|
-
/model — show current AI model
|
|
79
|
-
/workstream — show active workstream
|
|
80
|
-
/exit — exit Wispy
|
|
81
|
-
```
|
|
68
|
+
### Launch the full terminal UI
|
|
82
69
|
|
|
83
|
-
### TUI (Ink-based)
|
|
84
70
|
```bash
|
|
85
|
-
wispy-tui
|
|
86
|
-
wispy-tui -w myproject # workstream-specific TUI
|
|
71
|
+
wispy-tui
|
|
87
72
|
```
|
|
88
73
|
|
|
89
|
-
###
|
|
90
|
-
```bash
|
|
91
|
-
wispy ask "What files are in the current directory?"
|
|
92
|
-
wispy exec "summarize README.md"
|
|
93
|
-
```
|
|
74
|
+
### Check current execution context
|
|
94
75
|
|
|
95
|
-
### Overview
|
|
96
76
|
```bash
|
|
97
|
-
wispy
|
|
77
|
+
wispy where
|
|
98
78
|
```
|
|
99
79
|
|
|
100
|
-
|
|
80
|
+
### Inspect configuration
|
|
101
81
|
|
|
102
|
-
## 🤖 AI Providers
|
|
103
|
-
|
|
104
|
-
Wispy detects your configured provider automatically. Priority order:
|
|
105
|
-
|
|
106
|
-
| Provider | Env Var | Default Model |
|
|
107
|
-
|----------|---------|---------------|
|
|
108
|
-
| **Google AI** (Gemini) | `GOOGLE_AI_KEY` or `GEMINI_API_KEY` | `gemini-2.5-flash` |
|
|
109
|
-
| **Anthropic** (Claude) | `ANTHROPIC_API_KEY` | `claude-sonnet-4-20250514` |
|
|
110
|
-
| **OpenAI** | `OPENAI_API_KEY` | `gpt-4o` |
|
|
111
|
-
| **OpenRouter** | `OPENROUTER_API_KEY` | `anthropic/claude-sonnet-4` |
|
|
112
|
-
| **Groq** | `GROQ_API_KEY` | `llama-3.3-70b-versatile` |
|
|
113
|
-
| **DeepSeek** | `DEEPSEEK_API_KEY` | `deepseek-chat` |
|
|
114
|
-
| **Ollama** (local) | `OLLAMA_HOST` | `llama3.2` |
|
|
115
|
-
|
|
116
|
-
### Override provider
|
|
117
82
|
```bash
|
|
118
|
-
|
|
119
|
-
|
|
83
|
+
wispy config show
|
|
84
|
+
wispy config get provider
|
|
85
|
+
wispy config set provider openai
|
|
86
|
+
wispy config delete apiKey
|
|
87
|
+
wispy config reset
|
|
88
|
+
wispy config path
|
|
89
|
+
wispy config edit
|
|
120
90
|
```
|
|
121
91
|
|
|
122
|
-
|
|
123
|
-
```json
|
|
124
|
-
// ~/.wispy/config.json
|
|
125
|
-
{
|
|
126
|
-
"provider": "google",
|
|
127
|
-
"model": "gemini-2.5-flash",
|
|
128
|
-
"apiKey": "optional-if-not-in-env"
|
|
129
|
-
}
|
|
130
|
-
```
|
|
92
|
+
## Provider Support
|
|
131
93
|
|
|
132
|
-
|
|
94
|
+
Wispy v2.7.4 is positioned as a multi-provider workspace client with support spanning hosted APIs, local runtimes, aggregators, and OAuth-backed access.
|
|
133
95
|
|
|
134
|
-
|
|
96
|
+
| Category | Examples |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| Hosted frontier APIs | Google, Anthropic, OpenAI, xAI, Mistral, Cohere, Perplexity |
|
|
99
|
+
| Fast and cost-focused | Groq, DeepSeek, Together, Fireworks, Replicate, Anyscale |
|
|
100
|
+
| Aggregators and gateways | OpenRouter, Vercel AI Gateway |
|
|
101
|
+
| Regional and specialist providers | Kimi, MiniMax, Z.AI/GLM, DashScope, Volcengine, BytePlus, Xiaomi |
|
|
102
|
+
| Local and self-hosted | Ollama, vLLM, SGLang, LiteLLM |
|
|
103
|
+
| OAuth-backed access | GitHub Copilot |
|
|
135
104
|
|
|
136
|
-
|
|
105
|
+
### Authentication
|
|
137
106
|
|
|
138
|
-
|
|
|
139
|
-
|
|
140
|
-
|
|
|
141
|
-
|
|
|
142
|
-
|
|
|
143
|
-
| `file_search` | Search files with regex (like grep) |
|
|
144
|
-
| `list_directory` | List directory contents |
|
|
145
|
-
| `run_command` | Execute shell commands |
|
|
146
|
-
| `git_status` / `git_diff` / `git_log` | Git operations |
|
|
147
|
-
| `web_search` | Search the web |
|
|
148
|
-
| `memory_save` | Save facts to persistent memory |
|
|
149
|
-
| `memory_get` | Retrieve a memory by key |
|
|
150
|
-
| `memory_search` | Full-text search across all memories |
|
|
151
|
-
| `memory_list` | List all memory files |
|
|
152
|
-
| `memory_append` | Append to a memory file |
|
|
153
|
-
| `memory_delete` | Delete a memory file |
|
|
154
|
-
| `spawn_subagent` | Launch a parallel sub-agent |
|
|
155
|
-
| `list_subagents` | List running sub-agents |
|
|
156
|
-
| `get_subagent_result` | Get a sub-agent's result |
|
|
157
|
-
| `kill_subagent` | Cancel a sub-agent |
|
|
107
|
+
| Mode | Notes |
|
|
108
|
+
| --- | --- |
|
|
109
|
+
| API keys | Standard provider key flow |
|
|
110
|
+
| OAuth | Device flow support, including GitHub Copilot |
|
|
111
|
+
| Local runtimes | Host/base URL driven for local inference stacks |
|
|
158
112
|
|
|
159
|
-
|
|
113
|
+
Examples:
|
|
160
114
|
|
|
161
|
-
## 📱 Channel Setup
|
|
162
|
-
|
|
163
|
-
Run Wispy as a multi-platform bot that responds to messages in Telegram, Discord, or Slack.
|
|
164
|
-
|
|
165
|
-
### Start the bot server
|
|
166
115
|
```bash
|
|
167
|
-
|
|
168
|
-
wispy
|
|
116
|
+
export GOOGLE_AI_KEY=...
|
|
117
|
+
wispy
|
|
169
118
|
```
|
|
170
119
|
|
|
171
|
-
### Telegram
|
|
172
|
-
1. Create a bot via [@BotFather](https://t.me/BotFather)
|
|
173
|
-
2. Copy the bot token
|
|
174
|
-
3. Configure:
|
|
175
120
|
```bash
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
# Option 2: config file
|
|
180
|
-
# ~/.wispy/channels.json
|
|
181
|
-
{
|
|
182
|
-
"telegram": {
|
|
183
|
-
"enabled": true,
|
|
184
|
-
"token": "your_bot_token"
|
|
185
|
-
}
|
|
186
|
-
}
|
|
121
|
+
wispy auth github-copilot
|
|
122
|
+
wispy
|
|
187
123
|
```
|
|
188
124
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
3. Configure:
|
|
193
|
-
```json
|
|
194
|
-
{
|
|
195
|
-
"discord": {
|
|
196
|
-
"enabled": true,
|
|
197
|
-
"token": "your_discord_token",
|
|
198
|
-
"clientId": "your_client_id",
|
|
199
|
-
"guildId": "optional_guild_id"
|
|
200
|
-
}
|
|
201
|
-
}
|
|
125
|
+
```bash
|
|
126
|
+
export OLLAMA_HOST=http://localhost:11434
|
|
127
|
+
wispy
|
|
202
128
|
```
|
|
203
129
|
|
|
204
|
-
|
|
205
|
-
1. Create a Slack app at [api.slack.com](https://api.slack.com/apps)
|
|
206
|
-
2. Install peer dependency: `npm install -g @slack/bolt`
|
|
207
|
-
3. Configure:
|
|
208
|
-
```json
|
|
209
|
-
{
|
|
210
|
-
"slack": {
|
|
211
|
-
"enabled": true,
|
|
212
|
-
"botToken": "xoxb-your-token",
|
|
213
|
-
"appToken": "xapp-your-token",
|
|
214
|
-
"signingSecret": "your-signing-secret"
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
```
|
|
130
|
+
## Interfaces
|
|
218
131
|
|
|
219
|
-
|
|
132
|
+
### REPL
|
|
220
133
|
|
|
221
|
-
|
|
134
|
+
The default `wispy` interface is a conversational REPL with:
|
|
222
135
|
|
|
223
|
-
|
|
136
|
+
- slash commands
|
|
137
|
+
- command autocomplete
|
|
138
|
+
- inline preview hints
|
|
139
|
+
- one-shot and persistent workstream usage
|
|
140
|
+
- token and cost visibility
|
|
224
141
|
|
|
225
|
-
|
|
142
|
+
Examples:
|
|
226
143
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
Wispy: Got it! I'll remember that. 🌿
|
|
144
|
+
```bash
|
|
145
|
+
wispy
|
|
146
|
+
wispy -w product
|
|
147
|
+
wispy "Search this repo for sync-related code paths."
|
|
232
148
|
```
|
|
233
149
|
|
|
234
|
-
|
|
235
|
-
```
|
|
236
|
-
You: Save this to memory: the deployment command is `vercel --prod`
|
|
237
|
-
```
|
|
150
|
+
### TUI Workspace OS
|
|
238
151
|
|
|
239
|
-
|
|
240
|
-
```
|
|
241
|
-
~/.wispy/memory/
|
|
242
|
-
├── MEMORY.md — main persistent memory (auto-included in every chat)
|
|
243
|
-
├── user.md — user preferences
|
|
244
|
-
├── daily/
|
|
245
|
-
│ └── 2026-04-03.md — daily logs
|
|
246
|
-
└── projects/
|
|
247
|
-
└── myapp.md — project-specific notes
|
|
248
|
-
```
|
|
152
|
+
`wispy-tui` is a multi-panel terminal workspace with six built-in views.
|
|
249
153
|
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
154
|
+
| View | Purpose |
|
|
155
|
+
| --- | --- |
|
|
156
|
+
| `chat` | Main conversation and tool execution surface |
|
|
157
|
+
| `overview` | Cross-workstream status and recent activity |
|
|
158
|
+
| `agents` | Running and recent agent/sub-agent activity |
|
|
159
|
+
| `memory` | Search and inspect persistent memories |
|
|
160
|
+
| `audit` | Execution timeline, approvals, and receipts |
|
|
161
|
+
| `settings` | Model, provider, and runtime status surface |
|
|
162
|
+
|
|
163
|
+
## Trust and Execution Model
|
|
258
164
|
|
|
259
|
-
|
|
165
|
+
Wispy is built around trustworthy execution rather than blind automation.
|
|
260
166
|
|
|
261
|
-
|
|
167
|
+
| Capability | Description |
|
|
168
|
+
| --- | --- |
|
|
169
|
+
| Trust modes | `careful`, `balanced`, `yolo` |
|
|
170
|
+
| Dry-run | Preview actions before execution |
|
|
171
|
+
| Receipts | Inspect recent execution details |
|
|
172
|
+
| Approval prompts | Human-in-the-loop confirmation for sensitive actions |
|
|
173
|
+
| Audit trail | Persisted audit log and replayable session history |
|
|
174
|
+
| Permissions | Per-tool policy visibility and overrides |
|
|
262
175
|
|
|
263
|
-
|
|
176
|
+
Examples:
|
|
264
177
|
|
|
265
|
-
### Add a scheduled job
|
|
266
178
|
```bash
|
|
267
|
-
|
|
268
|
-
wispy
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
--channel "telegram:YOUR_CHAT_ID"
|
|
273
|
-
|
|
274
|
-
# Every 30 minutes
|
|
275
|
-
wispy cron add \
|
|
276
|
-
--name "Price Check" \
|
|
277
|
-
--schedule every:1800000 \
|
|
278
|
-
--task "Check the current price of BTC and ETH"
|
|
279
|
-
|
|
280
|
-
# One-shot at specific time
|
|
281
|
-
wispy cron add \
|
|
282
|
-
--name "Reminder" \
|
|
283
|
-
--schedule "at:2026-12-31T09:00:00Z" \
|
|
284
|
-
--task "Remind me it's New Year's Eve!"
|
|
179
|
+
wispy trust
|
|
180
|
+
wispy trust level careful
|
|
181
|
+
wispy trust log --today
|
|
182
|
+
wispy trust receipt <session-id>
|
|
183
|
+
wispy trust replay <session-id>
|
|
285
184
|
```
|
|
286
185
|
|
|
287
|
-
|
|
288
|
-
| Format | Example | Description |
|
|
289
|
-
|--------|---------|-------------|
|
|
290
|
-
| Cron expression | `0 9 * * *` | Standard 5-field cron (daily at 9am) |
|
|
291
|
-
| Interval | `every:1800000` | Every N milliseconds (30 min) |
|
|
292
|
-
| One-shot | `at:2026-12-31T09:00:00Z` | Specific ISO timestamp |
|
|
186
|
+
## Continuity
|
|
293
187
|
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
188
|
+
Wispy keeps workspace state portable across local and remote environments.
|
|
189
|
+
|
|
190
|
+
| Command | Purpose |
|
|
191
|
+
| --- | --- |
|
|
192
|
+
| `where` | Show current mode, provider, workstream, sync, memory, and session context |
|
|
193
|
+
| `handoff` | Push or pull state and generate a handoff summary |
|
|
194
|
+
| `sync` | Sync sessions, memory, workstreams, cron metadata, and permissions |
|
|
195
|
+
|
|
196
|
+
Examples:
|
|
301
197
|
|
|
302
|
-
### Start the scheduler
|
|
303
198
|
```bash
|
|
304
|
-
wispy
|
|
199
|
+
wispy where
|
|
200
|
+
wispy handoff cloud
|
|
201
|
+
wispy handoff local
|
|
202
|
+
wispy sync
|
|
305
203
|
```
|
|
306
204
|
|
|
307
|
-
|
|
205
|
+
## Memory, Skills, and Agents
|
|
308
206
|
|
|
309
|
-
|
|
207
|
+
### Memory
|
|
310
208
|
|
|
311
|
-
|
|
209
|
+
Wispy stores long-term memory under `~/.wispy/memory/` and exposes both natural-language and command-driven memory operations.
|
|
312
210
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
211
|
+
| Command | Purpose |
|
|
212
|
+
| --- | --- |
|
|
213
|
+
| `remember` | Save something important |
|
|
214
|
+
| `recall` | Search memories |
|
|
215
|
+
| `memories` | List saved memories |
|
|
216
|
+
| `forget` | Remove a memory |
|
|
318
217
|
|
|
319
|
-
|
|
320
|
-
- `spawn_subagent` — start a sub-agent with a task
|
|
321
|
-
- `list_subagents` — see all active/recent sub-agents
|
|
322
|
-
- `get_subagent_result` — wait for and retrieve results
|
|
323
|
-
- `kill_subagent` — cancel a running sub-agent
|
|
324
|
-
- `steer_subagent` — send mid-task guidance
|
|
218
|
+
Examples:
|
|
325
219
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
↘ timeout
|
|
220
|
+
```text
|
|
221
|
+
/remember The staging server runs on port 8090.
|
|
222
|
+
/recall staging server
|
|
223
|
+
/memories
|
|
224
|
+
/forget old-note
|
|
332
225
|
```
|
|
333
226
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
{
|
|
346
|
-
"servers": {
|
|
347
|
-
"filesystem": {
|
|
348
|
-
"command": "npx",
|
|
349
|
-
"args": ["-y", "@modelcontextprotocol/server-filesystem", "/path/to/dir"]
|
|
350
|
-
},
|
|
351
|
-
"github": {
|
|
352
|
-
"command": "npx",
|
|
353
|
-
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
354
|
-
"env": { "GITHUB_TOKEN": "your_token" }
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
```
|
|
227
|
+
### Skills
|
|
228
|
+
|
|
229
|
+
Skills turn successful workflows into reusable commands.
|
|
230
|
+
|
|
231
|
+
| Command | Purpose |
|
|
232
|
+
| --- | --- |
|
|
233
|
+
| `skills` | List learned skills |
|
|
234
|
+
| `teach` | Create a skill from recent conversation context |
|
|
235
|
+
| `improve` | Refine an existing skill |
|
|
236
|
+
|
|
237
|
+
Examples:
|
|
359
238
|
|
|
360
|
-
### MCP CLI
|
|
361
239
|
```bash
|
|
362
|
-
wispy
|
|
363
|
-
wispy
|
|
364
|
-
wispy
|
|
240
|
+
wispy skill
|
|
241
|
+
wispy teach release-checklist
|
|
242
|
+
wispy improve release-checklist "Make it verify cron and channel health."
|
|
365
243
|
```
|
|
366
244
|
|
|
367
|
-
|
|
245
|
+
### Agents and sub-agents
|
|
368
246
|
|
|
369
|
-
|
|
247
|
+
Wispy supports delegated execution through agent and sub-agent orchestration.
|
|
370
248
|
|
|
371
|
-
|
|
249
|
+
| Capability | Description |
|
|
250
|
+
| --- | --- |
|
|
251
|
+
| Agent listing | Inspect active and recent workers |
|
|
252
|
+
| Agent detail | Pull status and results |
|
|
253
|
+
| Agent termination | Kill a running task |
|
|
254
|
+
| Parallel delegation | Spawn task-specific workers |
|
|
255
|
+
| Pipelines | Chain role-based execution stages |
|
|
372
256
|
|
|
373
|
-
|
|
374
|
-
~/.wispy/
|
|
375
|
-
├── config.json — main config (provider, model, apiKey)
|
|
376
|
-
├── channels.json — channel bot configuration
|
|
377
|
-
├── mcp.json — MCP server configuration
|
|
378
|
-
├── sessions/ — conversation history
|
|
379
|
-
├── memory/ — long-term memory files
|
|
380
|
-
├── cron/ — scheduler jobs and history
|
|
381
|
-
├── subagents/ — sub-agent results
|
|
382
|
-
└── audit/ — audit log (JSONL per day)
|
|
383
|
-
```
|
|
257
|
+
Examples:
|
|
384
258
|
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
"model": "gemini-2.5-flash", // defaults to provider's default
|
|
390
|
-
"apiKey": "...", // env var takes precedence
|
|
391
|
-
"workstream": "default" // default workstream
|
|
392
|
-
}
|
|
259
|
+
```text
|
|
260
|
+
/agents
|
|
261
|
+
/agent agent-123
|
|
262
|
+
/kill agent-123
|
|
393
263
|
```
|
|
394
264
|
|
|
395
|
-
|
|
396
|
-
```bash
|
|
397
|
-
WISPY_PROVIDER=google # force provider
|
|
398
|
-
WISPY_MODEL=gemini-2.5-flash # force model
|
|
399
|
-
WISPY_WORKSTREAM=myproject # set active workstream
|
|
400
|
-
WISPY_DEBUG=1 # enable debug output
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
---
|
|
265
|
+
## MCP and Built-in Tools
|
|
404
266
|
|
|
405
|
-
|
|
267
|
+
Wispy can merge Model Context Protocol tools with its own built-in tool registry.
|
|
406
268
|
|
|
407
|
-
|
|
269
|
+
### MCP
|
|
408
270
|
|
|
409
271
|
```bash
|
|
410
|
-
wispy
|
|
411
|
-
wispy
|
|
412
|
-
wispy
|
|
272
|
+
wispy mcp
|
|
273
|
+
wispy mcp list
|
|
274
|
+
wispy mcp connect
|
|
275
|
+
wispy mcp disconnect
|
|
276
|
+
wispy mcp reload
|
|
277
|
+
wispy mcp config
|
|
413
278
|
```
|
|
414
279
|
|
|
415
|
-
|
|
416
|
-
- Conversation sessions
|
|
417
|
-
- Context/memory scope
|
|
418
|
-
- Sub-agent history
|
|
280
|
+
### Built-in tools
|
|
419
281
|
|
|
420
|
-
|
|
282
|
+
Wispy ships with 18+ built-in tools across file operations, shell execution, git, web access, memory, planning, and delegation.
|
|
421
283
|
|
|
422
|
-
|
|
284
|
+
| Tool family | Examples |
|
|
285
|
+
| --- | --- |
|
|
286
|
+
| Files | `read_file`, `write_file`, `file_edit`, `file_search`, `list_directory` |
|
|
287
|
+
| Execution | `run_command`, `git`, `web_search`, `web_fetch` |
|
|
288
|
+
| System | `keychain`, `clipboard` |
|
|
289
|
+
| Planning | `update_plan`, `pipeline`, `ralph_loop` |
|
|
290
|
+
| Agents | `spawn_agent`, `spawn_async_agent`, `spawn_subagent`, `list_agents`, `list_subagents`, `get_agent_result`, `get_subagent_result`, `kill_subagent` |
|
|
423
291
|
|
|
424
|
-
|
|
425
|
-
┌─────────────────────────────┐
|
|
426
|
-
│ WispyEngine │
|
|
427
|
-
│ core/engine.mjs │
|
|
428
|
-
│ processMessage() ─────────┐│
|
|
429
|
-
└─────────────────────────────┘│
|
|
430
|
-
│ │
|
|
431
|
-
┌──────────────────────────┼──────────┐ │
|
|
432
|
-
│ │ │ │ │
|
|
433
|
-
REPL TUI channels server.mjs │
|
|
434
|
-
(bin/wispy) (bin/wispy-tui) (lib/channels/) │
|
|
435
|
-
│
|
|
436
|
-
┌─────────────────────────┘
|
|
437
|
-
│
|
|
438
|
-
┌───────────────────┼──────────────────────────┐
|
|
439
|
-
│ │ │
|
|
440
|
-
ProviderRegistry ToolRegistry SessionManager
|
|
441
|
-
core/providers.mjs core/tools.mjs core/session.mjs
|
|
442
|
-
(Gemini/Claude/ (18+ built-in + (file-based,
|
|
443
|
-
OpenAI/Groq/ MCP tools) per-channel)
|
|
444
|
-
DeepSeek/Ollama/
|
|
445
|
-
OpenRouter)
|
|
446
|
-
│
|
|
447
|
-
└── MemoryManager CronManager SubAgentManager
|
|
448
|
-
core/memory.mjs core/cron.mjs core/subagents.mjs
|
|
449
|
-
(~/.wispy/ (~/.wispy/ (~/.wispy/
|
|
450
|
-
memory/) cron/) subagents/)
|
|
451
|
-
```
|
|
292
|
+
## Channels and Scheduling
|
|
452
293
|
|
|
453
|
-
|
|
294
|
+
### Messaging channels
|
|
454
295
|
|
|
455
|
-
|
|
296
|
+
| Channel | Status in repo |
|
|
297
|
+
| --- | --- |
|
|
298
|
+
| Telegram | Built-in adapter |
|
|
299
|
+
| Discord | Built-in adapter |
|
|
300
|
+
| Slack | Built-in adapter |
|
|
301
|
+
| WhatsApp | Built-in adapter |
|
|
302
|
+
| Signal | Built-in adapter |
|
|
303
|
+
| Email | Built-in adapter |
|
|
456
304
|
|
|
457
|
-
|
|
305
|
+
Example setup paths:
|
|
458
306
|
|
|
459
307
|
```bash
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
308
|
+
wispy channel setup telegram
|
|
309
|
+
wispy channel setup discord
|
|
310
|
+
wispy channel setup slack
|
|
311
|
+
```
|
|
463
312
|
|
|
464
|
-
|
|
465
|
-
npm install
|
|
313
|
+
### Cron scheduler
|
|
466
314
|
|
|
467
|
-
|
|
468
|
-
npm test
|
|
315
|
+
Use Wispy as an operator that wakes itself up and delivers work on schedule.
|
|
469
316
|
|
|
470
|
-
# Development REPL
|
|
471
|
-
node bin/wispy.mjs
|
|
472
|
-
```
|
|
473
|
-
|
|
474
|
-
### Running tests
|
|
475
317
|
```bash
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
```
|
|
318
|
+
wispy cron add
|
|
319
|
+
wispy cron list
|
|
320
|
+
wispy cron run <job-id>
|
|
321
|
+
wispy cron remove <job-id>
|
|
322
|
+
wispy cron history <job-id>
|
|
323
|
+
wispy cron start
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## Slash Commands
|
|
327
|
+
|
|
328
|
+
The shared command registry powers REPL completion, the TUI command palette, and shell completion.
|
|
329
|
+
|
|
330
|
+
### By category
|
|
331
|
+
|
|
332
|
+
| Category | Commands |
|
|
333
|
+
| --- | --- |
|
|
334
|
+
| Workstream | `/ws`, `/ws new <name>`, `/ws <name>`, `/ws status`, `/ws search <query>`, `/ws archive <name>`, `/ws delete <name>` |
|
|
335
|
+
| Trust | `/trust`, `/trust <level>`, `/trust log`, `/dry`, `/receipt`, `/replay`, `/permissions`, `/permit <tool> <level>`, `/audit` |
|
|
336
|
+
| Continuity | `/where`, `/handoff`, `/sync` |
|
|
337
|
+
| Skills | `/skills`, `/teach <name>`, `/improve <name>` |
|
|
338
|
+
| Session | `/clear`, `/model`, `/cost`, `/compact`, `/sessions`, `/history` |
|
|
339
|
+
| Memory | `/remember <text>`, `/recall <query>`, `/memories`, `/forget <key>` |
|
|
340
|
+
| Agents | `/agents`, `/agent <id>`, `/kill <id>` |
|
|
341
|
+
| MCP | `/mcp`, `/mcp list`, `/mcp connect`, `/mcp disconnect`, `/mcp reload`, `/mcp config` |
|
|
342
|
+
| Quick aliases | `/o`, `/w`, `/a`, `/m`, `/t`, `/s`, `/d` |
|
|
343
|
+
| Meta | `/help`, `/quit`, `/exit`, `/provider`, `/overview`, `/search <keyword>` |
|
|
344
|
+
|
|
345
|
+
### Full scan list
|
|
346
|
+
|
|
347
|
+
```text
|
|
348
|
+
/ws
|
|
349
|
+
/trust
|
|
350
|
+
/dry
|
|
351
|
+
/receipt
|
|
352
|
+
/replay
|
|
353
|
+
/where
|
|
354
|
+
/handoff
|
|
355
|
+
/sync
|
|
356
|
+
/skills
|
|
357
|
+
/teach
|
|
358
|
+
/improve
|
|
359
|
+
/clear
|
|
360
|
+
/model
|
|
361
|
+
/cost
|
|
362
|
+
/compact
|
|
363
|
+
/sessions
|
|
364
|
+
/history
|
|
365
|
+
/remember
|
|
366
|
+
/recall
|
|
367
|
+
/memories
|
|
368
|
+
/forget
|
|
369
|
+
/agents
|
|
370
|
+
/agent
|
|
371
|
+
/kill
|
|
372
|
+
/mcp
|
|
373
|
+
/permissions
|
|
374
|
+
/permit
|
|
375
|
+
/audit
|
|
376
|
+
/o
|
|
377
|
+
/w
|
|
378
|
+
/a
|
|
379
|
+
/m
|
|
380
|
+
/t
|
|
381
|
+
/s
|
|
382
|
+
/d
|
|
383
|
+
/help
|
|
384
|
+
/quit
|
|
385
|
+
/exit
|
|
386
|
+
/provider
|
|
387
|
+
/overview
|
|
388
|
+
/search
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
## Architecture
|
|
392
|
+
|
|
393
|
+
The repository is organized around two entrypoints, a core runtime, user-facing command modules, channel adapters, and a focused test suite.
|
|
394
|
+
|
|
395
|
+
```text
|
|
483
396
|
wispy-cli/
|
|
484
397
|
├── bin/
|
|
485
|
-
│ ├── wispy.mjs
|
|
486
|
-
│
|
|
398
|
+
│ ├── wispy.mjs
|
|
399
|
+
│ ├── wispy-tui.mjs
|
|
487
400
|
├── core/
|
|
488
|
-
│ ├── engine.mjs
|
|
489
|
-
│ ├──
|
|
490
|
-
│ ├──
|
|
491
|
-
│ ├──
|
|
492
|
-
│ ├──
|
|
493
|
-
│ ├──
|
|
494
|
-
│ ├──
|
|
495
|
-
│ ├──
|
|
496
|
-
│ ├──
|
|
497
|
-
│
|
|
401
|
+
│ ├── engine.mjs
|
|
402
|
+
│ ├── providers.mjs
|
|
403
|
+
│ ├── auth.mjs
|
|
404
|
+
│ ├── config.mjs
|
|
405
|
+
│ ├── permissions.mjs
|
|
406
|
+
│ ├── audit.mjs
|
|
407
|
+
│ ├── session.mjs
|
|
408
|
+
│ ├── memory.mjs
|
|
409
|
+
│ ├── skills.mjs
|
|
410
|
+
│ ├── subagents.mjs
|
|
411
|
+
│ ├── mcp.mjs
|
|
412
|
+
│ ├── cron.mjs
|
|
413
|
+
│ ├── sync.mjs
|
|
414
|
+
│ ├── onboarding.mjs
|
|
415
|
+
│ └── ...
|
|
498
416
|
├── lib/
|
|
499
|
-
│ ├── wispy-repl.mjs
|
|
500
|
-
│ ├── wispy-tui.mjs
|
|
501
|
-
│
|
|
502
|
-
│
|
|
503
|
-
│
|
|
504
|
-
│
|
|
505
|
-
│
|
|
506
|
-
│
|
|
417
|
+
│ ├── wispy-repl.mjs
|
|
418
|
+
│ ├── wispy-tui.mjs
|
|
419
|
+
│ ├── command-registry.mjs
|
|
420
|
+
│ ├── channels/
|
|
421
|
+
│ │ ├── index.mjs
|
|
422
|
+
│ │ ├── telegram.mjs
|
|
423
|
+
│ │ ├── discord.mjs
|
|
424
|
+
│ │ ├── slack.mjs
|
|
425
|
+
│ │ ├── whatsapp.mjs
|
|
426
|
+
│ │ ├── signal.mjs
|
|
427
|
+
│ │ ├── email.mjs
|
|
428
|
+
│ │ └── base.mjs
|
|
429
|
+
│ └── commands/
|
|
430
|
+
│ ├── ws.mjs
|
|
431
|
+
│ ├── trust.mjs
|
|
432
|
+
│ ├── continuity.mjs
|
|
433
|
+
│ ├── skills-cmd.mjs
|
|
434
|
+
│ └── ws-interactive-enhancement.js
|
|
507
435
|
└── tests/
|
|
436
|
+
├── channels.test.mjs
|
|
508
437
|
├── core-engine.test.mjs
|
|
509
|
-
├── core-
|
|
438
|
+
├── core-tools.test.mjs
|
|
510
439
|
├── core-memory.test.mjs
|
|
511
|
-
├── core-
|
|
440
|
+
├── core-session.test.mjs
|
|
512
441
|
├── core-subagents.test.mjs
|
|
513
|
-
|
|
514
|
-
└── channels.test.mjs
|
|
442
|
+
└── core-cron.test.mjs
|
|
515
443
|
```
|
|
516
444
|
|
|
517
|
-
|
|
445
|
+
### Runtime flow
|
|
518
446
|
|
|
519
|
-
|
|
447
|
+
```text
|
|
448
|
+
bin/wispy.mjs
|
|
449
|
+
-> lib/wispy-repl.mjs
|
|
450
|
+
-> core/engine.mjs
|
|
451
|
+
-> core/providers.mjs
|
|
452
|
+
-> core/tools.mjs
|
|
453
|
+
-> core/session.mjs
|
|
454
|
+
-> core/memory.mjs
|
|
455
|
+
-> core/subagents.mjs
|
|
456
|
+
-> core/mcp.mjs
|
|
457
|
+
-> core/audit.mjs
|
|
458
|
+
-> core/permissions.mjs
|
|
520
459
|
|
|
460
|
+
bin/wispy-tui.mjs
|
|
461
|
+
-> lib/wispy-tui.mjs
|
|
462
|
+
-> core/engine.mjs
|
|
521
463
|
```
|
|
522
|
-
Usage: wispy [options] [command]
|
|
523
|
-
|
|
524
|
-
Commands:
|
|
525
|
-
wispy — start interactive REPL
|
|
526
|
-
wispy ask <message> — one-shot chat
|
|
527
|
-
wispy exec <message> — one-shot execution
|
|
528
|
-
wispy overview — show workstream overview
|
|
529
|
-
wispy sessions — list recent sessions
|
|
530
|
-
wispy memory <cmd> — manage long-term memory
|
|
531
|
-
wispy cron <cmd> — manage scheduled jobs
|
|
532
|
-
wispy channels <cmd> — manage channel bots
|
|
533
|
-
wispy mcp <cmd> — manage MCP servers
|
|
534
|
-
wispy server <cmd> — start/stop HTTP/WS server
|
|
535
|
-
wispy audit <cmd> — view audit log
|
|
536
|
-
|
|
537
|
-
Options:
|
|
538
|
-
-w, --workstream <name> — set active workstream
|
|
539
|
-
--session <id> — resume a specific session
|
|
540
|
-
--model <name> — override AI model
|
|
541
|
-
--provider <name> — override AI provider
|
|
542
|
-
--help — show help
|
|
543
|
-
--version — show version
|
|
544
|
-
```
|
|
545
|
-
|
|
546
|
-
---
|
|
547
464
|
|
|
548
|
-
##
|
|
465
|
+
## Development
|
|
549
466
|
|
|
550
|
-
|
|
551
|
-
- **Google AI (Gemini)** — [aistudio.google.com/apikey](https://aistudio.google.com/apikey) *(free tier available)*
|
|
552
|
-
- **Anthropic (Claude)** — [console.anthropic.com/settings/keys](https://console.anthropic.com/settings/keys)
|
|
553
|
-
- **OpenAI** — [platform.openai.com/api-keys](https://platform.openai.com/api-keys)
|
|
554
|
-
- **OpenRouter** — [openrouter.ai/keys](https://openrouter.ai/keys) *(free credits)*
|
|
555
|
-
- **Groq** — [console.groq.com/keys](https://console.groq.com/keys) *(free tier)*
|
|
556
|
-
- **DeepSeek** — [platform.deepseek.com/api_keys](https://platform.deepseek.com/api_keys)
|
|
557
|
-
- **Ollama** — [ollama.ai](https://ollama.ai) *(fully local, no key needed)*
|
|
467
|
+
### Tests
|
|
558
468
|
|
|
559
|
-
|
|
469
|
+
```bash
|
|
470
|
+
npm test
|
|
471
|
+
```
|
|
560
472
|
|
|
561
|
-
|
|
473
|
+
Current status:
|
|
562
474
|
|
|
563
|
-
|
|
475
|
+
| Metric | Value |
|
|
476
|
+
| --- | --- |
|
|
477
|
+
| Test suites | `8` |
|
|
478
|
+
| Tests | `91` |
|
|
479
|
+
| Passing | `91` |
|
|
480
|
+
| Failing | `0` |
|
|
564
481
|
|
|
565
|
-
|
|
482
|
+
## License
|
|
566
483
|
|
|
567
|
-
|
|
484
|
+
MIT
|
|
568
485
|
|
|
569
486
|
Built by Minseo & Poropo 🫧
|
|
570
|
-
|
|
571
|
-
*Wispy is a small ghost that lives in terminals — floating between code, files, and servers.*
|
package/bin/wispy-mjs
ADDED
package/bin/wispy.mjs
CHANGED
|
@@ -7,10 +7,16 @@
|
|
|
7
7
|
(async () => {
|
|
8
8
|
const { fileURLToPath } = await import('url');
|
|
9
9
|
const { dirname } = await import('path');
|
|
10
|
+
const { readFile } = await import('fs/promises');
|
|
10
11
|
const baseDir = dirname(fileURLToPath(import.meta.url));
|
|
11
12
|
|
|
12
13
|
const args = process.argv.slice(2);
|
|
13
14
|
|
|
15
|
+
if (args.includes('--help')) {
|
|
16
|
+
console.log(`\nWispy CLI Help:\n\nCommands:\n ws - Execute WebSocket operations\n help - Interactive help guide\n --help - Show this message\n --version - Display version\n\n`);
|
|
17
|
+
process.exit(0);
|
|
18
|
+
}
|
|
19
|
+
|
|
14
20
|
async function handleCommand(command) {
|
|
15
21
|
const inquirer = (await import('inquirer')).default;
|
|
16
22
|
|
|
@@ -23,38 +29,95 @@
|
|
|
23
29
|
name: 'selectedCommand',
|
|
24
30
|
message: 'What would you like to do?',
|
|
25
31
|
choices: [
|
|
26
|
-
{ name: 'Run WebSocket command', value: 'ws' },
|
|
27
|
-
{ name: 'Get help', value: 'help' },
|
|
28
|
-
{ name: 'Exit', value: null }
|
|
32
|
+
{ name: 'Run WebSocket command - Execute and debug WebSocket operations', value: 'ws' },
|
|
33
|
+
{ name: 'Get help - Learn about available commands and usage', value: 'help' },
|
|
34
|
+
{ name: 'Exit - Close the interactive prompt', value: null }
|
|
29
35
|
],
|
|
30
36
|
}
|
|
31
37
|
]);
|
|
32
38
|
} catch (error) {
|
|
33
|
-
|
|
34
|
-
console.error("Prompt couldn't be rendered in the current environment.");
|
|
35
|
-
} else {
|
|
36
|
-
console.log("Prompt closed by the user. Exiting gracefully.");
|
|
37
|
-
}
|
|
39
|
+
console.error("TTY Prompt failed. Need help? Run 'node bin/wispy.mjs --help'. Restarting interactivity...");
|
|
38
40
|
process.exit(0);
|
|
39
41
|
}
|
|
40
42
|
command = answers.selectedCommand;
|
|
41
43
|
}
|
|
42
44
|
|
|
43
45
|
switch (command) {
|
|
46
|
+
case "--version":
|
|
47
|
+
try {
|
|
48
|
+
const packageJson = JSON.parse(await readFile(`${baseDir}/../package.json`, 'utf8'));
|
|
49
|
+
console.log(`Wispy CLI version: ${packageJson.version}`);
|
|
50
|
+
} catch {
|
|
51
|
+
console.error('Failed to read version information from package.json.');
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
44
54
|
case "ws":
|
|
55
|
+
if (!args[1]) {
|
|
56
|
+
let subcommand;
|
|
57
|
+
try {
|
|
58
|
+
const { subcommand: chosenSubcommand } = await inquirer.prompt([
|
|
59
|
+
{
|
|
60
|
+
type: 'list',
|
|
61
|
+
name: 'subcommand',
|
|
62
|
+
message: 'Choose a WebSocket subcommand:',
|
|
63
|
+
choices: [
|
|
64
|
+
{ name: 'Start WebSocket Client', value: 'start-client' },
|
|
65
|
+
{ name: 'Run WebSocket Server Debug Mode', value: 'run-debug' }
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
]);
|
|
69
|
+
subcommand = chosenSubcommand;
|
|
70
|
+
} catch (error) {
|
|
71
|
+
console.error('Interactive prompt was cancelled or closed. Exiting gracefully.');
|
|
72
|
+
process.exit(0);
|
|
73
|
+
}
|
|
74
|
+
args[1] = subcommand;
|
|
75
|
+
} else if (!['start-client', 'run-debug'].includes(args[1])) {
|
|
76
|
+
console.error(`Error: Unrecognized argument '${args[1]}'.`);
|
|
77
|
+
const { retry } = await inquirer.prompt([
|
|
78
|
+
{
|
|
79
|
+
type: 'confirm',
|
|
80
|
+
name: 'retry',
|
|
81
|
+
message: 'Would you like to re-enter the WebSocket command?',
|
|
82
|
+
default: true,
|
|
83
|
+
}
|
|
84
|
+
]);
|
|
85
|
+
if (retry) return await handleCommand('ws');
|
|
86
|
+
process.exit(1);
|
|
87
|
+
}
|
|
45
88
|
const { handleWsCommand } = await import(baseDir + '/../lib/commands/ws.mjs');
|
|
46
89
|
return await handleWsCommand(args);
|
|
47
90
|
case "help":
|
|
48
|
-
|
|
91
|
+
if (args.length > 1) {
|
|
92
|
+
console.error(`Invalid arguments provided for 'help': ${args.slice(1).join(' ')}\n`);
|
|
93
|
+
console.log(`Usage: node bin/wispy.mjs help\n\nAvailable Commands:\n ws - Run WebSocket command (debug operations)\n help - Show this message\n\nTip: Run 'node bin/wispy.mjs' with no args for interactive guidance!\n`);
|
|
94
|
+
} else {
|
|
95
|
+
console.log(`\nWispy CLI Help:\n\nCommands:\n ws - Run WebSocket command (e.g., 'node bin/wispy.mjs ws')\n help - Show this help message (e.g., 'node bin/wispy.mjs --help')\n --version - Show the CLI version (e.g., 'node bin/wispy.mjs --version')\n\nExamples:\n $ node bin/wispy.mjs ws\n $ node bin/wispy.mjs --help\n $ node bin/wispy.mjs --version\n\nTip: Use no args for full interactivity.\n`);
|
|
96
|
+
}
|
|
49
97
|
break;
|
|
50
98
|
case null:
|
|
51
99
|
console.log("Goodbye!");
|
|
52
100
|
break;
|
|
53
101
|
default:
|
|
102
|
+
const { getCommandsWithSkills } = await import(baseDir + '/../lib/command-registry.mjs');
|
|
103
|
+
const validCommands = getCommandsWithSkills(null);
|
|
104
|
+
const prompt = (await import('inquirer')).default;
|
|
54
105
|
console.error(`Unknown command: ${command}`);
|
|
55
|
-
|
|
106
|
+
try {
|
|
107
|
+
const { choice } = await prompt.prompt([{
|
|
108
|
+
type: 'list',
|
|
109
|
+
name: 'choice',
|
|
110
|
+
message: 'Unknown command. Need help? Select a valid command:',
|
|
111
|
+
choices: validCommands.map(c => `${c.cmd} - ${c.desc}`),
|
|
112
|
+
}]);
|
|
113
|
+
const selectedCmd = choice.split(' ')[0];
|
|
114
|
+
console.log(`Executing '${selectedCmd}'...`);
|
|
115
|
+
await handleCommand(selectedCmd);
|
|
116
|
+
} catch (err) {
|
|
117
|
+
console.log('Prompt exited. No command executed. Goodbye!');
|
|
118
|
+
}
|
|
56
119
|
}
|
|
57
120
|
}
|
|
58
121
|
|
|
59
|
-
await handleCommand(args[0]
|
|
122
|
+
await handleCommand(args[0]);
|
|
60
123
|
})();
|
package/lib/commands/ws.mjs
CHANGED
|
@@ -1,32 +1,41 @@
|
|
|
1
1
|
import { select } from '@inquirer/prompts';
|
|
2
2
|
|
|
3
|
-
export async function handleWsCommand() {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
export async function handleWsCommand(args = []) {
|
|
4
|
+
try {
|
|
5
|
+
if (args.length > 0 && !['startClient', 'runServerDebug'].includes(args[0])) {
|
|
6
|
+
console.error(`\nError: Invalid WebSocket subcommand '${args[0]}'.\n`);
|
|
7
|
+
console.log('Available subcommands:');
|
|
8
|
+
console.log(' startClient Start WebSocket Client');
|
|
9
|
+
console.log(' runServerDebug Run WebSocket Server Debug Mode');
|
|
10
|
+
console.log('\nTip: Use no arguments to enter interactive mode.\n');
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
14
|
+
const action = args[0] || await select({
|
|
15
|
+
message: 'What WebSocket action would you like to perform?',
|
|
16
|
+
choices: [
|
|
17
|
+
{ name: 'Start WebSocket Client', value: 'startClient' },
|
|
18
|
+
{ name: 'Run WebSocket Server Debug Mode', value: 'runServerDebug' },
|
|
19
|
+
{ name: 'Exit', value: 'exit' }
|
|
20
|
+
]
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
switch (action) {
|
|
24
|
+
case 'startClient':
|
|
25
|
+
console.log('Starting WebSocket client...');
|
|
26
|
+
break;
|
|
27
|
+
case 'runServerDebug':
|
|
28
|
+
console.log('Running server in debug mode...');
|
|
29
|
+
break;
|
|
30
|
+
case 'exit':
|
|
31
|
+
console.log('Exiting WebSocket command.');
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (err.name === 'ExitPromptError') {
|
|
36
|
+
console.log('Prompt closed. Exiting command gracefully.');
|
|
37
|
+
} else {
|
|
38
|
+
console.error('Unexpected error:', err);
|
|
39
|
+
}
|
|
30
40
|
}
|
|
31
|
-
}
|
|
32
41
|
}
|