Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion build.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ async function build() {
},
minify: !isDev,
sourcemap: isDev ? 'inline' : false,
external: [],
// Native keyring bindings cannot be inlined. npm installs resolve this
// normally; release archives copy the current platform's @napi-rs tree
// beside the bundle so Node can load the OS credential backend.
external: ['@napi-rs/keyring'],
logLevel: 'info',
// Remove shebangs from source files during bundling
loader: {
Expand Down
7 changes: 5 additions & 2 deletions config.json.example
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,16 @@
"privateKey": "YOUR_ED25519_PRIVATE_KEY__base64_PKCS8_DER_recommended__or_32byte_raw_seed_as_hex_or_base64__run_ff-cli_setup_to_generate",
"role": "agent"
},
"ff1Relayer": {
"baseUrl": "https://tv-cast-coordination.autonomy-system.workers.dev"
},
"ff1Devices": {
"devices": [
{
"name": "DISPLAY_NAME_FOR_YOUR_FF1_DEVICE",
"id": "FF1-DEVICE_ID",
"host": "http://YOUR_FF1_IP_ADDRESS:1111",
"apiKey": "YOUR_FF1_DEVICE_API_KEY_FROM_DEVICE_SETTINGS",
"topicID": "YOUR_FF1_DEVICE_TOPIC_ID_FROM_DEVICE_SETTINGS"
"apiKey": "YOUR_FF1_DEVICE_API_KEY_FROM_DEVICE_SETTINGS"
}
]
}
Expand Down
33 changes: 31 additions & 2 deletions docs/CONFIGURATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,22 +120,30 @@ Configure devices you want to play content on.

- `ff1Devices.devices` (array of objects):
- `name` (string): Friendly device label. Free‑form; pick anything memorable.
- `id` (string): Stable physical ID discovered from FF1 (for example
`FF1-SKYZ2E3A`). Relayer pairing stores the topic under this ID in the OS
credential vault.
- `host` (string): Device base URL. For LAN devices, use `http://<ip>:1111`. The device typically listens on port `1111`.

During `ff-cli setup`, the CLI will attempt local discovery via mDNS (`_ff1._tcp`). If devices are found, you can pick one and the host will be filled in automatically. If discovery returns nothing, setup falls back to manual entry.

> **mDNS is best-effort.** It frequently does not cross subnets — a common case with mesh routers (e.g. eero) that put wired and Wi-Fi clients on different `/24`s. If discovery comes up empty even though the device is reachable by IP, skip it entirely and add the device directly:
>
> ```bash
> ff-cli device add --host http://<device-ip>:1111 --name <name>
> ff-cli device add --host http://<device-ip>:1111 --name <name> --id FF1-XXXXXXXX
> ```

You can also manage devices independently with:

- `ff-cli device add` – Add a device interactively (with mDNS discovery), or non-interactively with `--host` and `--name`.
- `ff-cli device add` – Add a device interactively (with mDNS discovery), or
non-interactively with `--host`, `--name`, and the physical `--id` shown in
Feral File mobile. Manual devices need the ID before relayer pairing.
- `ff-cli device list` – Show all configured devices.
- `ff-cli device remove <name>` – Remove a device by name.
- `ff-cli device default <name>` – Promote a device to the top of the list so it is used when `-d` is omitted.
- `ff-cli device pair [name]` – Display a one-time handoff code and key-bound
security check, then securely receive that device's relayer topic from Feral
File mobile. Confirm both values match before approving in mobile.

Setup and `device add` both preserve existing devices. Adding a device with the same host as an existing one updates it in place.

Expand Down Expand Up @@ -164,6 +172,26 @@ Content-Type: application/json

The `intent` field is **required** — without it the device returns `{"message":{"ok":false}}` with no further explanation. `dp1_call` may be the playlist inline (as above) or a hosted playlist URL string; ff-cli sends the resolved playlist object.

When LAN delivery is unreachable, `play` prints an explicit notice and retries
the same command through `ff1Relayer.baseUrl`. The per-device topic is read from
the operating system credential vault, never `config.json`. Pair it from the
mobile app first:

```bash
ff-cli device pair office
```

The CLI and mobile confirmation both show the same 12-hex-digit security check.
Comparing it authenticates the CLI public key out of band, so an active broker
cannot silently substitute its own encryption key.

The default relayer is
`https://tv-cast-coordination.autonomy-system.workers.dev`. Override it with
`ff1Relayer.baseUrl` or `FF1_RELAYER_URL`. Signed topic-only relayer deployments
need no additional key. Deployments that retain the cloud-edge compatibility
gate may receive `ff1Relayer.apiKey` or `FF1_RELAYER_API_KEY`; ff-cli never
bundles that shared key.

On the first cast after boot the device may return an empty body. ff-cli retries this automatically and, if it persists, reports a clear "accepted the request but returned no usable response" error rather than crashing on a JSON parse.

Compatibility checks:
Expand Down Expand Up @@ -207,6 +235,7 @@ Minimal `config.json` example (selected fields):
"devices": [
{
"name": "Living Room Display",
"id": "FF1-ABCD1234",
"host": "http://192.168.1.100:1111"
}
]
Expand Down
6 changes: 6 additions & 0 deletions docs/PROJECT_SPEC.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ Based on the code today, the CLI is responsible for:
- signing playlists when a private key is configured
- publishing validated playlists to configured feed servers
- discovering configured FF1 devices and sending playlists or direct media playback requests
- pairing a device's signed relayer topic through a short-lived end-to-end
encrypted mobile handoff, authenticating the CLI key with a user-compared
security check, and storing it in the operating system credential vault
- falling back from unreachable LAN delivery to the shared FF1 relayer with an
explicit terminal notice, so sandboxed and cross-subnet control remains
observable to the mobile app
- performing FF1 OS compatibility preflight checks before display and SSH flows

## Architecture boundaries
Expand Down
7 changes: 4 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ Both paths run the same deterministic pipeline: fetch metadata, assemble a DP-1
- `ssh <enable|disable>` – Manage SSH access on an FF1 device
- Options: `-d, --device <name>`, `--pubkey <path>`, `--ttl <duration>`
- `device list` – List all configured FF1 devices
- `device add` – Add a new FF1 device (with mDNS discovery)
- Options: `--host <host>`, `--name <name>`
- `device add` – Add a device with mDNS or manual `--host`, `--name`, and `--id`
- Options: `--host <host>`, `--name <name>`, `--id <id>`
- `device pair [name]` – Securely receive relayer access from Feral File mobile
- `device remove <name>` – Remove a configured FF1 device
- `device default <name>` – Set the default FF1 device (used when `-d` is omitted)
- `config <init|show|validate>` – Manage configuration
Expand Down Expand Up @@ -271,7 +272,7 @@ ff-cli device list
ff-cli device add

# Add a device non-interactively
ff-cli device add --host 192.168.1.100 --name kitchen
ff-cli device add --host 192.168.1.100 --name kitchen --id FF1-XXXXXXXX

# Remove a device by name
ff-cli device remove kitchen
Expand Down
235 changes: 235 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@
"author": "",
"license": "MIT",
"dependencies": {
"@napi-rs/keyring": "1.3.0",
"@feralfile/source-resolver": "git+https://github.com/feral-file/ff-source-resolver.git#54be943014c8cf7860114510257cdd713bbf4e79",
"axios": "^1.6.2",
"bonjour-service": "^1.3.0",
Expand Down
2 changes: 2 additions & 0 deletions scripts/release/build-asset-windows.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ try {
Copy-Item (Join-Path $ROOT_DIR "dist\ff-cli.js") (Join-Path $PACKAGE_DIR "lib\ff-cli.js")
Copy-Item (Join-Path $ROOT_DIR "package.json") (Join-Path $PACKAGE_DIR "package.json")
Copy-Item (Join-Path $ROOT_DIR "LICENSE") (Join-Path $PACKAGE_DIR "LICENSE")
New-Item -ItemType Directory -Path (Join-Path $PACKAGE_DIR "lib\node_modules") -Force | Out-Null
Copy-Item -Recurse (Join-Path $ROOT_DIR "node_modules\@napi-rs") (Join-Path $PACKAGE_DIR "lib\node_modules\@napi-rs")

$ffCliCmd = @"
@echo off
Expand Down
Loading
Loading