Skip to content

Files

A script can take files and hand files back. A bank statement goes in and an OFX file comes out. A CSV goes in and a cleaned CSV and a summary come out. The script reads and writes ordinary files on disk, so it works the way it does on your laptop.

In reminix.json, give the input "format": "file". Add "contentMediaType" when only one type makes sense:

{
"slug": "convert-statement",
"name": "Convert a bank statement",
"command": "python convert.py --account {account} {statement}",
"inputSchema": {
"type": "object",
"required": ["account", "statement"],
"properties": {
"account": { "type": "string" },
"statement": {
"type": "string",
"format": "file",
"contentMediaType": "application/pdf"
}
}
}
}

For several files in one input, use a list: { "type": "array", "items": { "type": "string", "format": "file" } }.

Put a small sample in your script’s folder and name it in the input’s examples, as a path inside the folder:

"statement": {
"type": "string",
"format": "file",
"contentMediaType": "text/csv",
"examples": ["samples/statement.csv"]
}

The run form then offers Use the sample file next to the file picker, so anyone can try the script without a file of their own. Publishing checks the sample is in the folder and refuses the version if it isn’t. Reminix offers only the files you name this way; the rest of your folder stays private. A sample can be up to 5 MB.

Reminix copies each file to /inputs/<input>/<file name> before the command starts, and puts its path where the command names the input. With the manifest above and a file called september.pdf, Reminix runs:

Terminal window
python convert.py --account acme /inputs/statement/september.pdf

The path is also in the environment ($REMINIX_INPUT_STATEMENT), and the JSON inputs give the file’s details:

{
"account": "acme",
"statement": {
"path": "/inputs/statement/september.pdf",
"name": "september.pdf",
"type": "application/pdf",
"size": 48213
}
}

A list of files becomes several arguments in the command, and a list of paths in the environment.

Reminix saves anything your script writes to /outputs (also $REMINIX_OUTPUTS) when the command ends, whether the run succeeded or failed. A folder inside /outputs becomes part of the file’s name, like reports/summary.csv.

import json, os, subprocess, sys
pdf = sys.argv[3]
text = subprocess.run(
["pdftotext", pdf, "-"], capture_output=True, text=True, check=True
).stdout
with open(os.path.join(os.environ["REMINIX_OUTPUTS"], "statement.txt"), "w") as f:
f.write(text)
print(json.dumps({"lines": len(text.splitlines())}))

Standard output is still the run’s result. Write large results to /outputs rather than printing them: Reminix keeps at most 1 MB of standard output.

On the script’s page, a file input is a file picker. Pick the file, or select Use the sample file when the script ships one, then select Run: the app uploads it, then starts the run. The run’s page lists the files it was given and the files it wrote, each as a download.

Files, beside Scripts and Runs in the app, lists what runs wrote, newest first: each file’s name, its script, when its run wrote it and who started that run, its size, and when it will be deleted. Search by name, switch to Given to runs for the files runs were given, or narrow to one script. A script’s page shows its latest files too, with See all files. Every file links to the run that made it.

Through the API, GET /v1/files gives the same list, with ?script=<slug>, ?direction=in (or all) and ?q= for a name; each file comes with a download link valid for an hour. From the command line, reminix files list.

--file uploads a file for an input, and --out saves the files the run writes:

Terminal window
reminix scripts run convert-statement \
--input '{"account":"acme"}' \
--file statement=./september.pdf \
--out ./results

Repeat --file for an input that takes several files. Without --out, the command prints each written file’s name and download link. reminix files download <id> saves one file later.

Upload the file first, then pass its id as the input:

Terminal window
curl -X POST "https://api.reminix.com/v1/files?name=september.pdf" \
-H "Authorization: Bearer $REMINIX_API_KEY" \
-H "Content-Type: application/pdf" \
--data-binary @september.pdf
# → { "id": "file_4c1e…", "name": "september.pdf", … }
curl -X POST https://api.reminix.com/v1/scripts/convert-statement/runs \
-H "Authorization: Bearer $REMINIX_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "inputs": { "account": "acme", "statement": "file_4c1e…" } }'

One run uses each upload. To give a second run the same file, upload it again, or pass the id of a file an earlier run wrote: one script’s output can be the next script’s input.

GET /v1/runs/{id} lists the run’s files: the ones it was given ("direction": "in") and the ones it wrote ("direction": "out"). Each has a downloadUrl that works for an hour without a key, and GET /v1/files/{id}/content returns a file’s bytes with your key. Reminix always sends a file as a download, never as a page to view.

An agent can’t carry a file inside a tool call, so a file input also takes an https link. Reminix downloads the file when the run starts and gives it to the script like an upload. Reminix refuses links to private networks. The run’s result lists the files it wrote, each with a download link the agent can share.

A schedule runs with no one there to give it a file, so a script that needs a file for every run can’t run on a schedule. A file input that’s optional is left empty on scheduled runs.

Reminix deletes an upload that no run uses after a day. It keeps a run’s files, given and written, for your plan’s number of days, and each file can be as large as your plan allows. A run writes at most a set number of files, and Reminix leaves out any over the limits with a line in the run’s log. The numbers are on Plan allowances.