Usage
Portal is easiest to understand if you stop thinking of it as a giant command tree and start thinking in flows. Most real usage falls into one of three buckets:
- prepare a receiver
- send to that receiver
- inspect or adjust the environment afterward
The shortest successful transfer
On the receiving machine:
portal receiveOn the sending machine:
portal send --to <username> path/to/fileThat is the baseline workflow Portal is optimized around.
Discovery mode vs direct IP mode
Discovery mode
Use discovery mode when both devices are on the same network and you want the safer default path.
portal receive
portal send --to <username> path/to/fileWhat the code actually does in this mode:
- it listens for multicast beacons on
224.0.0.123:5005 - it waits up to 30 seconds for the named receiver to appear
- it connects over TCP only after discovery succeeds
- it verifies the receiver’s node ID before the payload starts moving
Why this is the recommended mode:
- it is simpler when you do not want to manually manage addresses
- it supports identity confirmation during the flow
- it matches the product’s local-first design best
Direct IP mode
Use direct IP mode when you already know the exact destination and want to bypass discovery.
portal send --address <IP_ADDRESS> --port <PORT> path/to/fileThis is useful in controlled environments, but you give up the identity verification that discovery mode provides. The sender code connects directly and explicitly prints that the identity check was skipped.
Optional transfer descriptions
The sender can attach a note to a transfer. The CLI asks whether you want to add one after the TCP connection is established.
Why that matters:
- the receiver sees the note when the manifest arrives
- the description is stored in history
- it gives real context when reviewing older transfers later
Sending folders
Recursive sending is built in:
portal send -r path/to/folderWithout -r, the sender rejects directories instead of silently skipping them. That is a good default because it makes mistakes obvious.
Compression control
Portal can skip gzip compression for transfer payloads:
portal send --no-compress path/to/fileUse that when your files are already compressed or CPU is the bottleneck instead of network throughput.
Receiver-side behavior
The receiver command is intentionally simple, but there are still a few behaviors worth knowing.
Receive into a specific directory:
portal receive --dir /path/to/saveListen on a custom port:
portal receive --port 7878If you do not pass --dir, the receiver resolves the target directory in this order:
- use the CLI
--dirvalue if present - otherwise use
storage.download_dirfrom config if it exists - otherwise prompt you for a folder, defaulting to your home
Downloadspath
That means receive can still work even when your storage config is incomplete, but it will become interactive.
History is part of the workflow, not an afterthought
Portal keeps transfer history locally in ~/.portal/history.jsonl, and the records are more detailed than the old docs implied.
Each record can include:
- transfer mode (
sendorreceive) - success or failure state
- peer address and peer username
- intended item counts and byte totals
- actual item counts and byte totals
- transfer description
- receiver save path on receive operations
- an error string when something failed
List recent history:
portal historyInspect one record:
portal history 3Emit JSON:
portal history --jsonClear all records:
portal history clearDelete one record:
portal history delete 3Export records:
portal history export --output portal_history.json
portal history export --detailed --output portal_history.jsonFiltering history
The CLI already supports enough filtering to make history useful in practice.
Filter by transfer mode:
portal history --mode send
portal history --mode receiveFilter by date:
portal history --since 2026-03-16Limit the number of results:
portal history --limit 20Updating Portal
portal updateWhat that command actually does depends on your platform:
- Windows downloads and launches the MSI installer.
- Linux, macOS, and Android download the release archive for the current target and replace the binary in place.
- Portal asks for confirmation before applying the update.
Config commands you will actually use
Interactive onboarding:
portal config setupChange one key:
portal config set <key> <value>Read one key:
portal config show <key>List everything:
portal config listA useful nuance from the code: portal config set can bootstrap a new config file even if you never ran setup first. Setup is the friendlier onboarding path, but config set is still a valid low-level entry point.
Practical mental model
If you are teaching someone else to use Portal, the right order is:
- run setup once
- learn
receive - learn
send --to - use direct IP only when needed
- use history when a transfer needs verification or debugging