@feralfile/cli 1.6.0 → 2.0.1

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.
@@ -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
package/docs/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # ff-cli Documentation
2
2
 
3
- Build DP-1 (Display Protocol 1) playlists from NFT data with either natural language (AI‑driven) or deterministic parameters. This doc covers install, config, and day‑to‑day usage.
3
+ ff-cli is a set of deterministic commands for building DP-1 (Display Protocol 1) playlists and playing them on an Art Computer. There's no built-in chat — natural language belongs in your coding agent (Claude Code, Codex), which drives ff-cli through the `ff-control` skill. No LLM API key required. This doc covers install, config, and day‑to‑day usage.
4
4
 
5
5
  For project-level planning and future agentic work, see `./PROJECT_SPEC.md`.
6
6
 
@@ -42,33 +42,6 @@ ff-cli config validate
42
42
 
43
43
  ```json
44
44
  {
45
- "defaultModel": "claude",
46
- "models": {
47
- "claude": {
48
- "apiKey": "sk-ant-your-api-key-here",
49
- "baseURL": "https://api.anthropic.com/v1/",
50
- "model": "claude-sonnet-4-6",
51
- "supportsFunctionCalling": true
52
- },
53
- "grok": {
54
- "apiKey": "xai-your-api-key-here",
55
- "baseURL": "https://api.x.ai/v1",
56
- "model": "grok-beta",
57
- "supportsFunctionCalling": true
58
- },
59
- "gpt": {
60
- "apiKey": "sk-your-openai-key-here",
61
- "baseURL": "https://api.openai.com/v1",
62
- "model": "gpt-4o",
63
- "supportsFunctionCalling": true
64
- },
65
- "gemini": {
66
- "apiKey": "your-gemini-key-here",
67
- "baseURL": "https://generativelanguage.googleapis.com/v1beta/openai/",
68
- "model": "gemini-2.5-flash",
69
- "supportsFunctionCalling": true
70
- }
71
- },
72
45
  "defaultDuration": 10,
73
46
  "playlist": {
74
47
  "privateKey": "your_ed25519_private_key_hex_or_base64_here"
@@ -92,13 +65,13 @@ See `./CONFIGURATION.md` for environment variable mappings.
92
65
  ## Quick Start
93
66
 
94
67
  ```bash
95
- # Chat
96
- ff-cli chat
68
+ # Resolve a URL, on-chain coords, or wallet and build a playlist
69
+ ff-cli find https://www.artblocks.io/collection/ringers-by-dmitri-cherniak -o playlist.json
97
70
 
98
- # Or natural language in one shot
99
- ff-cli chat "Get 3 works from reas.eth" -o playlist.json
71
+ # Build and play it on your FF1 in one step
72
+ ff-cli find https://objkt.com/tokens/hicetnunc/111068 --play
100
73
 
101
- # Deterministic (no AI)
74
+ # Build from pre-structured params (JSON file or stdin)
102
75
  ff-cli build examples/params-example.json -o playlist.json
103
76
  ```
104
77
 
@@ -106,38 +79,26 @@ For development in this repo:
106
79
 
107
80
  ```bash
108
81
  npm run build
109
- node dist/index.js chat
82
+ node dist/index.js find https://objkt.com/tokens/hicetnunc/111068 --play
110
83
  ```
111
84
 
112
85
  If you're running from source without a build, use:
113
86
 
114
87
  ```bash
115
- npm run dev -- chat
88
+ npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 --play
116
89
  ```
117
90
 
118
- ## Recommended Deterministic Flow (LLM + Tools)
119
-
120
- The model orchestrates; deterministic tools keep us honest and DP1‑conformant.
91
+ ## Two ways to build a playlist
121
92
 
122
- 1. Input: Share the essentials (contract + token IDs, or feed/URL names).
123
- 2. Orchestration: The LLM parses your prompt and calls tools that:
124
- - Fetch NFT metadata via OSS libs (`viem` for Ethereum, `@taquito/taquito` for Tezos)
125
- - Validate DP1 schema with `dp1-js`
126
- - Build a DP1 playlist envelope deterministically
127
- - Optionally sign with Ed25519 (canonical JSON via `dp1-js`)
128
- 3. Preview/send: Send to an FF1 on your LAN over HTTP (recommended). Point `ff1Devices.devices[].host` at a local relay if needed.
129
- 4. Publish: Optional feed/registry publishing via the `publish` command.
93
+ ff-cli is deterministic: no chat, no model orchestration. There are two entry points for assembling a playlist.
130
94
 
131
- Notes:
95
+ 1. **`ff-cli find "<input>"`** — resolve a marketplace URL, raw `chain:contract:tokenId`, or wallet address into a playable DP-1 playlist. Add `--play` to build and play in one step. This is the fastest path for a single artwork, a collection/series, or a wallet.
96
+ 2. **`ff-cli build <params.json>`** — build from pre-structured `requirements` and `playlistSettings` (JSON file or stdin). Use this when you already have the contract, token IDs, feed names, or artwork ids and want explicit control over ordering, durations, and title.
132
97
 
133
- - **Deterministic by design**: Validation rejects bad or hallucinated data; we loop until it's valid or stop.
134
- - **OSS‑first**: `viem` and `@taquito/taquito`, with room for local caching.
135
- - **Relay**: Swap the example host for a local Node/Hono relay; avoid vendor lock‑in.
98
+ Both paths run the same deterministic pipeline: fetch metadata, assemble a DP-1 envelope, and validate it. Validation rejects malformed data rather than passing it through. Natural language lives in your coding agent (Claude Code, Codex) via the `ff-control` skill, which translates a request into one of these two commands.
136
99
 
137
100
  ## Commands (cheat sheet)
138
101
 
139
- - `chat [content]` – AI-driven natural language playlists
140
- - Options: `-o, --output <file>`, `-m, --model <name>`, `-d, --device <name>`, `-v, --verbose`
141
102
  - `build [params.json]` – Deterministic build from JSON or stdin
142
103
  - Options: `-o, --output <file>`, `-v, --verbose`
143
104
  - `validate <file-or-url>` – Validate playlist structure only
@@ -164,76 +125,63 @@ Notes:
164
125
 
165
126
  ## Usage Highlights
166
127
 
167
- ### Natural language (AI)
128
+ ### Find an artwork
168
129
 
169
- ```bash
170
- npm run dev -- chat "Get 3 works from reas.eth"
171
- npm run dev -- chat "Get 3 works from einstein-rosen.tez"
172
- npm run dev -- chat "Get tokens 52932,52457 from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0" -o playlist.json
173
- ```
174
-
175
- Feed playlists (for example `Unsupervised`, `Social Codes`) depend on your configured feed servers and network reachability.
176
- Use exact or near-exact playlist titles for best results.
177
-
178
- If you prompt with a bare EVM address (for example `from 0x...`), the CLI now tries owner-address lookup first, then automatically falls back to contract lookup when no owned tokens are found.
179
-
180
- ### One-shot complex prompt
181
-
182
- The model reads your request via the intent parser and turns it into structured `requirements` and `playlistSettings` (including shuffle, durations, and device). You can do everything in one line:
130
+ `ff-cli find` resolves a URL, raw `chain:contract:tokenId`, or wallet address into a playable DP-1 playlist.
183
131
 
184
132
  ```bash
185
- # Mix sources, shuffle order, set per-item duration, and send to a named device
186
- npm run dev -- chat "From Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 get tokens 52932,52457 and from reas.eth get 2 works; shuffle the order; 7 seconds per item; send to device 'Living Room Display'." -o playlist.json -v
187
- ```
133
+ # Paste a URL and play it on your FF1
134
+ ff-cli find https://www.artblocks.io/collection/ringers-by-dmitri-cherniak --play
188
135
 
189
- How it works (at a glance):
136
+ # Tezos / hic et nunc via Objkt (the alias resolves to a KT1 contract)
137
+ ff-cli find https://objkt.com/tokens/hicetnunc/111068 --play
190
138
 
191
- - The intent parser maps your text to `requirements` (what to fetch) and `playlistSettings` (e.g., `durationPerItem`, `preserveOrder=false` for shuffle, `deviceName`, `feedServer`).
192
- - Deterministic tools fetch NFT metadata, build a DP‑1 playlist, and verify it.
193
- - If `deviceName` is present, the CLI will send the verified playlist to that FF1 device.
194
- - If `feedServer` is present (via "publish to my feed"), the CLI will publish the playlist to the selected feed server.
139
+ # Save without playing
140
+ ff-cli find ethereum:0xababababab20053426ad1c782de9ea8444358070:5001410 -o send-receive.json
195
141
 
196
- Use `--model claude|grok|gpt|gemini` to switch models, or set `defaultModel` in `config.json`.
142
+ # Wallet address (owner lookup); cap the number of tokens with --limit
143
+ ff-cli find 0xaeE022552B539dB18297D7481b6D547C622488B3 -l 10 -o wallet.json
197
144
 
198
- ### Natural language publishing
199
-
200
- The intent parser recognizes publishing keywords and can both display and publish in one command:
201
-
202
- ```bash
203
- # Build and publish
204
- npm run dev -- chat "Build playlist from Ethereum contract 0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0 with tokens 52932 and 52457; publish to my feed" -o playlist.json -v
205
-
206
- # Display on Art Computer AND publish to feed
207
- npm run dev -- chat "Get 3 from Unsupervised; shuffle; send to my Art Computer and publish to feed" -o playlist.json -v
145
+ # Build and publish to a configured feed server
146
+ ff-cli find https://objkt.com/tokens/hicetnunc/111068 --publish
208
147
  ```
209
148
 
210
- For Feral File built playlists, you can reference titles listed in the repository:
211
- `https://github.com/feral-file/dp1-feed/tree/main/playlists`
149
+ Sources: Art Blocks, Objkt, fxhash, OpenSea, SuperRare, Feral File, Neort, Verse, raw on-chain coordinates, and wallet addresses. Run `ff-cli find --help` for the full input list.
212
150
 
213
- Example:
151
+ ### Build from structured params
214
152
 
215
153
  ```bash
216
- npm run dev -- chat "Get 3 from Unsupervised"
154
+ ff-cli build params.json -o playlist.json
155
+ cat params.json | ff-cli build -o playlist.json
217
156
  ```
218
157
 
219
- Publishing keywords: "publish", "publish to my feed", "push to feed", "send to feed". The CLI will:
158
+ `params.json` should include `requirements` and optional `playlistSettings`. See `examples/params-example.json`. Each requirement has a `type`:
220
159
 
221
- 1. Detect the keyword and call `get_feed_servers`
222
- 2. If multiple servers → ask which one to use
223
- 3. Build → verify → publish automatically
224
- 4. Display playlist ID and server URL on success
160
+ - `build_playlist` — `blockchain`, `contractAddress`, `tokenIds`, optional `quantity`
161
+ - `feral_file_artwork` — `artworkId` (a Feral File public artwork id or `/exhibitions/artwork/{id}` URL)
162
+ - `query_address` — `ownerAddress`, optional `quantity` (random selection)
163
+ - `fetch_feed` — `playlistName`, `quantity`
225
164
 
226
- If all configured feed servers are unreachable, the CLI now reports a feed availability error instead of "playlist not found".
165
+ `playlistSettings` may set `title`, `durationPerItem`, `preserveOrder` (set `false` to shuffle), and `deviceName`. Feed playlists (for example `Unsupervised`, `Social Codes`) depend on your configured feed servers and network reachability; use exact or near-exact playlist titles for best results.
227
166
 
228
- ### Deterministic (no AI)
229
-
230
- ```bash
231
- npm run dev -- build params.json -o playlist.json
232
- cat params.json | npm run dev -- build -o playlist.json
167
+ ```json
168
+ {
169
+ "requirements": [
170
+ {
171
+ "type": "build_playlist",
172
+ "blockchain": "ethereum",
173
+ "contractAddress": "0xb932a70A57673d89f4acfFBE830E8ed7f75Fb9e0",
174
+ "tokenIds": ["52932", "52457"]
175
+ }
176
+ ],
177
+ "playlistSettings": {
178
+ "title": "My Mix",
179
+ "preserveOrder": false,
180
+ "durationPerItem": 7
181
+ }
182
+ }
233
183
  ```
234
184
 
235
- `params.json` should include `requirements` and optional `playlistSettings`. See `examples/params-example.json`.
236
-
237
185
  ### Validate, sign, and play
238
186
 
239
187
  ```bash
@@ -348,7 +296,6 @@ Setup preserves existing devices when adding new ones. See selection rules and e
348
296
 
349
297
  ## Links
350
298
 
351
- - Function calling details: `./FUNCTION_CALLING.md`
352
299
  - Examples: `./EXAMPLES.md`
353
300
  - Release assets: `./RELEASING.md`
354
301
  - DP1 spec: `https://github.com/display-protocol/dp1`
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@feralfile/cli",
3
- "version": "1.6.0",
4
- "description": "CLI for building DP-1 playlists of digital art using AI (Claude, Grok, ChatGPT, Gemini)",
3
+ "version": "2.0.1",
4
+ "description": "CLI for building, signing, and playing DP-1 playlists of digital art on Feral File devices",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git+https://github.com/feral-file/ff-cli.git"
@@ -51,7 +51,7 @@
51
51
  "nft",
52
52
  "playlist",
53
53
  "dp1",
54
- "grok",
54
+ "feralfile",
55
55
  "cli"
56
56
  ],
57
57
  "author": "",
@@ -65,7 +65,6 @@
65
65
  "dp1-js": "2.0.0",
66
66
  "ff1": "^1.0.0",
67
67
  "fuzzysort": "^3.1.0",
68
- "openai": "^4.58.1",
69
68
  "viem": "^2.38.2"
70
69
  },
71
70
  "devDependencies": {