@runwingman/flightdeck-cli 0.2.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.
- package/Dockerfile +21 -0
- package/LICENSE +21 -0
- package/README.md +353 -0
- package/docs/to_fdcli.md +78 -0
- package/install.sh +86 -0
- package/package.json +53 -0
- package/src/bot-helpers.js +774 -0
- package/src/chat-runtime.js +782 -0
- package/src/cli.js +2767 -0
- package/src/client.js +285 -0
- package/src/config.js +117 -0
- package/src/db.js +653 -0
- package/src/flow-steps.js +215 -0
- package/src/nostr.js +160 -0
- package/src/render.js +34 -0
- package/src/sqlite-runtime.js +17 -0
- package/src/storage.js +191 -0
- package/src/sync.js +900 -0
- package/src/token.js +72 -0
- package/src/translators.js +1652 -0
- package/src/workspace-keys.js +214 -0
package/Dockerfile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
FROM node:20-bookworm-slim
|
|
2
|
+
|
|
3
|
+
WORKDIR /workspace
|
|
4
|
+
|
|
5
|
+
RUN apt-get update \
|
|
6
|
+
&& apt-get install -y --no-install-recommends python3 make g++ \
|
|
7
|
+
&& rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
COPY package.json package.json
|
|
10
|
+
COPY src/ src/
|
|
11
|
+
COPY README.md README.md
|
|
12
|
+
COPY LICENSE LICENSE
|
|
13
|
+
|
|
14
|
+
RUN npm install --omit=dev
|
|
15
|
+
RUN npm link
|
|
16
|
+
|
|
17
|
+
ENV FLIGHTDECK_CLI_STATE_DIR=/state
|
|
18
|
+
VOLUME ["/state"]
|
|
19
|
+
|
|
20
|
+
ENTRYPOINT ["flightdeck-cli"]
|
|
21
|
+
CMD ["--help"]
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Humans Institute
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
# FlightDeck CLI
|
|
2
|
+
|
|
3
|
+
FlightDeck CLI is the command line tool that agents and operators use to interact with Wingman workspaces through Tower. It provides local SQLite-backed access to tasks, chat, docs, storage, flows, approvals, and more.
|
|
4
|
+
|
|
5
|
+
## Runtime Support
|
|
6
|
+
|
|
7
|
+
FlightDeck CLI currently supports `Node.js` only.
|
|
8
|
+
|
|
9
|
+
- Use the installed `flightdeck-cli` binary, `npx @runwingman/flightdeck-cli ...`, or `node src/cli.js ...`
|
|
10
|
+
- Do not run the CLI with `bun`
|
|
11
|
+
|
|
12
|
+
The reason is the local SQLite layer currently uses `better-sqlite3`, and Bun execution can fail with native addon / ABI mismatches even when the rest of the CLI is otherwise fine.
|
|
13
|
+
|
|
14
|
+
## Quickstart
|
|
15
|
+
|
|
16
|
+
### 1. Install
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
# One-line installer
|
|
20
|
+
curl -fsSL https://raw.githubusercontent.com/humansinstitute/wingman-yoke/main/install.sh | bash
|
|
21
|
+
|
|
22
|
+
# From npm
|
|
23
|
+
npm install -g @runwingman/flightdeck-cli
|
|
24
|
+
|
|
25
|
+
# Or run directly
|
|
26
|
+
npx @runwingman/flightdeck-cli --help
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
For local development:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
git clone https://github.com/humansinstitute/wingman-yoke.git
|
|
33
|
+
cd wingman-yoke
|
|
34
|
+
npm install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Requires Node >= 20.** The installer tries `npm` first and falls back to GitHub until the npm package is published. Set `FLIGHTDECK_CLI_INSTALL_METHOD=git` to force the GitHub path.
|
|
38
|
+
|
|
39
|
+
### 2. Set your identity
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
export FLIGHTDECK_CLI_NSEC=nsec1...
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
When FlightDeck CLI runs inside a Wingmen-managed agent session, it can also resolve the per-session bot key automatically from Wingmen using `WINGMAN_URL` + `SESSION_ID`, or directly from `AGENT_NSEC` if that env var is injected into the session.
|
|
46
|
+
|
|
47
|
+
### 3. Initialize with a connection token
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
flightdeck-cli init --token "<connection_token>"
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
You can also pass the full Agent Connect JSON package — FlightDeck CLI extracts `.connection_token` automatically.
|
|
54
|
+
|
|
55
|
+
### 4. Sync workspace data
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
flightdeck-cli sync
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
This pulls workspace records into your local SQLite mirror at `./.flightdeck-cli/flightdeck-cli.db` under the folder where you run the CLI.
|
|
62
|
+
|
|
63
|
+
### 5. Start working
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Check connection status
|
|
67
|
+
flightdeck-cli status
|
|
68
|
+
|
|
69
|
+
# List and manage tasks
|
|
70
|
+
flightdeck-cli tasks list
|
|
71
|
+
flightdeck-cli tasks create --title "New task"
|
|
72
|
+
flightdeck-cli tasks comment <task-id> --body "Update here"
|
|
73
|
+
|
|
74
|
+
# Chat
|
|
75
|
+
flightdeck-cli chat channels
|
|
76
|
+
flightdeck-cli chat send <channel-id> --body "Hello"
|
|
77
|
+
|
|
78
|
+
# Docs
|
|
79
|
+
flightdeck-cli docs list
|
|
80
|
+
flightdeck-cli docs create --title "Notes" --content "hello world"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
> **Tip:** When running from a local clone, replace `flightdeck-cli` with `node src/cli.js`. Do not use `bun src/cli.js`.
|
|
84
|
+
|
|
85
|
+
The legacy `wingman-yoke` binary remains available during the rename window.
|
|
86
|
+
|
|
87
|
+
## State
|
|
88
|
+
|
|
89
|
+
By default, state lives in:
|
|
90
|
+
|
|
91
|
+
- `./.flightdeck-cli/flightdeck-cli.db` — local SQLite mirror for the current working directory
|
|
92
|
+
- `./.flightdeck-cli/config.json` — workspace config for the current working directory
|
|
93
|
+
|
|
94
|
+
Environment variables:
|
|
95
|
+
|
|
96
|
+
- `FLIGHTDECK_CLI_STATE_DIR` — override state directory explicitly, including a shared/global path if you want one
|
|
97
|
+
- `FLIGHTDECK_CLI_NSEC` — explicit agent/operator identity override
|
|
98
|
+
- `AGENT_NSEC` — per-agent secret injected by Wingmen sessions
|
|
99
|
+
- `WINGMAN_URL` + `SESSION_ID` — lets FlightDeck CLI fetch the current session bot key from the running Wingmen server
|
|
100
|
+
|
|
101
|
+
Compatibility fallbacks (`WINGMAN_YOKE_STATE_DIR`, `WINGMAN_YOKE_NSEC`, `./.wingman-yoke`, `yoke.db`, `WINGMAN_AP_STATE_DIR`, `WINGMAN_AUTOPILOT_NSEC`, `autopilot.db`, Bitwarden `wm21-nostr`) are still supported.
|
|
102
|
+
|
|
103
|
+
## Docker
|
|
104
|
+
|
|
105
|
+
Build the local image:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
docker build -t runwingman/flightdeck-cli .
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Run with mounted state:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
docker run --rm \
|
|
115
|
+
-e FLIGHTDECK_CLI_NSEC="$FLIGHTDECK_CLI_NSEC" \
|
|
116
|
+
-e FLIGHTDECK_CLI_STATE_DIR=/state \
|
|
117
|
+
-v flightdeck-cli-state:/state \
|
|
118
|
+
runwingman/flightdeck-cli sync
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
## Command Reference
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
node src/cli.js status
|
|
125
|
+
node src/cli.js getLatest
|
|
126
|
+
|
|
127
|
+
node src/cli.js tasks list
|
|
128
|
+
node src/cli.js tasks create --title "New task"
|
|
129
|
+
node src/cli.js tasks update <task-id> --state in_progress
|
|
130
|
+
node src/cli.js tasks comment <task-id> --body "Looks good"
|
|
131
|
+
node src/cli.js tasks reply <comment-id> --body "Following up"
|
|
132
|
+
node src/cli.js tasks comment-image <task-id> --file ./image.png --body "See this"
|
|
133
|
+
node src/cli.js tasks voice <task-id> --file ./voice.aiff --body "Voice note"
|
|
134
|
+
|
|
135
|
+
node src/cli.js chat channels
|
|
136
|
+
node src/cli.js chat create --title "FlightDeck temp"
|
|
137
|
+
node src/cli.js chat messages <channel-id>
|
|
138
|
+
node src/cli.js chat context --channel <channel-id> --format json
|
|
139
|
+
node src/cli.js chat history --channel <channel-id> --thread <thread-id> --format json
|
|
140
|
+
node src/cli.js chat search --query "term" --format json
|
|
141
|
+
node src/cli.js chat search --query "find previous budget chats" --deep --reference thread:<thread-id> --format json
|
|
142
|
+
node src/cli.js chat related --format json
|
|
143
|
+
node src/cli.js chat related --deep --format json
|
|
144
|
+
node src/cli.js chat reply-current --body "Reply" --format json
|
|
145
|
+
node src/cli.js chat send <channel-id> --body "Hello"
|
|
146
|
+
node src/cli.js chat reply <channel-id> --thread <message-id> --body "Reply"
|
|
147
|
+
node src/cli.js chat image <channel-id> --file ./image.png --body "Screenshot"
|
|
148
|
+
node src/cli.js chat voice <channel-id> --file ./voice.aiff --body "Voice note"
|
|
149
|
+
|
|
150
|
+
node src/cli.js docs list
|
|
151
|
+
node src/cli.js docs create --title "Scratch doc" --content "hello"
|
|
152
|
+
node src/cli.js docs show <doc-id>
|
|
153
|
+
node src/cli.js docs update <doc-id> --content-file ./doc.md
|
|
154
|
+
node src/cli.js directories create --title "Projects"
|
|
155
|
+
node src/cli.js directories list
|
|
156
|
+
node src/cli.js directories show <directory-id>
|
|
157
|
+
node src/cli.js directories update <directory-id> --title "Renamed"
|
|
158
|
+
node src/cli.js docs comment <doc-id> --body "Needs work" --line 12
|
|
159
|
+
node src/cli.js docs reply <comment-id> --body "Updated"
|
|
160
|
+
node src/cli.js docs comment-image <doc-id> --file ./image.png --line 12
|
|
161
|
+
node src/cli.js docs voice <doc-id> --file ./voice.aiff --line 12
|
|
162
|
+
|
|
163
|
+
node src/cli.js scopes create --title "Flight Deck" --level product
|
|
164
|
+
node src/cli.js scopes list
|
|
165
|
+
node src/cli.js scopes show <scope-id>
|
|
166
|
+
node src/cli.js scopes update <scope-id> --title "Flight Deck Core"
|
|
167
|
+
|
|
168
|
+
node src/cli.js storage upload ./image.png
|
|
169
|
+
node src/cli.js audio list
|
|
170
|
+
node src/cli.js audio show <audio-note-id>
|
|
171
|
+
node src/cli.js audio update-transcript <audio-note-id> --transcript "Transcript text"
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Agent Chat Runtime Tools
|
|
175
|
+
|
|
176
|
+
Phase 03 adds bot-friendly chat runtime commands. These commands persist a local "current chat context" in the SQLite mirror so Wingmen can bootstrap a session once, then use follow-up commands without custom shell glue. Runtime commands only support `--format json` in Phase 03 and default to JSON even without the global `--json` flag.
|
|
177
|
+
|
|
178
|
+
Context resolution order:
|
|
179
|
+
|
|
180
|
+
- explicit `--message`
|
|
181
|
+
- explicit `--thread`
|
|
182
|
+
- explicit `--channel` with the most recently active local thread in that channel
|
|
183
|
+
- last stored runtime context from local SQLite
|
|
184
|
+
|
|
185
|
+
### `chat context --format json`
|
|
186
|
+
|
|
187
|
+
Returns the active channel/thread context with participants and the latest few local thread messages.
|
|
188
|
+
|
|
189
|
+
```json
|
|
190
|
+
{
|
|
191
|
+
"channel_id": "chan_123",
|
|
192
|
+
"thread_id": "msg_root_1",
|
|
193
|
+
"participants": ["npub1bot...", "npub1user..."],
|
|
194
|
+
"recent_messages": [
|
|
195
|
+
{
|
|
196
|
+
"message_id": "msg_root_1",
|
|
197
|
+
"parent_message_id": null,
|
|
198
|
+
"sender_npub": "npub1user...",
|
|
199
|
+
"body": "@wingman can you review this?",
|
|
200
|
+
"attachments": [],
|
|
201
|
+
"updated_at": "2026-04-08T10:00:00.000Z"
|
|
202
|
+
}
|
|
203
|
+
]
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### `chat history --format json`
|
|
208
|
+
|
|
209
|
+
Returns paged local thread history for the active context. The first call returns the latest page in arrival order. Pass the returned cursor back in to page further back.
|
|
210
|
+
|
|
211
|
+
```json
|
|
212
|
+
{
|
|
213
|
+
"channel_id": "chan_123",
|
|
214
|
+
"thread_id": "msg_root_1",
|
|
215
|
+
"messages": [
|
|
216
|
+
{
|
|
217
|
+
"message_id": "msg_reply_2",
|
|
218
|
+
"parent_message_id": "msg_root_1",
|
|
219
|
+
"sender_npub": "npub1bot...",
|
|
220
|
+
"body": "I found the issue in the runtime helper.",
|
|
221
|
+
"attachments": [],
|
|
222
|
+
"updated_at": "2026-04-08T10:03:00.000Z"
|
|
223
|
+
}
|
|
224
|
+
],
|
|
225
|
+
"cursor": "offset:20"
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
### `chat search --format json`
|
|
230
|
+
|
|
231
|
+
Phase 05 keeps the Phase 04 workspace-local behavior and adds two bounded enhancements:
|
|
232
|
+
|
|
233
|
+
- `--reference` accepts exact `message:`, `thread:`, `channel:`, or `mention:` hints for direct lookup
|
|
234
|
+
- `--deep` adds bounded thread-level summaries with the top matching message snippets per thread
|
|
235
|
+
|
|
236
|
+
```json
|
|
237
|
+
{
|
|
238
|
+
"query": "find previous budget chats",
|
|
239
|
+
"references": [
|
|
240
|
+
{
|
|
241
|
+
"reference": "thread:msg_root_9",
|
|
242
|
+
"kind": "thread",
|
|
243
|
+
"channel_id": "chan_999",
|
|
244
|
+
"channel_title": "Budget Archive",
|
|
245
|
+
"thread_id": "msg_root_9",
|
|
246
|
+
"root_message_id": "msg_root_9",
|
|
247
|
+
"last_message_id": "msg_reply_11",
|
|
248
|
+
"message_count": 3,
|
|
249
|
+
"updated_at": "2026-04-07T19:12:00.000Z",
|
|
250
|
+
"summary": "Previous discussion about the same rollout.",
|
|
251
|
+
"participants": ["npub1bot...", "npub1user..."]
|
|
252
|
+
}
|
|
253
|
+
],
|
|
254
|
+
"results": [
|
|
255
|
+
{
|
|
256
|
+
"message_id": "msg_reply_2",
|
|
257
|
+
"channel_id": "chan_123",
|
|
258
|
+
"channel_title": "Agent Chat",
|
|
259
|
+
"thread_id": "msg_root_1",
|
|
260
|
+
"parent_message_id": "msg_root_1",
|
|
261
|
+
"sender_npub": "npub1bot...",
|
|
262
|
+
"body": "I found the issue in the runtime helper.",
|
|
263
|
+
"updated_at": "2026-04-08T10:03:00.000Z",
|
|
264
|
+
"scope": "current_thread"
|
|
265
|
+
}
|
|
266
|
+
],
|
|
267
|
+
"threads": [
|
|
268
|
+
{
|
|
269
|
+
"channel_id": "chan_123",
|
|
270
|
+
"channel_title": "Agent Chat",
|
|
271
|
+
"thread_id": "msg_root_1",
|
|
272
|
+
"root_message_id": "msg_root_1",
|
|
273
|
+
"last_message_id": "msg_reply_2",
|
|
274
|
+
"message_count": 4,
|
|
275
|
+
"updated_at": "2026-04-08T10:03:00.000Z",
|
|
276
|
+
"summary": "Please review the runtime helper rollout.",
|
|
277
|
+
"participants": ["npub1bot...", "npub1user..."],
|
|
278
|
+
"scope": "current_thread",
|
|
279
|
+
"matching_messages": [
|
|
280
|
+
{
|
|
281
|
+
"message_id": "msg_reply_2",
|
|
282
|
+
"sender_npub": "npub1bot...",
|
|
283
|
+
"body": "I found the issue in the runtime helper.",
|
|
284
|
+
"updated_at": "2026-04-08T10:03:00.000Z"
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
]
|
|
289
|
+
}
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
### `chat related --format json`
|
|
293
|
+
|
|
294
|
+
Phase 05 keeps the Phase 04 cross-chat behavior and adds `--deep`, which includes bounded supporting message snippets from each related thread.
|
|
295
|
+
|
|
296
|
+
```json
|
|
297
|
+
{
|
|
298
|
+
"message_id": "msg_reply_2",
|
|
299
|
+
"related_threads": [
|
|
300
|
+
{
|
|
301
|
+
"channel_id": "chan_123",
|
|
302
|
+
"channel_title": "Agent Chat",
|
|
303
|
+
"thread_id": "msg_root_9",
|
|
304
|
+
"root_message_id": "msg_root_9",
|
|
305
|
+
"last_message_id": "msg_reply_11",
|
|
306
|
+
"message_count": 3,
|
|
307
|
+
"updated_at": "2026-04-07T19:12:00.000Z",
|
|
308
|
+
"summary": "Previous discussion about the same rollout.",
|
|
309
|
+
"participants": ["npub1bot...", "npub1user..."],
|
|
310
|
+
"match_score": 24,
|
|
311
|
+
"relation": {
|
|
312
|
+
"same_channel": false,
|
|
313
|
+
"shared_terms": ["budget", "rollout"],
|
|
314
|
+
"shared_participants": ["npub1bot...", "npub1user..."]
|
|
315
|
+
},
|
|
316
|
+
"matching_messages": [
|
|
317
|
+
{
|
|
318
|
+
"message_id": "msg_reply_11",
|
|
319
|
+
"sender_npub": "npub1user...",
|
|
320
|
+
"body": "Budget notes from the earlier rollout are here.",
|
|
321
|
+
"updated_at": "2026-04-07T19:10:00.000Z"
|
|
322
|
+
}
|
|
323
|
+
]
|
|
324
|
+
}
|
|
325
|
+
]
|
|
326
|
+
}
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
### `chat reply-current --format json`
|
|
330
|
+
|
|
331
|
+
Replies into the active thread root stored in local runtime context, then updates that local context to the newly sent bot message.
|
|
332
|
+
|
|
333
|
+
```json
|
|
334
|
+
{
|
|
335
|
+
"channel_id": "chan_123",
|
|
336
|
+
"thread_id": "msg_root_1",
|
|
337
|
+
"message_id": "msg_bot_reply_3",
|
|
338
|
+
"status": "sent"
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
## Development
|
|
343
|
+
|
|
344
|
+
```bash
|
|
345
|
+
# Run commands locally
|
|
346
|
+
node src/cli.js status
|
|
347
|
+
node src/cli.js sync
|
|
348
|
+
|
|
349
|
+
# Run tests
|
|
350
|
+
npm test
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
Schema compatibility is part of the FlightDeck CLI test suite. It validates supported outbound families against the published Flight Deck manifests in `../sb-publisher/schemas/flightdeck`.
|
package/docs/to_fdcli.md
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# FlightDeck CLI Rollout
|
|
2
|
+
|
|
3
|
+
Yoke is becoming FlightDeck CLI so it can be installed reliably in local shells, CI jobs, and many Docker containers without cloning this repository in each environment.
|
|
4
|
+
|
|
5
|
+
## Package name
|
|
6
|
+
|
|
7
|
+
Use **FlightDeck CLI** as the product name.
|
|
8
|
+
|
|
9
|
+
Use `@runwingman/flightdeck-cli` as the npm package name. Keep `flightdeck-cli` as the executable name.
|
|
10
|
+
|
|
11
|
+
Keep `wingman-yoke` as a compatibility executable during the migration.
|
|
12
|
+
|
|
13
|
+
## Phase 1: Additive rename and compatibility
|
|
14
|
+
|
|
15
|
+
- Update visible CLI branding to FlightDeck CLI.
|
|
16
|
+
- Add the `flightdeck-cli` binary while keeping the existing `wingman-yoke` binary.
|
|
17
|
+
- Add preferred environment variables:
|
|
18
|
+
- `FLIGHTDECK_CLI_NSEC`
|
|
19
|
+
- `FLIGHTDECK_CLI_STATE_DIR`
|
|
20
|
+
- `FLIGHTDECK_CLI_ALLOW_STORAGE_KEY_GUESS`
|
|
21
|
+
- `FLIGHTDECK_CLI_AUDIO_S3_INPUT`
|
|
22
|
+
- Keep old variables working:
|
|
23
|
+
- `WINGMAN_YOKE_NSEC`
|
|
24
|
+
- `WINGMAN_YOKE_STATE_DIR`
|
|
25
|
+
- `WINGMAN_YOKE_ALLOW_STORAGE_KEY_GUESS`
|
|
26
|
+
- `WINGMAN_YOKE_AUDIO_S3_INPUT`
|
|
27
|
+
- Move the default local state directory to `./.flightdeck-cli` for new installs.
|
|
28
|
+
- Continue reading existing `./.wingman-yoke` and legacy `./.wingman-ap` state directories.
|
|
29
|
+
- Update README and command examples to prefer `flightdeck-cli`.
|
|
30
|
+
|
|
31
|
+
## Phase 2: npm distribution
|
|
32
|
+
|
|
33
|
+
- Rename package metadata to `@runwingman/flightdeck-cli`.
|
|
34
|
+
- Include both npm bin names:
|
|
35
|
+
- `flightdeck-cli`
|
|
36
|
+
- `wingman-yoke`
|
|
37
|
+
- Verify package contents with `npm pack --dry-run`.
|
|
38
|
+
- Verify installability with a packed tarball:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
npm pack
|
|
42
|
+
npm install -g ./runwingman-flightdeck-cli-*.tgz
|
|
43
|
+
flightdeck-cli --help
|
|
44
|
+
wingman-yoke --help
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
- Publish the new package when registry ownership is ready.
|
|
48
|
+
- Keep the old package as a compatibility alias or deprecated shim after the new package is live.
|
|
49
|
+
|
|
50
|
+
## Phase 3: Docker and script installs
|
|
51
|
+
|
|
52
|
+
- Add a Debian-based Dockerfile using Node 20 so native dependencies such as `better-sqlite3` build and load predictably.
|
|
53
|
+
- Prefer mounted state in Docker:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
docker run --rm \
|
|
57
|
+
-e FLIGHTDECK_CLI_NSEC="$FLIGHTDECK_CLI_NSEC" \
|
|
58
|
+
-e FLIGHTDECK_CLI_STATE_DIR=/state \
|
|
59
|
+
-v flightdeck-cli-state:/state \
|
|
60
|
+
runwingman/flightdeck-cli sync
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- Update `install.sh` to try npm first and fall back to git until the npm package is published.
|
|
64
|
+
- Keep a git install method for development or pre-publish testing.
|
|
65
|
+
- Create `flightdeck-cli` as the primary command and keep `wingman-yoke` available for existing automation.
|
|
66
|
+
|
|
67
|
+
## Release checklist
|
|
68
|
+
|
|
69
|
+
- `npm test`
|
|
70
|
+
- `npm pack --dry-run`
|
|
71
|
+
- install packed tarball in a temporary environment
|
|
72
|
+
- `flightdeck-cli --help`
|
|
73
|
+
- `wingman-yoke --help`
|
|
74
|
+
- Docker build smoke test
|
|
75
|
+
|
|
76
|
+
## Deprecation policy
|
|
77
|
+
|
|
78
|
+
Do not remove the old binary or old environment variables until downstream agent and Docker workflows have moved to FlightDeck CLI. At that point, emit warnings first, then remove compatibility in a later major version.
|
package/install.sh
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
# FlightDeck CLI installer
|
|
5
|
+
# Usage: curl -fsSL https://raw.githubusercontent.com/humansinstitute/wingman-yoke/main/install.sh | bash
|
|
6
|
+
|
|
7
|
+
PACKAGE="${FLIGHTDECK_CLI_PACKAGE:-@runwingman/flightdeck-cli}"
|
|
8
|
+
VERSION="${FLIGHTDECK_CLI_VERSION:-latest}"
|
|
9
|
+
INSTALL_METHOD="${FLIGHTDECK_CLI_INSTALL_METHOD:-npm}"
|
|
10
|
+
REPO="${FLIGHTDECK_CLI_REPO:-humansinstitute/wingman-yoke}"
|
|
11
|
+
INSTALL_DIR="${FLIGHTDECK_CLI_INSTALL_DIR:-${WINGMAN_YOKE_INSTALL_DIR:-$HOME/.flightdeck-cli}}"
|
|
12
|
+
BIN_DIR="${FLIGHTDECK_CLI_BIN_DIR:-/usr/local/bin}"
|
|
13
|
+
FLIGHTDECK_BIN_LINK="$BIN_DIR/flightdeck-cli"
|
|
14
|
+
YOKE_BIN_LINK="$BIN_DIR/wingman-yoke"
|
|
15
|
+
|
|
16
|
+
echo "Installing FlightDeck CLI..."
|
|
17
|
+
|
|
18
|
+
command -v node >/dev/null 2>&1 || { echo "Error: Node.js >= 20 is required. Install from https://nodejs.org"; exit 1; }
|
|
19
|
+
|
|
20
|
+
NODE_MAJOR=$(node -e "console.log(process.versions.node.split('.')[0])")
|
|
21
|
+
if [ "$NODE_MAJOR" -lt 20 ]; then
|
|
22
|
+
echo "Error: Node.js >= 20 required (found v$(node -v))"
|
|
23
|
+
exit 1
|
|
24
|
+
fi
|
|
25
|
+
|
|
26
|
+
command -v npm >/dev/null 2>&1 || { echo "Error: npm is required"; exit 1; }
|
|
27
|
+
|
|
28
|
+
link_git_install() {
|
|
29
|
+
local source_bin="$INSTALL_DIR/src/cli.js"
|
|
30
|
+
chmod +x "$source_bin"
|
|
31
|
+
|
|
32
|
+
if [ -w "$BIN_DIR" ]; then
|
|
33
|
+
ln -sf "$source_bin" "$FLIGHTDECK_BIN_LINK"
|
|
34
|
+
ln -sf "$source_bin" "$YOKE_BIN_LINK"
|
|
35
|
+
else
|
|
36
|
+
echo "Creating symlinks requires sudo..."
|
|
37
|
+
sudo ln -sf "$source_bin" "$FLIGHTDECK_BIN_LINK"
|
|
38
|
+
sudo ln -sf "$source_bin" "$YOKE_BIN_LINK"
|
|
39
|
+
fi
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
install_from_git() {
|
|
43
|
+
command -v git >/dev/null 2>&1 || { echo "Error: git is required for FLIGHTDECK_CLI_INSTALL_METHOD=git"; exit 1; }
|
|
44
|
+
|
|
45
|
+
if [ -d "$INSTALL_DIR" ]; then
|
|
46
|
+
echo "Removing previous install at $INSTALL_DIR..."
|
|
47
|
+
rm -rf "$INSTALL_DIR"
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
echo "Cloning from github.com/$REPO..."
|
|
51
|
+
git clone --depth 1 "https://github.com/$REPO.git" "$INSTALL_DIR" 2>&1 | tail -1
|
|
52
|
+
|
|
53
|
+
echo "Installing dependencies (this compiles better-sqlite3)..."
|
|
54
|
+
cd "$INSTALL_DIR"
|
|
55
|
+
npm install --omit=dev 2>&1 | tail -3
|
|
56
|
+
|
|
57
|
+
link_git_install
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
install_from_npm() {
|
|
61
|
+
if [ "$VERSION" = "latest" ]; then
|
|
62
|
+
npm install -g "$PACKAGE"
|
|
63
|
+
else
|
|
64
|
+
npm install -g "$PACKAGE@$VERSION"
|
|
65
|
+
fi
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
if [ "$INSTALL_METHOD" = "git" ]; then
|
|
69
|
+
install_from_git
|
|
70
|
+
else
|
|
71
|
+
if ! install_from_npm; then
|
|
72
|
+
echo "npm install failed for $PACKAGE@$VERSION."
|
|
73
|
+
echo "Falling back to git install from github.com/$REPO..."
|
|
74
|
+
install_from_git
|
|
75
|
+
fi
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
echo ""
|
|
79
|
+
echo "FlightDeck CLI installed successfully."
|
|
80
|
+
echo " Command: flightdeck-cli --help"
|
|
81
|
+
echo " Legacy: wingman-yoke --help"
|
|
82
|
+
echo ""
|
|
83
|
+
echo "Quick start:"
|
|
84
|
+
echo " export FLIGHTDECK_CLI_NSEC=<your-nsec>"
|
|
85
|
+
echo " flightdeck-cli init --token <connection_token>"
|
|
86
|
+
echo " flightdeck-cli sync"
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@runwingman/flightdeck-cli",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "FlightDeck CLI for Coworker v4 / SuperBased workspaces",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"author": "Humans Institute",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/humansinstitute/wingman-yoke.git"
|
|
11
|
+
},
|
|
12
|
+
"homepage": "https://github.com/humansinstitute/wingman-yoke#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/humansinstitute/wingman-yoke/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"wingman",
|
|
18
|
+
"flightdeck",
|
|
19
|
+
"cli",
|
|
20
|
+
"coworker",
|
|
21
|
+
"superbased",
|
|
22
|
+
"nostr"
|
|
23
|
+
],
|
|
24
|
+
"bin": {
|
|
25
|
+
"flightdeck-cli": "src/cli.js",
|
|
26
|
+
"wingman-yoke": "src/cli.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"src/",
|
|
30
|
+
"docs/to_fdcli.md",
|
|
31
|
+
"install.sh",
|
|
32
|
+
"Dockerfile",
|
|
33
|
+
"README.md",
|
|
34
|
+
"LICENSE"
|
|
35
|
+
],
|
|
36
|
+
"scripts": {
|
|
37
|
+
"start": "node src/cli.js",
|
|
38
|
+
"dev": "node src/cli.js",
|
|
39
|
+
"check": "node src/cli.js --help",
|
|
40
|
+
"pack:dry-run": "npm pack --dry-run",
|
|
41
|
+
"smoke:bin": "node src/cli.js --help",
|
|
42
|
+
"test": "node --test"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@nostr-superbased/core": "0.1.0",
|
|
46
|
+
"better-sqlite3": "^11.8.1",
|
|
47
|
+
"commander": "^13.1.0",
|
|
48
|
+
"nostr-tools": "^2.17.0"
|
|
49
|
+
},
|
|
50
|
+
"engines": {
|
|
51
|
+
"node": ">=20"
|
|
52
|
+
}
|
|
53
|
+
}
|