Documentation · macOS 15+
Filecrow CLI
filecrow is a macOS 15+ command-line sender using the same delivery API,
ZIP64 STORED archive, multipart transport, CRC32/SHA-256 entry metadata, and
server size/ready checks as the Mac app. It ships inside the Filecrow Mac app.
It uploads one archive; it never uploads originals separately. Its credential
and recovery directories belong to the CLI.
Installation
The CLI is included in the Filecrow Mac app, version 0.3.7 and later. There is nothing separate to download, and it updates with the app. It requires macOS 15 or later and lives at:
/Applications/filecrow.app/Contents/Helpers/filecrowIf the app was moved, the path is the app's location followed by
Contents/Helpers/filecrow. Contents/MacOS/filecrow is the app itself, not
the CLI. There is no separate CLI download or Homebrew formula; do not use a
guessed brew command or download URL.
No app yet? Filecrow is invitation-only: open the link in your invitation, or
https://filecrow.com/install if you already have an account. Is the app older
than 0.3.7, with no Contents/Helpers/filecrow? Choose
filecrow › Check for Updates… in the menu bar and click Install Update.
Typing filecrow in Terminal
Optional. Link the bundled CLI into a folder on your PATH. A link rather than a copy, so it keeps pointing at the current version after every app update:
mkdir -p "$HOME/.local/bin"
ln -sf /Applications/filecrow.app/Contents/Helpers/filecrow "$HOME/.local/bin/filecrow"
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.zshrc
source ~/.zshrc
filecrow --versionThe last line prints the CLI version. If it prints command not found, check
that /Applications/filecrow.app/Contents/Helpers/filecrow exists; if it does
not, update the app as described above.
First transfer
filecrow login --email you@example.com
# Open the Filecrow email and confirm sign-in in any browser.
filecrow send ./folderA successful send prints the server-issued recipient URL. It reports success only after archive completion and the production ready checks pass.
filecrow send ./folder --json --no-interactive
filecrow send ./folder --quiet
filecrow send ./folder --title 'Client finals' --from 'Studio' --expires 7
filecrow send ./folder --password
filecrow send ./folder --password-file /path/to/private-password.txt --json--password requires a terminal and hides input. A password file must be a
regular file with no group/other permissions (chmod 600). --password-file -
reads stdin. One trailing newline is removed. Passwords are never saved in
transfer metadata, passed as command-line values, or printed.
Commands
filecrow login [--email ADDRESS]
filecrow logout
filecrow whoami
filecrow send <path...> [--title TEXT] [--from TEXT] [--expires DAYS]
[--password | --password-file PATH] [--new]
filecrow send --resume ID
filecrow deliveries [--limit 1..100] [--cursor CURSOR]
filecrow delivery ID
filecrow delete ID [--yes]| Command | Purpose |
|---|---|
login |
Sign in through emailed browser confirmation |
logout |
Revoke this CLI session and remove its credential |
whoami |
Show the current account and allowance |
send |
Send one ZIP64 STORED delivery or resume a draft |
deliveries |
List deliveries with cursor pagination |
delivery |
Inspect a delivery and its file manifest |
delete |
Delete a delivery and disable its recipient link |
All commands accept --json, --quiet, and --no-interactive. --json implies
noninteractive operation. Use --help on any command for its options.
Authentication and confirmation
filecrow login --email ADDRESS requests a magic-link email and waits for
approval until the server challenge deadline. Open the email's link and confirm
sign-in in a browser; approval can happen on another computer. --no-interactive
disables terminal prompts, but it does not bypass email approval. A login with
--email --json --no-interactive can still wait for that human action.
Credentials use the CLI's own macOS Keychain item, separate from the Mac app's,
so signing in to the app does not sign in the CLI. Each Mac needs one CLI sign-in;
after that it stays signed in until logout or the session expires.
An agent does not need to check the sign-in before sending: send itself
reports authentication_required (exit 3) when the CLI is not signed in.
whoami --json --no-interactive shows the account when that is what you want
to know. When a command reports authentication_required:
- Ask the person which email address their Filecrow account uses, and tell them: "A Filecrow email is on its way. Open it and click Confirm."
- Run
filecrow login --email ADDRESS --json --no-interactive. It waits until they confirm, for up to 15 minutes; run it in the background if your tool has a shorter time limit. - Run the original command again. If macOS showed a Keychain dialog, the person should click Always Allow.
If you cannot run a waiting command at all, ask the person to run
filecrow login --email ADDRESS in Terminal instead. Never request an account
token, reuse the Mac app's credential, or repeatedly retry an unauthenticated
send. A refused sign-in may also require account access; report the returned
error to the person.
delete prompts for y in an interactive terminal. In JSON or noninteractive
mode it requires --yes; without confirmation it returns confirmation_required
and exit 9. Inspect the intended delivery and obtain the human's authorization
before an agent runs delete ID --yes. No active upload is deleted on interruption.
logout revokes the CLI session server-side before removing it locally. If the
network cannot acknowledge revocation, the credential is retained and the command
fails so logout can be retried.
File selection
Directories contribute their contents without their top directory. Individual
files contribute their basename; multiple roots merge into the same archive.
Paths are NFC normalized and sorted deterministically. Duplicate archive paths,
symlinks, special files, unreadable files, and invalid paths are refused. Dotfiles
and dot directories inside a traversed directory are omitted; an explicitly
selected hidden regular file is included. Empty directories are omitted. Use
-- before filenames beginning with a dash.
Output for scripts and agents
Stdout carries one final result. Progress and human diagnostics use stderr. Animation appears only on a terminal, never in JSON or quiet mode. Progress counts bytes acknowledged by the server and uses the shared network speed tracker; source reads do not become confirmed upload progress.
With --json --no-interactive, stdout contains exactly one newline-terminated
JSON object on success or failure. Parse stdout and check the process exit status
and ok; do not parse human text or progress. send --quiet prints only the URL
on success. Other human commands print a readable result. Help and version are
plain text even with --json.
If a process is killed or stdout breaks, a complete envelope may be absent. Treat missing/truncated JSON as a failed command and inspect or resume the transfer; never infer successful delivery from partial output.
Success envelope (formatted here for readability):
{
"schema_version": 1,
"command": "send",
"ok": true,
"data": {
"delivery_id": "11111111-1111-4111-8111-111111111111",
"status": "ready",
"public_url": "https://files.filecrow.com/d/<recipient-token>",
"file_count": 147,
"source_bytes": 18400000000,
"archive_bytes": 18400025000,
"expires_at": "2026-10-09T00:00:00Z",
"resumed": false
}
}Error envelope (missing authentication example):
{
"schema_version": 1,
"command": "send",
"ok": false,
"error": {
"code": "authentication_required",
"message": "Run filecrow login first.",
"retryable": false,
"resumable": false
}
}Failures use the same envelope with ok:false and error instead of data.
An error contains code, message, retryable, and resumable. Where available,
it adds delivery_id, resume_deadline, backend_code, request_id, and
details. No raw session token or password is returned. IDs are UUIDs. Byte
counts are integers; send expiry/deadline strings are UTC ISO 8601. Account and
history/detail timestamps preserve the API's Unix seconds. Unknown additive
fields must be ignored by consumers. schema_version changes for breaking output
changes. The example recipient token above is a placeholder, not a live link.
Stable exit codes
| Exit | Meaning |
|---|---|
| 0 | Success |
| 1 | Internal/unclassified API failure |
| 2 | Arguments or selection |
| 3 | Authentication or credential storage |
| 4 | Entitlement, quota, expiry ceiling, or sending disabled |
| 5 | Network failure or uncertain creation |
| 6 | Changed source, ambiguous/conflicting resume, expired draft |
| 7 | Recovery state or competing process |
| 8 | Archive verification failure |
| 9 | Destructive confirmation missing |
| 130 / 143 | SIGINT / SIGTERM |
Recovery
Rerun the same send ./folder after a crash or a network failure. A single matching
unfinished CLI transfer resumes automatically. The complete file plan must still
match: path, size, and modification time. A partially sent entry is re-appended
whole through the existing archive checkpoint machinery. No partial-file hash
state or alternate journal format is introduced.
Use send --resume ID when several transfers match. Resume uses saved paths and
delivery options; it accepts no new selection/options. Omit password options when
resuming; the original password is already set on the delivery. --new deliberately starts
a new delivery and preserves prior drafts. Use delete ID --yes to delete a draft
and its local recovery state after server acknowledgement. Keep the resume
deadline in error output: the multipart upload cannot be continued after it lapses.
A missing/truncated spool or changed source fails closed.
Creation is not automatically retried. A lost creation response leaves a marker
and returns creation_outcome_unknown; inspect deliveries before using --new.
This avoids silently creating more charged deliveries. It does not add server
creation idempotency.
After sealing, CLI metadata preserves the manifest, expected size, and recipient URL until commit/complete/ready and output succeed. Recovery reuses those existing idempotent endpoints. If the server is already ready it returns the original URL. An output failure retains the result for a later retry. The existing Mac app's checkpoint cleanup remains unchanged.
Configuration and security
The default API/account/auth origin is https://filecrow.com. Recipient links
come from the server, normally https://files.filecrow.com; the CLI never creates
one from the API origin. FILECROW_API_ORIGIN can select another HTTPS origin
(loopback HTTP is allowed for development). Credentials and state are namespaced
by that origin.
FILECROW_STATE_DIR overrides the default
~/Library/Application Support/FilecrowCLI. Recovery directories are private
(0700); CLI metadata and locks are 0600. Do not share or commit them: they contain
source paths and recipient capabilities. Passwords and sessions are not stored
there. The Keychain service is com.filecrow.cli; it never borrows the app's
session. Only an intentional interactive login allows credential UI. Unattended
credential access fails promptly if permission/unlocking is required.
From and expiry default to the account's settings. No configuration file or production environment-token fallback is provided. An agent uses an already signed-in CLI without receiving an account secret.
Scope
The V1 integrity gate is the current production delivery contract. CRC64/NVME full-object verification, server creation idempotency, and broader checkpoint or publication hardening belong to separate Filecrow reliability work. Watched folders, MCP, Linux, teams, and a new recovery journal are outside V1.
FilecrowCore exposes login, account/history/detail/delete, send, and output
acknowledgement without terminal dependencies. A future MCP adapter can call this
boundary with its own credential/progress adapters and confirmation policy. It
would reuse the same transfer implementation.