@marro-sh/cli
v0.2.0
Published
The marro command line client: give a project one permanent URL that people read and agents fetch.
Maintainers
Readme
marro
marro is the command line client for marro.sh, a tiny
remote filesystem for project context. One permanent URL gives a person a
readable page and gives an agent the file itself.
npm install -g @marro-sh/cliThe command is marro. Node 20 or newer.
Start
marro login --remote # pair this machine in a browser, once
marro new acme --remote # a project, and its permanent address
marro write acme/context.md -m "# Acme" --remote
marro ls acme --remote--remote talks to marro.sh. Without it the CLI runs against a local preview
store in ~/.marro/preview.json, so you can learn the surface before you have
an account. MARRO_REMOTE=1 makes remote the default for a shell.
The commands
marro login sign in on this machine
marro logout sign out, and forget the session
marro status the whole record
marro new <project> create a project and use it
marro use [project] choose the project other commands act on
marro ls [path] the shape of a project
marro read <path> print a file
marro write <path> replace a file, or create one
marro append <path> add to the end of a file
marro rm <path> delete a file, or a folder with -r
marro mkdir <path> create a folder
marro upload <local> <remote> put a local file into a project
marro download <remote> [local] pull a file onto this machineA path can be a bare name, a project-qualified path, or a full URL pasted
straight in: context.md, acme/context.md and
https://marro.sh/acme/context.md all resolve to the same file.
For agents and scripts
Pass --json and the CLI stops being a screen. It prints exactly one JSON
document on stdout, with no colour, no box drawing and no prompts.
marro ls acme --remote --json{"ok":true,"project":"acme","path":"acme","kind":"dir","entries":[{"name":"context.md","kind":"file","bytes":58,"updated":"2026-08-29T22:59:08.954Z"}],"files":1,"bytes":58}Every document carries ok, so success and failure are told apart without
inspecting the shape:
{"ok":false,"error":{"summary":"marro is a context host, not a hard drive","detail":["A .mp4 file is not project context, so it has no home here."]}}The rules that make it safe to automate:
- Failures print to stdout too, as
ok: false, so a caller that captures only stdout still gets the reason. The exit code is still non-zero. - Nothing ever blocks on a prompt. A command that would ask a question fails immediately and says which flag answers it.
- Destructive actions need
-y.rm, andwriteover an existing file, refuse without it rather than assuming consent. marro readwithout--jsonwrites the raw bytes and nothing else, so it pipes cleanly. With--jsonyou get the content plus its metadata.
Authenticate headlessly with MARRO_TOKEN, a device token minted at
marro.sh/devices/new. It is read from the environment and never written to
disk:
MARRO_TOKEN=mr_… marro status --remote --jsonEnvironment
| Variable | Meaning |
|---|---|
| MARRO_TOKEN | Device token. Used for this process only, never stored. |
| MARRO_REMOTE | 1 makes --remote the default. |
| MARRO_API_URL | Point the client at another origin, for local or staging work. |
| MARRO_HOME | Where the local record lives. Defaults to ~/.marro. |
| NO_COLOR | Honoured. So is a dumb terminal and a non-UTF-8 locale. |
What belongs here
marro is a context host, not a hard drive: Markdown, text, JSON, YAML, CSV, TOML and small images, up to 5 MB a file. It refuses anything else, in those words.
Licence
MIT. See LICENSE.
