Files, Events, and the Source Structure
On this page
The workspace filesystem (tako.pwd/cd/ls/stat/exists/read/write/mkdir/rm/mv/cp), the format-aware tako.input/tako.output read/write helpers, calculation event subscription (tako.events.on), and the run’s source structure (tako.source.active). Calculation artifacts are ordinary paths to this API: ls/stat/read/input address them exactly like files, so there is no separate artifact API — and everything that PRESENTS a file or the 3D scene lives in tako.ui.* (show, snapshot, capture, setStructure, camera, style).
Every path is resolved the same way: a leading / is absolute from the workspace root, anything else resolves against the script’s current working directory (changed with tako.cd); . segments are dropped and .. walks up one segment. A calculation’s own folder path doubles as two virtual input/output subfolders that list its actual artifacts even though nothing is really nested there on disk. Scripts run inside a sandboxed worker against a synchronous in-memory mirror of the workspace: fs calls return immediately and are visible to later calls in the same run, but each mutation is journaled and replayed onto the real, persisted workspace asynchronously and optimistically — a script has no way to observe a replay failure.
tako.pwd
tako.pwd() => string
Return the absolute path of the current working directory.
Returns: Absolute path string beginning with ’/’; ’/’ for the workspace root.
tako.cd
tako.cd(path: string) => string
Change the script’s current working directory and return the resulting absolute path.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Absolute (’/‘-prefixed) or cwd-relative path; ’..’ walks up one segment, ’.’ is a no-op segment. |
Returns: The resulting absolute path, same shape as tako.pwd().
- Resolving to the root (’/’) always succeeds without an existence check.
- Any non-root destination must be an existing folder or calculation folder, or a calculation’s input/output subpath; otherwise throws ‘Folder not found’.
tako.cd('/MyRun/output');
tako.pwd(); // '/MyRun/output'
tako.ls
tako.ls(path?: string) => TakoFileStat[]
List the immediate children of a workspace folder, calculation folder, or calculation input/output directory.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | '.' | Folder to list; defaults to the current working directory. |
Returns: Array of TakoFileStat: { name, path, type: ‘folder’|‘file’|‘calculation’|‘artifact’, size, mimeType?, updatedAt? }, one per child.
- Listing a calculation’s own folder synthesizes two virtual ‘input’ and ‘output’ folder entries (size 0, no mimeType) ahead of any of its own non-artifact children.
- Listing a calculation’s input or output subpath returns that calculation’s actual artifacts instead of ordinary folder children.
- Listing a single file or artifact path (rather than a folder) returns a one-element array with just that node’s stat.
- Throws ‘Path not found’ if the path does not exist.
for (const entry of tako.ls('output')) console.log(entry.name, entry.type);
tako.stat
tako.stat(path: string) => TakoFileStat
Return metadata for a single workspace path without reading its full content.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Path to inspect. |
Returns: TakoFileStat: { name, path, type, size, mimeType?, updatedAt? }; size is the content’s character length (0 for folders); a calculation’s input/output subpath reports as a zero-size virtual folder.
- Throws ‘Path not found’ if nothing resolves at the path.
- Reading the stat of a calculation artifact first flushes any pending throttled streaming writes (trajectory/energy logs), so size/mimeType reflect the latest content even mid-calculation.
tako.exists
tako.exists(path: string) => boolean
Report whether a workspace path resolves to an existing folder, file, artifact, or calculation.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Path to check. |
Returns: true if the path exists — the workspace root and any calculation’s input/output subpath always count as existing; false otherwise. Never throws.
tako.read
tako.read(path: string) => string
Read the raw text content of a workspace file or calculation artifact.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | File or artifact path. |
Returns: Raw string content, never parsed; a JSON artifact comes back as its literal serialized text, not an object — use tako.input to parse it.
- Throws ‘Path not found’ if the path does not exist, or ‘Path is not readable’ if it names a folder or calculation.
- Handle-backed and paged content stays lazy and throws with guidance to use await tako.readAsync(path).
tako.readAsync
await tako.readAsync(path: string) => string
Read workspace text on demand, resolving blob-backed and paged artifacts without hydrating them at script startup.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | File or artifact path. |
Returns: Raw string content after the requested payload has been materialized.
tako.write
tako.write(path: string, content: string, options?: { mimeType?: string, createParents?: boolean }) => ExplorerFile
Create or overwrite a plain workspace file with literal string content.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Destination path; a leading ’/’ is absolute, otherwise resolved against the current working directory. |
content | string | — | Literal file content — not JSON-serialized or structure-exported; use tako.output for that. |
options.mimeType | string | inferred from extension | Overrides the auto-detected MIME type. Auto-detection only recognizes .json, .js/.mjs, .ts/.tsx, .md, .xyz/.extxyz, and .cube/.cub; every other extension (including .cif/.vasp/.poscar) defaults to text/plain. |
options.createParents | boolean | false | Create any missing parent folders; without it, writing into a non-existent folder throws. |
Returns: The written ExplorerFile: { id, name, path, parentFolderId, content, mimeType, createdAt, updatedAt }.
- Throws ‘Cannot overwrite non-file path’ if the destination already exists as a folder, calculation, or artifact — use tako.output to update a calculation artifact instead.
- Overwriting an existing file replaces its content and mimeType in place; it does not rename or move it.
- Throws ‘Expected a non-root file path’ if path resolves to the workspace root.
tako.write('notes/summary.md', '# Result\n\nConverged.', { createParents: true });
tako.mkdir
tako.mkdir(path: string, options?: { recursive?: boolean }) => ExplorerTreeNode
Create a workspace folder, or return the existing one if it already exists.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Folder path to create. |
options.recursive | boolean | false | Create missing intermediate parent folders; without it, mkdir throws if the parent does not already exist. |
Returns: The folder’s ExplorerTreeNode: { id, kind, name, path, parentFolderId, reference, status?, metadata? } — a different, lower-level shape than the TakoFileStat returned by ls/stat.
- A no-op that returns the existing node if a folder already exists at the path.
- Throws ‘Path exists and is not a folder’ if a file, artifact, or calculation already occupies the path, and ‘Cannot create root folder’ for the root path.
tako.rm
tako.rm(path: string, options?: { recursive?: boolean, force?: boolean }) => void
Delete a workspace file, folder, calculation, or artifact by path.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Path to delete. |
options.recursive | boolean | false | Required to delete a non-empty folder; ignored for files/artifacts/calculations, which always delete in one step regardless. |
options.force | boolean | false | Suppress the not-found error and silently no-op when the path does not exist. |
Returns: undefined.
- Deleting a calculation’s own folder path deletes the entire calculation workspace, not just an explorer entry; deleting an artifact path clears that artifact’s content from its calculation (and un-pins any pinned artifact layer) rather than removing a file.
- Throws ‘Folder is not empty’ for a non-empty folder unless recursive: true, and ‘Path not found’ if the path does not exist unless force: true.
tako.rm('scratch', { recursive: true, force: true });
tako.mv
tako.mv(from: string, to: string) => void
Move, and optionally rename, a workspace file to a new path.
| Parameter | Type | Default | Contract |
|---|---|---|---|
from | string | — | Existing path to move. |
to | string | — | Destination path. |
Returns: undefined.
- Only supports renaming for plain files; if to’s basename differs from from’s and the source is a folder or artifact, it throws ‘Renaming folders and generated artifacts by path is not supported yet’ — those can only be moved to a new parent under the same name.
- The destination’s parent folder must already exist; mv never creates parent folders.
- Throws ‘Path not found’ if from does not resolve.
tako.cp
tako.cp(from: string, to: string) => ExplorerFile
Copy a workspace file or calculation artifact’s content to a new file path.
| Parameter | Type | Default | Contract |
|---|---|---|---|
from | string | — | Existing file or artifact path to read from. |
to | string | — | Destination file path. |
Returns: The newly written ExplorerFile at to, carrying the source’s content and MIME type.
- Only readable sources (files and artifacts) can be copied; folders and calculations throw ‘Path is not readable’.
- The destination’s parent folder must already exist; like tako.mv, cp never creates parent folders.
- Copying onto an existing file path overwrites it in place (same overwrite rule as tako.write).
tako.input
await tako.input(path: string) => Structure | unknown | string
Read a workspace path and parse it according to its file extension.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | File or artifact path to read. |
Returns: A parsed Structure for structure-file extensions (.xyz, .extxyz, .cif, .vasp/.poscar/.contcar, .cube/.cub); a parsed JSON value for .json; the raw text otherwise.
- Works on any readable path, including a calculation’s input/output artifacts, not only plain workspace files.
- A .json file whose content fails to parse (or is the literal text ‘null’) is returned as its raw text rather than a parsed value, since parse failure and a JSON null both fall back the same way.
const structure = await tako.input('input/molecule.xyz');
tako.output
await tako.output(path: string, value: unknown) => unknown
Serialize a value and write it to a workspace file, or update a calculation artifact in place if the path names one.
| Parameter | Type | Default | Contract |
|---|---|---|---|
path | string | — | Destination path. |
value | unknown | — | A string, a Structure, or any JSON-serializable value. |
Returns: The same value that was passed in.
- A string value is written verbatim; a Structure written to a structure-file extension is exported to that format (extxyz for any extension other than .xyz/.cif/.vasp/.poscar/.contcar); anything else is JSON.stringify’d with 2-space indentation.
- When path resolves to an existing calculation artifact, that artifact’s content is replaced in place (marked edited) instead of writing a plain workspace file; otherwise it writes a plain file and creates any missing parent folders automatically, unlike tako.write, which requires them to already exist.
- The one write call that understands calculation artifacts and structure serialization; there is no separate artifact-write API.
await tako.output('output/summary.json', { energyEv, converged: true });
tako.source.active
await tako.source.active() => Structure
Return the structure that was active when the current script run started.
Returns: A cloned Structure.
- Throws ‘No active structure is available’ if the run started with no structure open.
- Fixed for the whole run — it is the run-start snapshot, not a live read of whatever the app currently shows. Use tako.ui.liveStructure() to read the structure currently on screen instead.
tako.events.on
tako.events.on(listener: (event: CalculationWasmWorkerEvent) => void) => () => void
Subscribe to calculation worker events and return an unsubscribe function.
| Parameter | Type | Default | Contract |
|---|---|---|---|
listener | (event: CalculationWasmWorkerEvent) => void | — | Called synchronously for each event; the event is a discriminated union tagged by type. |
Returns: An unsubscribe function; call it to stop receiving events.
- Event types: ‘ready’; ‘started’ {id, kind}; ‘console’ {id, stream, message}; ‘calculationProgress’ {id, progress}; ‘assetProgress’ {id, progress}; ‘scfStep’ {id, scf}; ‘optimizationStep’/‘trajectoryStep’ {id, frame}; ‘streamedTrajectoryText’ {id, startFrameIndex, chunks}; ‘partialResult’/‘result’ {id, result}; ‘error’ {id, message}; ‘done’ {id}. Most carry the triggering calculation’s id.
- Scoped to this script run’s own calculations: events are only delivered while one of this script’s own tako.singlePoint/optimize/… calls is in flight, not for calculations started elsewhere in the app.
- Not a Promise: subscribes synchronously and does not itself wait for any event.
const stop = tako.events.on((event) => { if (event.type === 'scfStep') console.log(event.scf.energy_ev); });
// stop();
Return to the Tako Script API index.