> ## Documentation Index
> Fetch the complete documentation index at: https://docs.factrove.app/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Describe what the running code does. Do not invent hosted pricing, launch dates, or security guarantees. Share and viewer links are a configured base URL plus an artifact path. Show localhost and a placeholder origin such as https://library.example.com.

# CLI

> Commands, flags, config precedence, and how Factrove differs from aws s3.

The commands are `upload`, `list`, `get`, `share`, `rename`, `delete`, and `configure`. Run `factrove --help` for the short list, and `factrove <command> --help` for that command's flags. The generated pages reprint those help texts word for word, then list flags the help text omits.

## Install

The published npm package is `factrove`. Node.js must be at least 24.7.0 and below 25.

```bash theme={null}
npm install --global factrove
factrove --help
ftrv --help
```

`ftrv` is an alias for `factrove`. npm rejected a separate `ftrv` package, so both names are bins of `factrove`. `npx factrove` runs the same program without a global install.

With no profile and no API URL, the CLI calls `https://api.factrove.app`. A self-hosted API needs `--api-url`, `FACTROVE_API_URL`, or a profile `api_url`. [Release the CLI](https://docs.factrove.app/guides/releasing-the-cli.md) publishes a version. It does not run on push.

From a checkout of this repository, `pnpm factrove` runs the built CLI. pnpm prints the script line it runs to stderr. The program help uses the name `factrove`. `apps/cli/.env` can point that command at `http://localhost:3001`. The published commands do not read that file.

Help text uses synopsis placeholders such as `<artifact-id>`. In a shell, `<` starts a redirection. Executable examples below use quoted variables.

## Agent workflow

Plain upload prints only the artifact id on stdout. pnpm writes the script line it runs to stderr, so a substitution captures the id. Plain get prints the content bytes. Plain share prints the public URL and then a status line, so agents should use `--json` when they need one machine-readable line.

```bash theme={null}
artifact_id=$(pnpm factrove upload ./fixtures/hello.html)
pnpm factrove list --json
pnpm factrove get "$artifact_id" --format markdown > artifact.md
pnpm factrove rename "$artifact_id" --name "X launch calendar"
pnpm factrove upload ./fixtures/hello.html --artifactId "$artifact_id"
pnpm factrove share "$artifact_id" --json
pnpm factrove delete "$artifact_id" --yes
```

`--password` prompts twice and needs a terminal. `--password-stdin` reads a pipe and removes one trailing newline. Set `LINK_PASSWORD` in the environment, then:

```bash theme={null}
printf '%s' "$LINK_PASSWORD" | pnpm factrove share "$artifact_id" --password-stdin
```

```bash theme={null}
factrove upload ./hey.html
factrove upload ./hey.html --name "X launch calendar"
factrove upload ./hey.html --artifactId "$artifact_id"
factrove list --json
factrove get "$artifact_id" --format markdown
factrove share "$artifact_id" --password
factrove rename "$artifact_id" --name "X launch calendar"
factrove delete "$artifact_id" --yes
factrove configure
```

From this repository the same commands run as `pnpm factrove`. After `npm install --global factrove`, drop the `pnpm` prefix, or use `ftrv` in its place. pnpm prints the script line it runs to stderr. The program help uses the name `factrove`.

## Commands

`upload <file>` sends one HTML file and creates a new artifact. Plain success prints only the new id and a newline. `--json` prints the `{ artifact }` envelope on one line. `--access private|org_shared` chooses who can see a new artifact. The default is `private`. `org_shared` requires a current organization membership. Signup does not create one. See [Organization membership](https://docs.factrove.app/concepts.md#organization-membership).

`--name <name>` sets the name shown in the library, the viewer, and a public share. The name is one line of 1 to 120 characters. Omit `--name` and the stored name is the file name without `.html` or `.htm`. A stem that is empty, longer than 120 characters, or not one line stores null, and the upload still succeeds. Those screens then show `{artifactId}.html`. There is no flag to clear a name.

`upload <file> --artifactId <id>` replaces that artifact's content and prints the same id. The API keeps the current access, the current name, and the current share token, so an existing public link serves the new HTML. Pass `--name` with `--artifactId` to set a new name in that same replace. Omit `--name` and the current name stays, including null. `--access` together with `--artifactId` is an error. A replace writes a new object and points the artifact at it. Another replace of the same revision receives `409 CONTENT_CONFLICT` and does not change the name. A replace that returns `500` because the database acknowledgement was lost can still land the new HTML and, when `--name` was sent, the new name together. Factrove currently exposes only the current content. Replacement provides no version-history or undo interface and normally removes the previous object. A replace can rarely return `500` after the new object is already committed. GET the artifact before retrying.

`get <id>` prints the artifact's content. The default is HTML. `--format markdown` asks the API to convert the stored HTML on the way out. Markdown is not saved. The conversion does not run JavaScript and drops scripts, styles, SVG, and MathML. Limits and errors are in [Markdown conversion](https://docs.factrove.app/concepts.md#markdown-conversion). `--json` prints `{ format, mediaType, content }` on one line.

`list` prints the caller's artifacts, one per line: the id, `private` or `org_shared`, then the library name. A null name uses `{id}.html`. An empty list prints nothing. `--view org` lists organization-shared artifacts in the caller's current organization, and is an empty list when the caller has no current organization. `--json` prints the `{ items }` envelope on one line.

`share <id>` creates a public link, or prints the existing one. `--password` prompts twice on a terminal. `--password-stdin` reads a pipe and removes one trailing newline. `--remove-password` keeps the link and clears its password. `--revoke` removes the link and its password. A Factrove link is the public base origin plus `/share/{id}/{token}` and lasts until revoke. It can also carry a password.

`rename <id> --name <name>` changes the library name and leaves the stored HTML, access, and any public link in place. Quote a name that contains spaces. Plain success prints `Renamed {id}.` `--json` prints the `{ artifact }` envelope. There is no way to clear a name. Only the owner can rename. Anyone else, including an organization admin, gets `404 ARTIFACT_NOT_FOUND`.

`delete <id>` removes the artifact, its current HTML object, and any public link. A terminal asks for confirmation and continues only for `y` or `yes`. `--yes` and `--force` skip that prompt. They are the same flag. Use one of them when stdin is not a terminal, which is the usual case for an agent. Plain success prints `Deleted {id}.` `--json` prints `{"deleted":true,"id":"…"}`. The HTTP response is empty. Only the owner can delete. Anyone else, including an organization admin, gets `404 ARTIFACT_NOT_FOUND`. A storage failure keeps the artifact row. The stored HTML may already be gone, so retry the delete. If concurrent replaces prevent deletion after eight attempts, the API returns `409 CONTENT_CONFLICT`. Retry the delete. The CLI does not keep a local index such as `factrove.md`, so delete and rename change only the artifact on the server.

`configure` saves an API key and API URL for a profile. `--api-key` prompts when omitted, so the key stays out of shell history. `--api-url` sets the origin, and `--endpoint-url` is the same option. `--profile` selects the profile. The default profile name is `default`. Create the key in the web app, or with the [session recipe](https://docs.factrove.app/api-reference/overview.md#create-an-api-key-from-a-session). If configure cannot reach the API, see [Troubleshooting](https://docs.factrove.app/guides/troubleshooting.md).

## Flags

`--api-url <origin>` and `--endpoint-url <origin>` set the API origin for one command. They must be the same value when both are present. `configure` stores that origin as `api_url`.

`--json` and `--output json` print one JSON line. `--output text` is the plain output. `--json` together with `--output text` is an error in either order.

`--profile <name>` is accepted on every command. Help lists it on `configure`. An explicit `--profile` uses that profile's key and ignores `FACTROVE_API_KEY`.

`--quiet` is accepted on `upload`, `get`, `share`, `list`, `rename`, and `delete`. Help does not list it, and it does not hide their output. `configure` rejects it.

Success exits 0. Failure exits 1.

## Config precedence

The API origin is the first value that is set:

1. `--api-url` or `--endpoint-url`
2. `FACTROVE_API_URL`
3. `FACTROVE_ENDPOINT_URL`, only when `FACTROVE_API_URL` is unset
4. `api_url` in the selected profile
5. `endpoint_url` in that profile, when `api_url` is absent
6. a URL from the dev env file, only for `pnpm factrove`
7. `https://api.factrove.app`

The API key is `FACTROVE_API_KEY`, then `factrove_api_key` in the selected profile. An explicit `--profile` skips `FACTROVE_API_KEY` and uses that profile's key. The profile name is `--profile`, then `FACTROVE_PROFILE`, then `default`.

`configure` writes `~/.factrove/credentials` and `~/.factrove/config` with mode 0600. Directories Factrove creates for those files are mode 0700. `FACTROVE_CONFIG_DIR`, `FACTROVE_SHARED_CREDENTIALS_FILE`, and `FACTROVE_CONFIG_FILE` override the paths. The command does not print the key.

## Dev env file

`pnpm factrove` reads `apps/cli/.env`. `node apps/cli/dist/main.js` and the published `factrove` command do not. `FACTROVE_CLI_ENV_FILE` selects a different file, and that name comes from the process environment. The file may set `FACTROVE_API_URL` and `FACTROVE_PROFILE` when those variables are unset. It does not set an API key or `FACTROVE_ENDPOINT_URL`. A URL from the file is used only when the process environment and the selected profile have no URL. The example sets `FACTROVE_API_URL=http://localhost:3001` so `pnpm factrove` talks to a local API. Without that file, the built-in origin is `https://api.factrove.app`.

## Differences from aws s3

Factrove stores an artifact id, a human-readable name, access, a share link, and the current HTML object key with its size. HTTP responses and the CLI omit the object key. There is no etag and no caller-supplied object metadata. New objects use `{artifactId}/{contentId}.html`. Older rows keep `{artifactId}.html`. The public filename is `{artifactId}.html`. The name is a separate field.

`aws s3` commands such as `cp`, `ls`, `rm`, `mv`, `sync`, `mb`, and `rb` are not Factrove commands. Factrove uses `list`, `rename`, and `delete` for those jobs. `aws s3api` commands such as `put-object` and `get-object` take a caller-supplied object key. The CLI addresses an artifact by id and has no `s3api` surface. It uploads a local HTML file, lists artifacts, and prints or downloads one artifact. It does not copy between two remote locations, and it does not read an upload from stdin.

`share` is the public-link command. An `aws s3 presign` URL is a temporary signed GET and has no password. A Factrove share lasts until `--revoke` and can take a password. The password flags stay on `share`.

`--endpoint-url` is the API origin, the same option as `--api-url`. It is not an S3 endpoint. The API's `S3_ENDPOINT` is server configuration and is not a CLI flag.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.