Skip to content

Files

A script can take files and hand files back. The monthly report on this page takes an optional CSV file of manual adjustments and writes last month’s revenue as a CSV file for Finance. 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": "monthly-report",
"name": "Monthly report",
"command": "python report.py [--month {month}] [--adjustments {adjustments}]",
"inputSchema": {
"type": "object",
"properties": {
"month": { "type": "string", "title": "Month" },
"adjustments": {
"type": "string",
"title": "Manual adjustments",
"format": "file",
"contentMediaType": "text/csv"
}
}
}
}

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:

"adjustments": {
"type": "string",
"format": "file",
"contentMediaType": "text/csv",
"examples": ["samples/adjustments.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, the month 2026-09 and a file called adjustments.csv, Reminix runs:

Terminal window
python report.py --month 2026-09 --adjustments /inputs/adjustments/adjustments.csv

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

{
"month": "2026-09",
"adjustments": {
"path": "/inputs/adjustments/adjustments.csv",
"name": "adjustments.csv",
"type": "text/csv",
"size": 2048
}
}

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/revenue-2026-09.csv.

import argparse, csv, datetime, json, os
last_month = (datetime.date.today().replace(day=1) - datetime.timedelta(days=1)).strftime("%Y-%m")
parser = argparse.ArgumentParser()
parser.add_argument("--month", default=last_month)
parser.add_argument("--adjustments") # a path in /inputs, or None
args = parser.parse_args()
month = args.month
rows = revenue_by_day(month, args.adjustments) # your query, reading api.stripe.com
path = os.path.join(os.environ["REMINIX_OUTPUTS"], f"revenue-{month}.csv")
with open(path, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["day", "charges", "refunds", "net"])
writer.writerows(rows)
print(json.dumps({"month": month, "days": len(rows)}))

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.

From the CLI, reminix files list; from your code, reminix.files.list(). Each file comes with a download link valid for an hour (see List files).

Pass the file as the input. Reminix uploads it first and gives the run its id; --out (or the files on the finished run) brings back what the run writes:

import { readFile } from "node:fs/promises";
import { createClient } from "@reminix/sdk";
const reminix = createClient();
const run = await reminix.run("monthly-report", {
month: "2026-09",
adjustments: {
name: "adjustments.csv",
type: "text/csv",
data: await readFile("adjustments.csv"),
},
});

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.

A finished run lists its 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. On the run’s page in the app, each one is a download; reminix files download <file-id> saves one, and reminix.files.download(fileId) returns its bytes (see Download a file). 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: the monthly report’s schedule runs on the 1st without adjustments, and still writes its CSV file.

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.