Storage and filesystem layout¶
What lives on disk vs. in postgres, and how to plan for it.
Two roots¶
Trimus writes to two filesystem roots:
| Variable | Default | What goes there |
|---|---|---|
TRIMUS_HOME |
$HOME/.trimus/ |
Per-company / per-agent / per-project directories |
TRIMUS_STORAGE_DIR |
./storage |
Uploaded attachments and assets |
Both should be on persistent disk in production. A single Trimus
install can host many companies; the layout below is per-company
under TRIMUS_HOME.
TRIMUS_HOME layout¶
$TRIMUS_HOME/
├── companies/
│ └── <company-id>/
│ ├── files/ Company-scope files
│ ├── skills/ Company-scope FS skills
│ │ └── <slug>/
│ │ ├── SKILL.md
│ │ └── skill.yaml
│ ├── projects/
│ │ └── <project-id>/
│ │ └── files/ Fallback project workspace
│ │ (when project.working_dir is unset)
│ └── agents/
│ └── <agent-id>/
│ ├── files/ Per-agent files
│ ├── skills/ Per-agent FS skills
│ ├── work/ claude_local working directory
│ │ (used when no project working_dir)
│ └── bootstrap/
│ └── credentials.env Hired-agent API key bootstrap
companies/<id>/files/¶
Generic file storage scoped to the company. Visible at the Files
sidebar entry in the UI, accessible via /api/companies/{id}/files.
Mostly used for shared reference material agents need.
companies/<id>/skills/<slug>/¶
FS skills shared across every agent in the company. Each is a
directory with SKILL.md + skill.yaml. Editable through the UI
(Skills → click into a skill) or directly on disk; changes take
effect on the next agent run.
companies/<id>/projects/<id>/files/¶
The Trimus-managed fallback workspace for a project. Used when
project.working_dir is not set. Files agents write via
/write-file land here. Operators rarely touch these directly —
they're managed through the project's UI page.
When project.working_dir IS set, the workspace resolves to that
operator-managed path instead, and these directories aren't created.
companies/<id>/agents/<id>/¶
Per-agent home. Contains the agent's per-agent files, per-agent FS
skills, and a work/ directory used as the CLI's CWD by the local and
sandboxed CLI adapters (claude_local, codex_local, claude_sandbox,
codex_sandbox) when an issue has no project working_dir.
The bootstrap/credentials.env file is created when an agent is
hired by another agent — it holds the new agent's API key so its
first heartbeat can authenticate. Sensitive: 0600 perms, do not
log.
TRIMUS_STORAGE_DIR layout¶
$TRIMUS_STORAGE_DIR/
├── attachments/
│ └── <issue-id>/
│ └── <attachment-id>/<filename>
├── assets/
│ └── <asset-id>/<filename>
└── <company-id>/
└── logos/<uuid> Company logo image bytes
Attachments are uploaded files attached to issues. Assets are company-scoped reference uploads. Logos are raster company brand images for the UI (PNG/JPEG/GIF/WebP — SVG is rejected). See branding.md.
Total size scales with usage. The default TRIMUS_MAX_UPLOAD_SIZE
(25 MB per upload) is the per-file cap; nothing limits aggregate
size besides your disk.
Per-company / per-agent home overrides¶
Both companies and agents have an optional home_dir override. When
set:
- The company's resolved home becomes that absolute path instead of
$TRIMUS_HOME/companies/<id>/. - An agent's resolved home becomes that path instead of the default-under-the-company.
Use cases:
- Multi-host setups where different companies live on different block-storage volumes.
- Compliance: keeping one company's data physically isolated from another's.
- Migrating from another tool: pointing a company's home at an existing directory tree.
Changing home_dir does not move existing files. The old path
remains on disk; the new path is just where future writes go. If
you need to migrate, copy first and then update the override.
Permissions¶
The OS user running trimus-server needs:
- Read + write + execute on
TRIMUS_HOMEandTRIMUS_STORAGE_DIR. - Read + write + execute on every operator-managed
project.working_dirfor any project where agents will write.
Recommended: dedicated trimus user, TRIMUS_HOME owned trimus:trimus
with mode 750, files written 0600. The shipped Dockerfile already
sets this up under /data/.
Disk planning¶
Rough sizing for a small team running ~10 agents on 50 issues/day:
- Database: 500 MB / month with default retention.
TRIMUS_HOME: 100 MB baseline + project workspaces (depends on what agents write — could be tiny, could be GBs).TRIMUS_STORAGE_DIR: depends on attachment volume — typically small unless humans are uploading lots of binaries.
Monitor disk on both roots. The clean failure mode (disk full → write errors → run failures) is loud, but you'd rather catch it ahead of time.
Backups¶
The filesystem roots need to be backed up alongside postgres. A postgres-only backup is not enough to fully restore — you'll have rows referencing files that don't exist.
Three things to back up:
- Postgres (see database.md).
TRIMUS_HOME—tarit nightly, or use filesystem-level snapshots if your storage supports them.TRIMUS_STORAGE_DIR— same.
Restore order: postgres first, then files. Trimus gracefully handles "row references a missing file" with 404s rather than crashing, but you'll see broken downloads until the files come back.
Cleanup¶
Trash¶
Soft‑deleted skills / home entities move into $TRIMUS_HOME/trash/
(organised by type, e.g. trash/company-skills/<company>/<slug>), each
with a trash-info.json recording the original path. The restore path
is validated so a tampered trash-info.json can't redirect a restore
outside its expected scope (SEC‑025). The Admin → Trash
(/admin/trash) page lets instance admins inspect, restore, or
hard‑delete early.
Run-event pruning¶
heartbeat_run_events rows in postgres age out after
TRIMUS_RUN_EVENTS_RETENTION_DAYS (default 30) for succeeded runs;
failed‑run events are kept indefinitely. The associated heartbeat_runs
records have their own retention (TRIMUS_HEARTBEAT_RUN_RETENTION_DAYS,
default 90).
Manual cleanup¶
If a company is being decommissioned:
- Delete the company through the UI (admin only). This CASCADEs in postgres and queues the on-disk tree for trash.
- After the trash retention window, the on-disk tree is removed.
- To force-remove immediately, hard-delete from Admin → Trash.
Where to next¶
- database.md — the postgres-side of "what's on disk".
- secrets-and-encryption.md — the encryption-at-rest story for sensitive blobs.
- adapters.md — how
claude_localanddockeragents use these directories.