Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/aipoch/open-science/llms.txt

Use this file to discover all available pages before exploring further.

Open Science is local-first — every piece of data it produces lives on your own machine. There are no accounts, cloud sync services, or remote databases involved. All persistent state — projects, chat sessions, agent-produced artifacts, notebook run histories, and staged uploads — is written under a dot-directory in your home folder. Understanding this layout helps you back up your research, debug unexpected behavior, or migrate your data to another machine.

Storage Root Paths

The storage root is the top-level directory that contains everything Open Science writes. Its location follows each platform’s conventions:
PlatformPath
macOS~/.open-science/
Windows%USERPROFILE%\.open-science\
Linux~/.open-science/
The path is resolved at runtime by storage-root.ts using app.getPath('home') — it does not use app.getPath('userData'), so it is a dot-directory in your home folder rather than the OS app data folder.
When running from source with npm run dev, Open Science isolates its data to a sibling directory called .open-science-project to avoid polluting your real .open-science tree. The two directories are otherwise identical in structure. app.isPackaged controls which name is used.

Directory Layout

The complete directory tree under the storage root looks like this:
~/.open-science/                    ← storage root
├── open-science.db                 ← SQLite (Projects + ProjectPreviewState)
├── sessions/                       ← chat session JSON files
│   ├── manifest.json               ← last-open project/session pointer
│   └── {projectId}/
│       └── {sessionId}.json
├── artifacts/                      ← agent-produced output files
│   └── {projectName}/
│       └── {sessionId}/
│           ├── {messageId}/        ← finalized (durable)
│           │   └── {filename}
│           └── .pending/           ← in-flight run files (pre-finalization)
│               └── {runId}/
│                   └── {filename}
├── notebooks/                      ← notebook session directories
│   └── {sessionId}/
│       ├── run.json                ← NotebookRunDocument
│       └── data/                   ← kernel working files
└── uploads/                        ← staged upload files
    └── default-project/            ← fixed bucket (DEFAULT_UPLOAD_PROJECT_NAME)
        ├── .pending/               ← pre-send staged files
        └── {sessionId}/            ← finalized uploads
            └── {filename}
To back up all your Open Science research data — projects, sessions, artifacts, notebooks, and uploads — simply copy the entire storage root directory (~/.open-science/) to a safe location. Restoring is equally straightforward: copy it back and relaunch the app.

SQLite Database

File: open-science.db in the storage root. The database is created automatically on first launch. Open Science applies its schema using CREATE TABLE IF NOT EXISTS DDL at startup — no migration engine is required in the packaged app. The schema is managed via Prisma during development. The database contains exactly two tables:

Project

Stores user-created research projects.
ColumnTypeDescription
idTEXT (CUID)Primary key, auto-generated
nameTEXTUser-assigned project name
descriptionTEXTOptional project description (default: empty string)
isExampleBOOLEANWhether this is a bundled example project
createdAtDATETIMECreation timestamp
updatedAtDATETIMELast modification timestamp (auto-updated)

ProjectPreviewState

Stores the per-project preview panel UI state so it survives app restarts.
ColumnTypeDescription
projectIdTEXTPrimary key — matches a Project.id
panelStateTEXTOpen/collapsed state of the preview panel
activeItemIdTEXTCurrently active preview tab ID (nullable)
itemsTEXTJSON array of open file previews (default: [])
updatedAtDATETIMELast modification timestamp (auto-updated)
Sessions, messages, artifacts, and notebook runs are not stored in SQLite. They are stored as JSON files and directories on disk (see the sections below). The database only tracks the project list and panel state.

Sessions

Chat sessions are stored as JSON files on disk, one file per session, organized by project ID:
sessions/
├── manifest.json
└── {projectId}/
    └── {sessionId}.json
  • manifest.json records the last-open project and session so the app can reopen to the correct state on next launch.
  • Session files are written atomically (write to a .tmp file, then rename) to protect against data loss during crashes.
  • Reads are performed on app start — all session files are loaded into memory by the session persistence module.
  • If a session file is unreadable or contains invalid JSON, it is renamed to {sessionId}.json.invalid-{timestamp} as a backup rather than deleted.

Artifacts

Agent-produced output files are organized under the artifacts/ directory by project, session, and message:
artifacts/
└── {projectName}/
    └── {sessionId}/
        ├── {messageId}/       ← durable message artifacts
        │   └── {filename}
        └── .pending/          ← in-flight artifacts during a run
            └── {runId}/
                └── {filename}
  • projectName is the logical project bucket. For sessions not yet associated with a named project, the constant DEFAULT_ARTIFACT_PROJECT_NAME = 'default-project' is used as the bucket name.
  • Pending artifacts (under .pending/{runId}/) are written while an agent run is active. The renderer finalizes them by calling FinalizeRunArtifactsRequest, which moves them into the durable {messageId}/ directory.
  • Artifact files are never deleted automatically. You are responsible for managing disk space in the artifacts/ tree.

Notebooks

Each notebook session has its own directory under notebooks/:
notebooks/
└── {sessionId}/
    ├── run.json    ← full execution history
    └── data/       ← kernel working files (scripts, outputs, caches)
The directory names come directly from the source constants:
export const NOTEBOOKS_DIR = 'notebooks'
export const NOTEBOOK_RUN_FILE = 'run.json'

run.jsonNotebookRunDocument

The run.json file is the authoritative record of everything that has happened in a notebook session. It is a NotebookRunDocument (schema version 1) with the following top-level fields:
FieldTypeDescription
version1Schema version — always 1
projectNamestringOwning project name
sessionIdstringNotebook session identifier
workspaceCwdstringInitial working directory of the kernel
notebookSessionRootstringAbsolute path to this session’s directory
dataRootstringAbsolute path to the data/ subdirectory
kernelNotebookKernelMetadataLanguage, Python path, kernel name, last known status
runsNotebookRunRecord[]Ordered list of all cell executions
updatedAtnumberUnix timestamp (ms) of the last write
Each entry in runs captures the cell source code, execution status, stdout/stderr output, structured outputs (text, JSON, error tracebacks), and references to any artifact files or working files created during that execution.

Uploads

User-uploaded files are staged under uploads/ before being sent to the agent:
uploads/
└── default-project/    ← fixed bucket (DEFAULT_UPLOAD_PROJECT_NAME = 'default-project')
    ├── .pending/       ← staged before a session id is known
    └── {sessionId}/    ← finalized after the runtime session is created
        └── {filename}
All uploads share a single fixed project bucket: the constant DEFAULT_UPLOAD_PROJECT_NAME = 'default-project' from src/shared/artifacts.ts. There is no per-user or per-project upload directory selection.
  • Staging: when a user attaches a file or pastes an image before sending a message, it is written to .pending/ (the constant PENDING_UPLOAD_SESSION_ID = '.pending' from src/shared/uploads.ts).
  • Finalization: once the agent runtime assigns a session ID, pending uploads are copied into {sessionId}/ and the staging file is deleted, associating them durably with that conversation.
  • Orphaned staging files: if the app crashes between staging and finalization, files may remain in .pending/. These can be safely deleted — they are not referenced by any session.
  • Upload filenames are sanitized and deduplicated automatically. The original display name is stored separately in the attachment record (originalName) and is not lost.

Build docs developers (and LLMs) love