@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.
- package/README.md +6 -11
- package/config.json.example +0 -65
- package/dist/index.js +1 -3
- package/dist/package.json +3 -4
- package/dist/src/commands/config.js +15 -13
- package/dist/src/commands/play.js +63 -0
- package/dist/src/commands/setup.js +1 -73
- package/dist/src/commands/status.js +0 -13
- package/dist/src/config.js +3 -126
- package/dist/src/main.js +2 -361
- package/dist/src/utilities/ff1-device.js +55 -0
- package/dist/src/utilities/playlist-builder.js +79 -17
- package/docs/CONFIGURATION.md +1 -35
- package/docs/EXAMPLES.md +206 -215
- package/docs/PROJECT_SPEC.md +20 -18
- package/docs/README.md +51 -104
- package/package.json +3 -4
- package/dist/src/ai-orchestrator/index.js +0 -1040
- package/dist/src/ai-orchestrator/registry.js +0 -96
- package/dist/src/commands/chat.js +0 -189
- package/dist/src/intent-parser/index.js +0 -1393
- package/dist/src/intent-parser/utils.js +0 -116
- package/docs/FUNCTION_CALLING.md +0 -100
package/docs/PROJECT_SPEC.md
CHANGED
|
@@ -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
|
|
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
|
|
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
|
-
-
|
|
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
|
-
-
|
|
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
|
-
-
|
|
104
|
-
-
|
|
105
|
-
- supporting a deterministic
|
|
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
|
-
-
|
|
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
|
-
-
|
|
136
|
-
- Trust-sensitive correctness must stay vendor-neutral and portable
|
|
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
|
|
151
|
+
### Build
|
|
150
152
|
|
|
151
|
-
- `
|
|
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
|
|
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
|
-
-
|
|
174
|
-
- utilities perform the real
|
|
175
|
-
- invalid or malformed outputs
|
|
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
|
-
|
|
220
|
-
|
|
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
|
-
|
|
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
|
-
#
|
|
96
|
-
ff-cli
|
|
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
|
-
#
|
|
99
|
-
ff-cli
|
|
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
|
-
#
|
|
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
|
|
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 --
|
|
88
|
+
npm run dev -- find https://objkt.com/tokens/hicetnunc/111068 --play
|
|
116
89
|
```
|
|
117
90
|
|
|
118
|
-
##
|
|
119
|
-
|
|
120
|
-
The model orchestrates; deterministic tools keep us honest and DP1‑conformant.
|
|
91
|
+
## Two ways to build a playlist
|
|
121
92
|
|
|
122
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
-
###
|
|
128
|
+
### Find an artwork
|
|
168
129
|
|
|
169
|
-
|
|
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
|
-
#
|
|
186
|
-
|
|
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
|
-
|
|
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
|
-
|
|
192
|
-
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
151
|
+
### Build from structured params
|
|
214
152
|
|
|
215
153
|
```bash
|
|
216
|
-
|
|
154
|
+
ff-cli build params.json -o playlist.json
|
|
155
|
+
cat params.json | ff-cli build -o playlist.json
|
|
217
156
|
```
|
|
218
157
|
|
|
219
|
-
|
|
158
|
+
`params.json` should include `requirements` and optional `playlistSettings`. See `examples/params-example.json`. Each requirement has a `type`:
|
|
220
159
|
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
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
|
-
|
|
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
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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": "
|
|
4
|
-
"description": "CLI for building DP-1 playlists of digital art
|
|
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
|
-
"
|
|
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": {
|