@feralfile/cli 1.6.0 → 2.0.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/docs/EXAMPLES.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Examples
2
2
 
3
- Copy‑pasteable commands that work with the current CLI.
3
+ Copy‑pasteable commands that work with the current CLI. ff-cli is deterministic: there's no built-in chat. Natural language belongs in your coding agent (Claude Code, Codex), which drives these commands via the `ff-control` skill. No LLM API key required.
4
4
 
5
5
  ## Setup
6
6
 
@@ -16,190 +16,249 @@ npm run dev -- config init
16
16
  npm run dev -- config validate
17
17
  ```
18
18
 
19
- ## OpenClaw skill prompt
19
+ ## Use with a coding agent
20
20
 
21
- If you want OpenClaw to run ff-cli end-to-end without confirmation, start from:
22
-
23
- `skills/ff-control/SKILL.md`
21
+ ff-cli ships a [Claude Code](https://docs.claude.com/en/docs/claude-code) / Codex skill at `skills/ff-control/SKILL.md`. Once installed, ask your agent in plain language ("Get 3 works from reas.eth and play on Living Room", "Build a playlist from this Objkt URL and publish to my feed") and it translates the request into `ff-cli find` or `ff-cli build` and runs the validate → play/publish flow for you.
24
22
 
25
23
  Recommended local install path:
26
24
 
27
25
  ```bash
28
- mkdir -p ~/.openclaw/skills
29
- ln -sfn ~/Work/ff-cli/skills/ff-control ~/.openclaw/skills/ff-control
26
+ git clone --depth=1 https://github.com/feral-file/ff-cli /tmp/ff-cli \
27
+ && mkdir -p ~/.claude/skills \
28
+ && cp -r /tmp/ff-cli/skills/ff-control ~/.claude/skills/
30
29
  ```
31
30
 
32
- Compatibility copy (same prompt):
31
+ The rest of this doc shows the deterministic commands the skill (or you) drives directly.
33
32
 
34
- `examples/openclaw-ff-skill.md`
33
+ ## Find an artwork
35
34
 
36
- Paste that prompt into your OpenClaw skill config, then test with plain requests like:
35
+ `ff-cli find` resolves a marketplace URL, raw `chain:contract:tokenId`, or wallet address into a playable DP-1 playlist. Sources: Art Blocks, Objkt, fxhash, OpenSea, SuperRare, Feral File, Neort, Verse, raw on-chain coordinates, and wallet addresses.
37
36
 
38
37
  ```bash
39
- "Get 3 works from reas.eth and send to Living Room"
40
- "Get 3 from Unsupervised and publish to my feed"
38
+ # Paste a URL and play it on your FF1
39
+ npm run dev -- find https://www.artblocks.io/collection/ringers-by-dmitri-cherniak --play
40
+
41
+ # Tezos / hic et nunc via Objkt (the alias resolves to a KT1 contract)
42
+ npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 --play
43
+
44
+ # Feral File artwork (public id may be hex or numeric)
45
+ npm run dev -- find https://feralfile.com/exhibitions/artwork/f0240e04d64717e319584957f6a83954b029254ad1260b6320472ea8c0c5b1cf --play
46
+
47
+ # Save without playing
48
+ npm run dev -- find ethereum:0xababababab20053426ad1c782de9ea8444358070:5001410 -o send-receive.json
49
+
50
+ # Single on-chain token by coordinates
51
+ npm run dev -- find ethereum:0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0:52932 -o token.json
52
+
53
+ # Tezos token by coordinates
54
+ npm run dev -- find tezos:KT1BcNnzWze3vCviwiETYNwcFSwjv6RihZEQ:22 -o tez-token.json
55
+
56
+ # Wallet address (owner lookup); cap the number of tokens with --limit
57
+ npm run dev -- find 0xaeE022552B539dB18297D7481b6D547C622488B3 -l 10 -o wallet.json
58
+
59
+ # Limit a large series to the first N tokens
60
+ npm run dev -- find https://www.artblocks.io/collection/ringers-by-dmitri-cherniak -l 5 -o ringers.json
61
+
62
+ # Build and publish to a configured feed server
63
+ npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 --publish
64
+
65
+ # Build, play on a named device, and skip interactive prompts
66
+ npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 --play -d "Living Room Display" -y
41
67
  ```
42
68
 
43
- ## Natural Language
69
+ OpenSea and Verse accept both item and collection/series URLs:
44
70
 
45
71
  ```bash
46
- # Interactive chat
47
- npm run dev chat
72
+ # OpenSea collection (Ethereum); slug resolved from the public page, no API key
73
+ npm run dev -- find https://opensea.io/collection/your-collection-slug -l 5 -o opensea.json
48
74
 
49
- # One-shot requests
50
- npm run dev -- chat "Get 3 works from reas.eth" -o playlist.json
51
- npm run dev -- chat "Get 3 works from einstein-rosen.tez"
52
- npm run dev -- chat "Get tokens 52932,52457 from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0" -v
53
- npm run dev -- chat "Make a playlist of 10 works from 0xaeE022552B539dB18297D7481b6D547C622488B3" -v
75
+ # Verse series
76
+ npm run dev -- find https://verse.works/series/your-series-slug -l 5 -o verse.json
77
+ ```
54
78
 
55
- # Switch model
56
- npm run dev -- chat "your request" --model grok
57
- npm run dev -- chat "your request" --model gpt
58
- npm run dev -- chat "your request" --model gemini
79
+ Run `npm run dev -- find --help` for the full input list and options.
59
80
 
60
- # Model names must match keys in config.json under `models`.
61
- ```
81
+ ## Build from structured params
62
82
 
63
- ## Deterministic Build (no AI)
83
+ Use `ff-cli build` when you already have the contract, token IDs, feed names, or artwork ids and want explicit control over ordering, durations, and title. The input is a JSON object with `requirements` and optional `playlistSettings`.
64
84
 
65
85
  ```bash
66
- # From file
86
+ # From a file
67
87
  npm run dev -- build examples/params-example.json -o playlist.json
68
88
 
69
89
  # From stdin
70
90
  cat examples/params-example.json | npm run dev -- build -o playlist.json
71
91
  ```
72
92
 
73
- Build from a Feral File public artwork id or artwork URL:
93
+ Each requirement has a `type`:
94
+
95
+ - `build_playlist` — `blockchain`, `contractAddress`, `tokenIds`, optional `quantity`
96
+ - `feral_file_artwork` — `artworkId` (a Feral File public artwork id or `/exhibitions/artwork/{id}` URL)
97
+ - `query_address` — `ownerAddress`, optional `quantity` (random selection)
98
+ - `fetch_feed` — `playlistName`, `quantity`
99
+
100
+ `playlistSettings` may set `title`, `durationPerItem`, `preserveOrder` (set `false` to shuffle), and `deviceName`.
101
+
102
+ ### From a contract + token IDs
74
103
 
75
104
  ```bash
76
- cat > /tmp/ff-artwork.json <<'JSON'
105
+ cat > /tmp/eth-tokens.json <<'JSON'
77
106
  {
78
107
  "requirements": [
79
108
  {
80
- "type": "feral_file_artwork",
81
- "artworkId": "https://feralfile.com/exhibitions/artwork/f0240e04d64717e319584957f6a83954b029254ad1260b6320472ea8c0c5b1cf"
109
+ "type": "build_playlist",
110
+ "blockchain": "ethereum",
111
+ "contractAddress": "0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0",
112
+ "tokenIds": ["52932", "52457"]
82
113
  }
83
114
  ],
84
115
  "playlistSettings": {
85
- "title": "Feral File Artwork"
116
+ "title": "ETH Tokens",
117
+ "preserveOrder": false,
118
+ "durationPerItem": 7
86
119
  }
87
120
  }
88
121
  JSON
89
122
 
90
- npm run dev -- build /tmp/ff-artwork.json -o playlist.json
123
+ npm run dev -- build /tmp/eth-tokens.json -o playlist-eth.json -v
91
124
  ```
92
125
 
93
- ## AI‑Orchestrated Deterministic Flow (prompts)
126
+ Tezos works the same way with `"blockchain": "tezos"` and a `KT1...` contract:
94
127
 
95
128
  ```bash
96
- # Show tool‑call progress and validation
97
- npm run dev -- chat "Build a playlist of my works from reas.eth plus 3 from Unsupervised" -v -o playlist.json
98
-
99
- # Build from a Feral File artwork URL
100
- npm run dev -- chat "Build a playlist from https://feralfile.com/exhibitions/artwork/f0240e04d64717e319584957f6a83954b029254ad1260b6320472ea8c0c5b1cf" -v -o playlist.json
129
+ cat > /tmp/tez-tokens.json <<'JSON'
130
+ {
131
+ "requirements": [
132
+ {
133
+ "type": "build_playlist",
134
+ "blockchain": "tezos",
135
+ "contractAddress": "KT1BcNnzWze3vCviwiETYNwcFSwjv6RihZEQ",
136
+ "tokenIds": ["22", "8"]
137
+ }
138
+ ],
139
+ "playlistSettings": { "title": "Tezos Tokens", "preserveOrder": false }
140
+ }
141
+ JSON
101
142
 
102
- # Switch model if desired
103
- npm run dev -- chat "Build playlist from Ethereum address 0xaeE022552B539dB18297D7481b6D547C622488B3 and 2 from Unsupervised" --model gpt -v
143
+ npm run dev -- build /tmp/tez-tokens.json -o playlist-tez.json -v
104
144
  ```
105
145
 
106
- ### One‑shot complex prompt
107
-
108
- The CLI can parse rich requests and do it all in one go: fetch, build a DP‑1 playlist, shuffle, set durations, and send to a named device.
146
+ ### From a wallet address
109
147
 
110
148
  ```bash
111
- # Example: combine sources, shuffle, set 6s per item, and send to device
112
- npm run dev -- chat "Get tokens 52932,52457 from contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 and 2 from reas.eth; shuffle; 6 seconds each; send to 'Living Room Display'." -o playlist.json -v
149
+ cat > /tmp/wallet.json <<'JSON'
150
+ {
151
+ "requirements": [
152
+ {
153
+ "type": "query_address",
154
+ "ownerAddress": "0xaeE022552B539dB18297D7481b6D547C622488B3",
155
+ "quantity": 5
156
+ }
157
+ ],
158
+ "playlistSettings": { "title": "From a wallet", "preserveOrder": false }
159
+ }
160
+ JSON
161
+
162
+ npm run dev -- build /tmp/wallet.json -o playlist-wallet.json -v
113
163
  ```
114
164
 
115
- ## Feral File Built Playlists
165
+ ### From a feed playlist
116
166
 
117
- Use exhibition titles from the official playlist repository:
118
- `https://github.com/feral-file/dp1-feed/tree/main/playlists`
167
+ Feed playlist queries require reachable feed servers in your config. Reference exhibition titles from the official playlist repository: `https://github.com/feral-file/dp1-feed/tree/main/playlists`.
119
168
 
120
169
  ```bash
121
- # Fetch from a built playlist title
122
- npm run dev -- chat "Get 3 from Unsupervised" -v
170
+ cat > /tmp/feed.json <<'JSON'
171
+ {
172
+ "requirements": [
173
+ { "type": "fetch_feed", "playlistName": "Unsupervised", "quantity": 3 }
174
+ ],
175
+ "playlistSettings": { "title": "From a feed", "preserveOrder": false }
176
+ }
177
+ JSON
123
178
 
124
- # Mix a built playlist with wallet/domain sources
125
- npm run dev -- chat "Get 3 from Unsupervised and 2 from reas.eth" -v -o playlist.json
179
+ npm run dev -- build /tmp/feed.json -o playlist-feed.json -v
126
180
  ```
127
181
 
128
- Notes:
129
-
130
- - Feed playlist queries require reachable feed servers in your config.
131
- - If no feeds are reachable, feed playlist examples will fail even if the title exists.
132
- - Bare EVM prompts (`from 0x...`) now fall back from owner lookup to contract lookup when needed.
133
-
134
- ## Natural Language: Display and Publish
135
-
136
- The CLI recognizes publishing keywords like "publish", "publish to my feed", "push to feed", "send to feed" and automatically publishes after building.
137
-
138
- ### Basic Publishing
182
+ ### From a Feral File artwork
139
183
 
140
184
  ```bash
141
- # Build and publish
142
- npm run dev -- chat "Build playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 with tokens 52932 and 52457; publish to my feed" -o playlist.json -v
143
-
144
- # With feed selection (if multiple servers configured)
145
- # The CLI will ask: "Which feed server? 1) https://dp1-feed-operator-api-prod.autonomy-system.workers.dev/api/v1 2) http://localhost:8787"
146
- npm run dev -- chat "Get 3 from Unsupervised and publish to feed" -v
147
-
148
- # Publish existing playlist (defaults to ./playlist.json)
149
- npm run dev chat
150
- # Then type: "publish playlist"
185
+ cat > /tmp/ff-artwork.json <<'JSON'
186
+ {
187
+ "requirements": [
188
+ {
189
+ "type": "feral_file_artwork",
190
+ "artworkId": "https://feralfile.com/exhibitions/artwork/f0240e04d64717e319584957f6a83954b029254ad1260b6320472ea8c0c5b1cf"
191
+ }
192
+ ],
193
+ "playlistSettings": { "title": "Feral File Artwork" }
194
+ }
195
+ JSON
151
196
 
152
- # Publish specific playlist file
153
- npm run dev chat
154
- # Then type: "publish the playlist ./playlist-temp.json"
197
+ npm run dev -- build /tmp/ff-artwork.json -o playlist.json
155
198
  ```
156
199
 
157
- ### Combined: Display + Publish
200
+ ### Mixing sources in one playlist
201
+
202
+ Combine multiple requirements; shuffle with `preserveOrder: false` and set per-item timing with `durationPerItem`.
158
203
 
159
204
  ```bash
160
- # Display on Art Computer AND publish to feed
161
- npm run dev -- chat "Build playlist from contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 with tokens 52932 and 52457; mix them up; send to my Art Computer and publish to my feed" -o playlist.json -v
205
+ cat > /tmp/mixed.json <<'JSON'
206
+ {
207
+ "requirements": [
208
+ {
209
+ "type": "build_playlist",
210
+ "blockchain": "tezos",
211
+ "contractAddress": "KT1BcNnzWze3vCviwiETYNwcFSwjv6RihZEQ",
212
+ "tokenIds": ["22", "8"]
213
+ },
214
+ {
215
+ "type": "build_playlist",
216
+ "blockchain": "ethereum",
217
+ "contractAddress": "0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0",
218
+ "tokenIds": ["52932", "52457"]
219
+ },
220
+ { "type": "fetch_feed", "playlistName": "Unsupervised", "quantity": 3 },
221
+ { "type": "query_address", "ownerAddress": "reas.eth", "quantity": 1 }
222
+ ],
223
+ "playlistSettings": {
224
+ "title": "Mixed",
225
+ "preserveOrder": false,
226
+ "durationPerItem": 6,
227
+ "deviceName": "Living Room Display"
228
+ }
229
+ }
230
+ JSON
162
231
 
163
- # With explicit device name
164
- npm run dev -- chat "Get 5 from Unsupervised, shuffle, display on 'Living Room', and publish to feed" -v
232
+ npm run dev -- build /tmp/mixed.json -o playlist-mixed.json -v
165
233
  ```
166
234
 
167
- ### How It Works
168
-
169
- **Mode 1: Build and Publish** (when sources are mentioned)
170
-
171
- 1. Intent parser detects "publish" keywords with sources/requirements
172
- 2. Calls `get_feed_servers` to retrieve configured servers
173
- 3. If 1 server → uses it automatically; if 2+ servers → asks user to pick
174
- 4. Builds playlist → validates structure → publishes automatically
235
+ ## Validate / Sign / Play
175
236
 
176
- **Mode 2: Publish Existing File** (e.g., "publish playlist")
237
+ ```bash
238
+ # Validate playlist structure
239
+ npm run dev -- validate playlist.json
240
+ npm run dev -- validate "https://cdn.example.com/playlist.json"
177
241
 
178
- 1. Intent parser detects "publish playlist" or similar phrases
179
- 2. Calls `get_feed_servers` to retrieve configured servers
180
- 3. If 1 server → uses it automatically; if 2+ servers → asks user to pick
181
- 4. Publishes the playlist from `./playlist.json` (or specified path)
242
+ # Validate structure AND verify signatures
243
+ npm run dev -- verify playlist.json
182
244
 
183
- Output shows:
245
+ # Sign playlist (uses key/role from config, or override via --key / --role)
246
+ npm run dev -- sign playlist.json -o signed.json
184
247
 
185
- - Playlist build progress (Mode 1 only)
186
- - Device sending (if requested): `✓ Sent to device: Living Room`
187
- - Publishing status: `✓ Published to feed server`
188
- - Playlist ID: `Playlist ID: 84e028f8-...`
248
+ # Play on the configured default device
249
+ npm run dev -- play playlist.json
189
250
 
190
- ## Validate / Sign / Send
251
+ # Play on a specific named device
252
+ npm run dev -- play signed.json -d "Living Room Display"
191
253
 
192
- ```bash
193
- # Validate playlist
194
- npm run dev -- validate playlist.json
195
- npm run dev -- validate "https://cdn.example.com/playlist.json"
254
+ # Play a hosted DP-1 playlist
255
+ npm run dev -- play "https://cdn.example.com/playlist.json"
196
256
 
197
- # Sign playlist
198
- npm run dev -- sign playlist.json -o signed.json
257
+ # Play a media URL directly
258
+ npm run dev -- play "https://example.com/video.mp4"
199
259
 
200
- # Send to device
201
- npm run dev -- send playlist.json -d "Living Room Display"
202
- npm run dev -- send "https://cdn.example.com/playlist.json" -d "Living Room Display"
260
+ # Skip verification only if you must send a non-conformant payload (not recommended)
261
+ npm run dev -- play playlist.json --skip-verify
203
262
  ```
204
263
 
205
264
  ## Publish to Feed Server
@@ -240,9 +299,9 @@ npm run dev -- publish --help
240
299
 
241
300
  ### Flow
242
301
 
243
- 1. **Validate** - Playlist structure checked (`validate`-style parse; use `verify` for signatures)
302
+ 1. **Verify** - Playlist structure and signatures checked; unsigned or broken playlists are rejected
244
303
  2. **Select Server** - If multiple servers, choose which one (interactive or via `-s` flag)
245
- 3. **Publish** - Send validated playlist to selected feed server
304
+ 3. **Publish** - Send the verified playlist to the selected feed server
246
305
  4. **Confirm** - Returns playlist ID and server details
247
306
 
248
307
  ### Example Output
@@ -287,11 +346,11 @@ Select server (0-based index): 0
287
346
  Failed to publish: {"error":"unauthorized","message":"Invalid API key"}
288
347
  ```
289
348
 
290
- ## Validate / Sign / Send / Publish (Complete Flow)
349
+ ## Complete Flow (build → validate → sign → play → publish)
291
350
 
292
351
  ```bash
293
- # 1. Create a playlist (via chat or build)
294
- npm run dev -- chat "Get 3 works from reas.eth" -o playlist.json
352
+ # 1. Build a playlist (via find or build)
353
+ npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 -o playlist.json
295
354
 
296
355
  # 2. Validate it
297
356
  npm run dev -- validate playlist.json
@@ -299,13 +358,38 @@ npm run dev -- validate playlist.json
299
358
  # 3. Sign it
300
359
  npm run dev -- sign playlist.json -o signed.json
301
360
 
302
- # 4. Send to device
303
- npm run dev -- send signed.json -d "My Display"
361
+ # 4. Play it on a device
362
+ npm run dev -- play signed.json -d "Living Room Display"
304
363
 
305
- # 5. Publish to feed server
364
+ # 5. Publish to a feed server
306
365
  npm run dev -- publish signed.json -s 0
307
366
  ```
308
367
 
368
+ `ff-cli find` can collapse build + play + publish into one command:
369
+
370
+ ```bash
371
+ npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 --play -d "Living Room Display" --publish
372
+ ```
373
+
374
+ ## FF1 device management
375
+
376
+ ```bash
377
+ # List configured devices
378
+ npm run dev -- device list
379
+
380
+ # Add a device interactively (with mDNS discovery)
381
+ npm run dev -- device add
382
+
383
+ # Add a device non-interactively
384
+ npm run dev -- device add --host 192.168.1.100 --name kitchen
385
+
386
+ # Remove a device by name
387
+ npm run dev -- device remove kitchen
388
+
389
+ # Set the default device (used when -d is omitted)
390
+ npm run dev -- device default office
391
+ ```
392
+
309
393
  ## Troubleshooting
310
394
 
311
395
  ```bash
@@ -314,100 +398,7 @@ npm run dev -- config show
314
398
 
315
399
  # Reinitialize config
316
400
  npm run dev -- config init
317
- ```
318
401
 
319
- ### Natural‑language one‑shot examples (proven)
320
-
321
- - **ETH contract + token IDs (shuffle/mix, generic device)**
322
- - Format:
323
- ```bash
324
- npm run dev -- chat "Compose a playlist from Ethereum contract <0x...> with tokens <id> and <id>; [shuffle|mix]; [send to device|send to '<device>']" -o <output.json> -v
325
- ```
326
- - Example:
327
- ```bash
328
- npm run dev -- chat "Compose a playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 with tokens 52932 and 52457; mix them up; send to device" -o playlist-eth.json -v
329
- ```
330
-
331
- - **TEZ contract + token IDs (shuffle, named device)**
332
- - Format:
333
- ```bash
334
- npm run dev -- chat "Build a playlist from Tezos contract <KT1...> with tokens <id> and <id>; shuffle; send to '<device>'" -o <output.json> -v
335
- ```
336
- - Example:
337
- ```bash
338
- npm run dev -- chat "Build a playlist from Tezos contract KT1BcNnzWze3vCviwiETYNwcFSwjv6RihZEQ with tokens 22 and 8; shuffle; send to 'Living Room'" -o playlist-tez.json -v
339
- ```
340
-
341
- - **Owner address (ENS → ETH), shuffled**
342
- - Format:
343
- ```bash
344
- npm run dev -- chat "Create a playlist from address <ens> (<n> items); [shuffle|mix]; [send/push to my device]" -o <output.json> -v
345
- ```
346
- - Example:
347
- ```bash
348
- npm run dev -- chat "Create a playlist from address reas.eth (5 items); shuffle; push to my device" -o playlist-ens.json -v
349
- ```
350
-
351
- - **Owner address (Tezos tz1), shuffled**
352
- - Format:
353
- ```bash
354
- npm run dev -- chat "Create a playlist from Tezos address <tz1...> (<n> items); [shuffle|mix]; [send to device]" -o <output.json> -v
355
- ```
356
- - Example:
357
- ```bash
358
- npm run dev -- chat "Create a playlist from Tezos address tz1VSUr8wwNhLAzempoch5d6hLRiTh8Cjcjb (3 items); mix them up; send to device" -o playlist-tz1.json -v
359
- ```
360
-
361
- - **Feed playlists (named), shuffled**
362
- - Format:
363
- ```bash
364
- npm run dev -- chat "[Create|Build] a playlist from feed '<name>' (<n> items); shuffle; [send to device]" -o <output.json> -v
365
- ```
366
- - Examples:
367
- ```bash
368
- npm run dev -- chat "Create a playlist from feed 'Unsupervised' (3 items); shuffle; send to device" -o playlist-feed1.json -v
369
- npm run dev -- chat "Build a playlist from feed 'Unsupervised' (3 items); shuffle; send to device" -o playlist-feed2.json -v
370
- ```
371
-
372
- - **Mixed in one prompt (ETH + TEZ + feed + ENS), shuffled, named device**
373
- - Format:
374
- ```bash
375
- npm run dev -- chat "Compose a playlist: Tezos <KT1...> tokens <id>, <id>; Ethereum <0x...> tokens <id>, <id>; <n> from '<feed>'; <m> from <ens>; shuffle; send to '<device>'" -o <output.json> -v
376
- ```
377
- - Example:
378
- ```bash
379
- npm run dev -- chat "Compose a playlist: Tezos KT1BcNnzWze3vCviwiETYNwcFSwjv6RihZEQ tokens 22, 8; Ethereum 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 tokens 52932, 52457; 3 from 'Unsupervised'; 1 from reas.eth; shuffle; send to 'Living Room'" -o playlist-mixed.json -v
380
- ```
381
-
382
- - **Multiple instructions in one prompt (incremental), shuffled**
383
- - Format:
384
- ```bash
385
- npm run dev -- chat "Create a playlist from Ethereum contract <0x...> tokens <id>, <id>; then add <n> from '<feed>'; then add <m> from <ens>; shuffle; [send/push to my device]" -o <output.json> -v
386
- ```
387
- - Example:
388
- ```bash
389
- npm run dev -- chat "Create a playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 tokens 52932, 52457; then add 2 from 'Unsupervised'; then add 1 from reas.eth; shuffle; push to my device" -o playlist-multi.json -v
390
- ```
391
-
392
- - **Synonym variants for the same ETH case**
393
- - Format:
394
- ```bash
395
- npm run dev -- chat "[Build|Create|Compose] a playlist from Ethereum contract <0x...> tokens <id> and <id>; send to device" -o <output.json> -v
396
- ```
397
- - Examples:
398
- ```bash
399
- npm run dev -- chat "Build a playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 tokens 52932 and 52457; send to device" -o playlist-eth-build.json -v
400
- npm run dev -- chat "Create a playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 tokens 52932 and 52457; send to device" -o playlist-eth-create.json -v
401
- ```
402
-
403
- - **Device targeting: generic vs named**
404
- - Format:
405
- ```bash
406
- npm run dev -- chat "Compose a playlist from <ens/address> (<n> items); send to device" -o <output.json> -v
407
- npm run dev -- chat "Compose a playlist from <ens/address> (<n> items); send to '<device>'" -o <output.json> -v
408
- ```
409
- - Examples:
410
- ```bash
411
- npm run dev -- chat "Compose a playlist from reas.eth (3 items); send to device" -o playlist-generic-device.json -v
412
- npm run dev -- chat "Compose a playlist from reas.eth (3 items); send to 'Living Room'" -o playlist-named-device.json -v
413
- ```
402
+ # Validate configuration
403
+ npm run dev -- config validate
404
+ ```
@@ -15,7 +15,9 @@ It is derived from the behavior and interfaces implemented in this repository as
15
15
  - Project: `ff-cli`
16
16
  - Type: Node.js CLI
17
17
  - System role: a control and integration surface for FF1 and DP-1 workflows
18
- - Primary purpose: turn user intent or structured parameters into valid DP-1 playlists, then validate them and optionally sign, publish, and send them through FF1 and feed paths
18
+ - Primary purpose: turn resolved sources or structured parameters into valid DP-1 playlists deterministically, then validate them and optionally sign, publish, and play them through FF1 and feed paths
19
+
20
+ There is no built-in natural-language interface and no model orchestration. Natural language belongs in the user's coding agent (Claude Code, Codex), which drives ff-cli's deterministic commands via the `ff-control` skill. ff-cli requires no LLM API key.
19
21
 
20
22
  In the Feral File architecture bands, `ff-cli` sits primarily in the presentation and control layer. It is not the canonical source of truth for exhibitions, ownership, device runtime, or protocol evolution. It is a practical operator and developer surface that bridges those systems.
21
23
 
@@ -28,7 +30,7 @@ Its value is reducing friction in the publish-to-play path:
28
30
  - assemble playlists quickly
29
31
  - keep outputs DP-1 conformant
30
32
  - make FF1 playback and feed publishing easier to exercise
31
- - provide deterministic tooling around model-assisted workflows
33
+ - provide deterministic tooling that agents and scripts can drive reliably
32
34
 
33
35
  The CLI should strengthen the Gold Path, not invent a parallel product model.
34
36
 
@@ -44,11 +46,11 @@ Current likely users:
44
46
  Primary use cases:
45
47
 
46
48
  - build a playlist from structured JSON inputs
47
- - build a playlist from natural-language prompts using model orchestration plus deterministic tools
49
+ - resolve a marketplace URL, on-chain coordinates, or a wallet address into a playlist (`find`)
48
50
  - validate or verify a local or hosted DP-1 playlist
49
51
  - sign a playlist with an Ed25519 key
50
52
  - publish a validated playlist to a configured feed server
51
- - send a playlist or direct media URL to a configured FF1 device
53
+ - play a playlist or direct media URL on a configured FF1 device
52
54
  - manage local config and FF1 SSH access
53
55
  - exercise compatibility checks against FF1 OS versions before risky commands
54
56
 
@@ -100,9 +102,9 @@ Long-term interoperability should continue to reduce hard infrastructure couplin
100
102
  Based on the code today, the CLI is responsible for:
101
103
 
102
104
  - loading configuration from `config.json`, `.env`, and defaults, with `config.json` taking precedence
103
- - parsing natural-language requests into structured playlist requirements and settings
104
- - orchestrating tool calls for feed fetches, address queries, contract-based NFT queries, domain resolution, playlist building, verification, publishing, and sending
105
- - supporting a deterministic non-AI build path from structured JSON
105
+ - resolving marketplace URLs, on-chain coordinates, and wallet addresses into playlists (`find`)
106
+ - running feed fetches, address queries, contract-based NFT queries, domain resolution, playlist building, verification, publishing, and playback
107
+ - supporting a deterministic build path from structured JSON (`build`)
106
108
  - building DP-1 playlist envelopes from NFT metadata or direct media URLs
107
109
  - validating and verifying playlist structure and signatures
108
110
  - signing playlists when a private key is configured
@@ -116,7 +118,7 @@ Based on the code today, the CLI is responsible for:
116
118
 
117
119
  - command-line UX and command routing
118
120
  - local config loading and validation
119
- - intent parsing and orchestration glue
121
+ - source resolution (`find`) and structured-params handling (`build`)
120
122
  - deterministic playlist assembly, verification, and signing helpers
121
123
  - device and feed integration calls from the client side
122
124
 
@@ -132,8 +134,8 @@ Based on the code today, the CLI is responsible for:
132
134
 
133
135
  - The CLI may assemble, validate, and transmit DP-1 objects, but it should not silently fork the protocol.
134
136
  - The CLI may call feed and device endpoints, but it should not become their compatibility abstraction layer of last resort.
135
- - The CLI may use models for orchestration, but deterministic utilities remain the source of truth for output correctness.
136
- - Trust-sensitive correctness must stay vendor-neutral and portable. The CLI can use cloud APIs for model orchestration, but the trust path cannot depend on cloud-specific guarantees.
137
+ - Deterministic utilities remain the source of truth for output correctness; the CLI does not interpret natural language or orchestrate models.
138
+ - Trust-sensitive correctness must stay vendor-neutral and portable; the trust path cannot depend on cloud-specific guarantees.
137
139
  - Current implementation note: some retrieval paths still use Feral File-operated services directly, so portability here is an intended direction rather than a fully achieved property.
138
140
 
139
141
  ## Functional shape
@@ -146,9 +148,9 @@ Today the CLI groups into these workflow areas:
146
148
  - `status`
147
149
  - `config init|show|validate`
148
150
 
149
- ### Build and orchestration
151
+ ### Build
150
152
 
151
- - `chat`
153
+ - `find`
152
154
  - `build`
153
155
 
154
156
  ### DP-1 output integrity
@@ -168,11 +170,11 @@ Today the CLI groups into these workflow areas:
168
170
 
169
171
  ## Deterministic-first behavior
170
172
 
171
- The CLI supports model-assisted workflows, but the implementation posture should remain deterministic-first:
173
+ The CLI is deterministic end to end. There is no natural-language interface; any natural-language layer lives in the user's coding agent, which drives these commands:
172
174
 
173
- - models interpret intent
174
- - utilities perform the real data fetching, playlist building, validation, signing, and delivery work
175
- - invalid or malformed outputs should fail validation rather than being accepted because they were model-produced
175
+ - commands map directly to source resolution, data fetching, playlist building, validation, signing, and delivery
176
+ - utilities perform the real work and are the source of truth for output correctness
177
+ - invalid or malformed outputs fail validation rather than being passed through
176
178
 
177
179
  ## Trust, protocol, and rights assumptions
178
180
 
@@ -216,8 +218,8 @@ The current repo verification path is:
216
218
  npm run lint:fix
217
219
  npm test
218
220
  npm run build
219
- ANTHROPIC_API_KEY=dummy node dist/index.js validate examples/sample-playlist.json
220
- ANTHROPIC_API_KEY=dummy node dist/index.js config validate
221
+ node dist/index.js validate examples/sample-playlist.json
222
+ node dist/index.js config validate
221
223
  ```
222
224
 
223
225
  ## Open questions