superseedr 1.0.5

A BitTorrent Client in your Terminal.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
# Shared Config Cluster Mode

## What It Is

Shared config mode lets multiple Superseedr nodes participate in one cluster by
pointing them at the same mounted shared root.

- Every node is a full Superseedr client.
- Every node can run torrents and seed.
- One node is the leader at any given time.
- The leader is the only node that consumes the shared inbox and writes
  cluster-wide desired state.
- Non-leader nodes follow shared desired state and apply it locally.

Shared mode is enabled from the first available source in this order:

1. `SUPERSEEDR_SHARED_CONFIG_DIR`
2. persisted launcher shared-config sidecar
3. normal standalone mode

Host id is resolved from:

1. `SUPERSEEDR_SHARED_HOST_ID`
2. persisted launcher host-id sidecar
3. sanitized hostname fallback

This is mainly useful when:

- multiple machines share the same NAS or mounted volume
- installed browser or OS protocol launches do not inherit shell environment
- you want one shared torrent catalog with automatic leader failover

## Before You Start

Shared mode depends on a real writable shared root.

Before starting any node:

1. Create a dedicated shared folder on the mounted volume.
2. Mount that shared folder on every host.
3. Confirm every host can read and write inside it.
4. Start each client once so it can create its host-local shared files.

Use a dedicated folder inside the mounted volume, not the entire volume root.

Examples:

- Windows: `C:\Users\jagat\Documents\seedbox\test`
- macOS: `/Volumes/seedbox/test`
- Linux: `/mnt/shared-drive/test`

If the shared root is missing, unmounted, or not writable, runtime startup will
fail with a shared-root accessibility error.

## Quick Start

### 1. Pick a Shared Root

Choose one dedicated shared folder per cluster.

Example:

```text
/mnt/shared-drive/test
```

Superseedr stores its cluster files under:

```text
/mnt/shared-drive/test/superseedr-config/
```

Payload data still lives under the shared root itself, not under
`superseedr-config/`.

### 2. Configure Each Host

You can use environment variables:

```bash
export SUPERSEEDR_SHARED_CONFIG_DIR=/mnt/shared-drive/test
superseedr
```

Or persist launcher-side setup once per user account:

```bash
superseedr set-shared-config /mnt/shared-drive/test
superseedr show-shared-config
```

Then start the client normally:

```bash
superseedr
```

Repeat on every host with the same shared root.

### 3. Confirm the Cluster

After startup:

- one node should become leader
- other nodes should run as followers
- each host should have a `hosts/<host-id>/` folder under the shared config root

Useful checks:

```bash
superseedr show-shared-config
superseedr status
superseedr journal
superseedr torrents
```

### 4. Use the Cluster

Once running, use the CLI normally:

```bash
superseedr add /path/to/file.torrent
superseedr pause <INFO_HASH_HEX_OR_PATH>
superseedr resume <INFO_HASH_HEX_OR_PATH>
superseedr remove <INFO_HASH_HEX_OR_PATH>
superseedr purge <INFO_HASH_HEX_OR_PATH>
```

## Environment Variables

### `SUPERSEEDR_SHARED_CONFIG_DIR`

Absolute path to the shared mount root.

Superseedr automatically uses:

```text
<mount-root>/superseedr-config/
```

Example:

```bash
SUPERSEEDR_SHARED_CONFIG_DIR=/mnt/shared-drive/test
```

This has the highest precedence and overrides any persisted launcher config.

### `SUPERSEEDR_SHARED_HOST_ID`

Optional explicit host id for selecting:

```text
hosts/<host-id>/config.toml
```

If unset, Superseedr falls back to a sanitized hostname.

`SUPERSEEDR_HOST_ID` is still accepted as a legacy fallback, but
`SUPERSEEDR_SHARED_HOST_ID` is the canonical name.

Example:

```bash
SUPERSEEDR_SHARED_HOST_ID=seedbox-a
```

## Launcher Commands

These commands persist launcher-side shared mode without editing runtime
`settings.toml`:

```bash
superseedr set-shared-config /mnt/shared-drive/test
superseedr show-shared-config
superseedr clear-shared-config

superseedr set-host-id seedbox-a
superseedr show-host-id
superseedr clear-host-id
```

Rules:

- `set-shared-config` requires an absolute path
- the path may be either the mount root or an explicit `.../superseedr-config`
- Superseedr normalizes and stores the mount root in a launcher sidecar file
- `set-host-id` stores a sanitized host id in a separate launcher sidecar file
- `show-shared-config` reports the effective source and resolved paths
- `show-host-id` reports the effective host id and its source
- `clear-shared-config` disables persisted shared mode unless the env var is set
- `clear-host-id` removes the persisted host id unless the env var is set

## Conversion Commands

You can convert between standalone local config and layered shared config:

```bash
superseedr to-shared /mnt/shared-drive/test
superseedr to-standalone
```

Behavior:

- `to-shared` reads current standalone local config and writes layered shared files
- `to-standalone` reads the currently selected shared config and writes local standalone files
- neither command modifies launcher sidecars by itself

## Shared Root Layout

```text
/mnt/shared-drive/test/
  superseedr-config/
    settings.toml
    catalog.toml
    torrent_metadata.toml
    cluster.revision
    hosts/
      seedbox-a/
        config.toml
        logs/
        persistence/
        status.json
      desktop-a/
        config.toml
        logs/
        persistence/
        status.json
    torrents/
    inbox/
    processed/
    staged-adds/
    status/
      leader.json
    superseedr.lock
  downloads/
  library/
```

Different hosts may mount the same shared root at different local paths.

Examples:

- Windows: `C:\Users\jagat\Documents\seedbox\test`
- macOS: `/Volumes/seedbox/test`
- Linux: `/mnt/shared-drive/test`

Each host should point `SUPERSEEDR_SHARED_CONFIG_DIR` or `set-shared-config` at
its own local mount path for the same shared root.

## Layered Files

### `settings.toml`

Cluster-wide shared settings.

Examples:

- shared `client_id` default
- RSS settings
- shared UI and performance settings
- shared default download folder

### `catalog.toml`

Cluster-wide desired torrent state.

Examples:

- torrent list
- pause and resume state
- remove and purge intent
- per-torrent download path
- per-torrent file priorities

All nodes read this file and converge local runtime to it.

### `torrent_metadata.toml`

Leader-written derived torrent metadata, including persisted file lists used by
commands like `files`, `info`, reverse path lookup, and offline purge.

### `hosts/<host-id>/config.toml`

Host-local runtime settings on the shared root.

This file is bootstrapped by runtime startup if it does not exist yet.
CLI shared loads also bootstrap this host file when shared cluster settings
already exist.

Common host-local fields:

- optional `client_id`
- `client_port`
- `watch_folder`

### `hosts/<host-id>/`

Host-local runtime artifacts on the shared root.

Examples:

- `hosts/<host-id>/logs/`
- `hosts/<host-id>/persistence/network_history.bin`
- `hosts/<host-id>/persistence/activity_history.bin`
- `hosts/<host-id>/persistence/rss.toml`
- `hosts/<host-id>/persistence/event_journal.toml`
- `hosts/<host-id>/status.json`

## Leadership

Shared mode still uses the file-lock mechanism.

- Leader: holds `superseedr.lock`
- Follower: does not hold the lock
- If a follower later acquires the lock, it promotes itself to leader without a restart

Leader responsibilities:

- consume `inbox/`
- write shared desired state
- write `settings.toml`, `catalog.toml`, and `torrent_metadata.toml`
- write `cluster.revision`
- update the current leader snapshot

Followers remain active torrent clients. They do not stop running torrents just
because they are not the leader.

## Cluster Convergence

The leader writes `cluster.revision` after shared desired-state changes.

Host-only changes do not bump `cluster.revision`.

Followers:

- watch shared state
- reload layered config when `cluster.revision` changes
- converge local runtime to the shared catalog

Convergence includes:

- starting newly added torrents
- pausing or resuming torrents
- applying file-priority changes
- applying download-path changes
- removing torrents deleted from shared desired state

### Remove vs Purge

`remove` and `purge` are cluster-wide.

- `remove` removes the torrent from desired state but keeps payload data
- `purge` removes the torrent and deletes payload data

## Watch Folder Model

Each host can still define its own local ingress folder:

```toml
client_port = 6681
watch_folder = "/srv/local-watch"
```

Behavior:

- leader watches its own local `watch_folder`
- leader also watches `inbox/`
- followers watch their own local `watch_folder`
- followers relay supported files into `inbox/`
- followers do not write shared desired state directly from local watch ingress

Supported dropped file types:

- `.torrent`
- `.magnet`
- `.path`
- `.control`

### Cross-Host Add Rules

This is the most important ingest rule in a multi-host cluster:

- magnet adds are naturally portable
- `.torrent` adds work across hosts when the torrent file is staged onto the shared root
- shared-mode `.path` adds are encoded relative to the shared root and resolved by the leader against its own local mount path

In practice:

- if you add a `.torrent` from a follower watch folder, Superseedr may stage it into `staged-adds/`
- if you add a path-based torrent source in shared mode, the follower resolves it and stages the actual torrent file for the leader

## Data Path Rules

Shared mode requires all payload data to live under the shared root.

Rules:

- shared-mode download paths must resolve inside the shared root
- shared-mode download paths are stored root-relative in layered config
- host-specific path translation is not supported

Examples:

- `default_download_folder = ""` resolves to the shared mount root itself
- `default_download_folder = "downloads"` resolves to `<mount-root>/downloads`

Example shared catalog entry:

```toml
[[torrents]]
name = "Shared Collection"
download_path = "library/shared-collection"
```

## CLI Behavior in Shared Mode

### Read Commands

Commands like these read shared state:

- `status`
- `journal`
- `torrents`
- `info`
- `files`

`status` in shared mode follows the current leader snapshot rather than a purely
local standalone-style node status view.

### Mutating Commands

Mutating commands include:

- `add`
- `pause`
- `resume`
- `remove`
- `purge`
- `priority`

Behavior:

- if a leader is running, shared mutating commands are queued through `inbox/`
- if no leader is running, offline-capable CLI commands mutate shared config directly using the offline path

That means shared CLI is not queue-only in all cases.

### `stop-client`

`stop-client` in shared mode targets the leader through the shared inbox.

Use it as a cluster-leader stop request, not a guaranteed “stop only this local
follower process” command.

## First-Run and Bootstrap Behavior

Runtime startup bootstraps shared host state.

CLI bootstrap behavior is intentionally narrower:

- in standalone mode, CLI can create first-run local settings when no local client is running
- in shared mode, CLI does not create an entirely new cluster from nothing
- in shared mode, if shared cluster settings already exist, CLI can bootstrap the current host's missing `hosts/<host-id>/config.toml`

Practical implications:

- start the client once on one host to establish the shared cluster files
- start the client once on each additional host if you want all host runtime folders to exist immediately
- if the shared root exists but shared `settings.toml` does not, CLI reports that the client has never started yet instead of silently creating a new cluster

## Status and Journal Semantics

### Status

Shared `status` is cluster-oriented and follows the leader snapshot. During
manual failover or failback, brief lag is expected while watches and snapshots
catch up.

### Journal

Shared journal output is merged:

- host-specific health/runtime events remain host-scoped
- shared command events are shared-scoped

This gives one combined operational view while preserving the difference between
host-local health and cluster-wide actions.

## Troubleshooting

### The shared root is missing or unmounted

Make sure:

- the mount exists on this host
- `SUPERSEEDR_SHARED_CONFIG_DIR` points to the mounted shared root
- the process can read and write that location

### A host cannot start in shared mode

Check:

- unique host id
- write access to `hosts/<host-id>/`
- write access to `hosts/<host-id>/config.toml`
- write access to `hosts/<host-id>/logs/`

### A cross-host add fails

Prefer:

- magnets
- `.torrent` files staged onto the shared root

Avoid relying on host-local absolute paths being valid on another OS.

## Example

Shared root:

```text
/srv/shared-drive/test/
  superseedr-config/
    settings.toml
    catalog.toml
    torrent_metadata.toml
    cluster.revision
    hosts/
      seedbox-a/
        config.toml
        logs/
        persistence/
        status.json
      desktop-a/
        config.toml
        logs/
        persistence/
        status.json
    inbox/
    processed/
    staged-adds/
    status/
      leader.json
    superseedr.lock
  downloads/
```

Shared settings:

```toml
# settings.toml
client_id = "shared-node"
default_download_folder = "downloads"
global_upload_limit_bps = 8000000
```

Shared catalog:

```toml
# catalog.toml
[[torrents]]
name = "Shared Collection"
torrent_or_magnet = "shared:torrents/0123456789abcdef0123456789abcdef01234567.torrent"
download_path = "downloads/shared-collection"
```

Host config:

```toml
# hosts/seedbox-a/config.toml
client_port = 6681
watch_folder = "/srv/local-watch"
```

## Summary

- Shared mode is opt-in.
- Environment configuration overrides persisted launcher configuration.
- The leader is the single writer for cluster-wide desired state.
- Followers are still active torrent clients.
- Shared mode supports failover and failback.
- Shared payload data must live under the shared root.
- Shared CLI reads cluster state and queues leader mutations when a leader is available.