title: "Scripts: the side assistant" description: "The scripts folder, the explorer, the editor, the console and the run lifecycle." nodes: 18 progress: 89% generated: ohm spec editor#
Scripts: the side assistant#
The scripts folder, the explorer, the editor, the console and the run lifecycle.
Contents#
☑ Overview#
☑ Scope#
note
packages/core/src/{script-files,script-service,examples}.ts, the Scripts panel,
the Monaco editor integration and the console.
☑ Scripts are plain files in a folder the user owns#
decision
Documents/Ohm by default, overridable with OHM_SCRIPTS_DIR. No database, no
hidden store: the same folder is visible in the OS file manager, works with git, and
is where projects live too.
The one reserved area is .ohm/, which holds memory, the trash and screenshots and
is hidden from the explorer.
- spec:
12-storage
☑ The file surface#
☑ ScriptFiles#
api #security
ensureRoot(seed), list(), read, write, exists, create(rel, 'file' | 'dir'), delete, rename, listDir, exportTo, importFrom.
Every path is resolved against the root and rejected if it escapes it; the reserved
.ohm directory is refused as well, so neither the UI nor a script can reach it
through the normal API.
☑ Delete means trash#
requirement #safety
Deleting moves the item to .ohm/trash/<timestamp>-<name> rather than unlinking it.
A misclick in a file tree should never be final.
☑ Import and export never overwrite#
requirement
Importing a folder copies it in under a unique name, and exporting writes a tree to a chosen folder. A name collision gets a suffix instead of clobbering, and the copy is bounded by a file-count budget so a mistaken pick cannot run away.
- node:
script-files
☑ First run seeds examples#
requirement #regression
An empty scripts folder is seeded with runnable examples — ai/ (agent, compose,
parallel, research), models/ (list, download GGUF, download a web model, compare
profiles), browse.ohm, math.ohm, memory.ohm, welcome.ohm and a
README.md that doubles as the language reference. Settings has a "restore
examples" action that re-seeds without touching the user's own files.
A test compiles every bundled example, so a language change that breaks the seeds fails the build.
- spec:
02-ohm-language
☑ Running#
☑ A run#
flow
scripts.run accepts a path or inline source, allocates a runId, compiles,
and streams:
- compile diagnostics as
errlines formattedname:line:column: message, - output events (
out,err,info,warn,result) as they happen, - a final
scripts.statuswith the outcome.
A script under projects/<id>/ is automatically bound to that project; a loose
script uses the active project and says so clearly when there is none.
☑ The console is a persistent session#
requirement
The console runs in its own session whose Lua globals persist between lines, which is
what makes it a REPL: assign a variable on one line and use it on the next. It
accepts both Lua and math ($\frac{22}{7}$), and a bare expression prints its
value.
Stopping resets the session and says so on the info stream, because terminating
the worker necessarily discards the globals.
- spec:
02-ohm-language— the worker runner and stopping
☑ Run history is bounded#
requirement
Finished runs are pruned to 150 entries once 200 accumulate, so a long session cannot grow without limit.
☑ Three views of one file#
component #regression
The editor toolbar switches between Code (Monaco, editable), Math (the LaTeX typeset) and Lua (the compiled output). Monaco stays mounted while the typeset view is shown, so a toggle does not lose the cursor, selection or undo history.
The typeset view is produced by renderOhm in @ohm/ohm-lang, which walks the
compiler's own AST:
- It knows Ohm's operators —
\CoT_{\Psi}renders as CoT with a Ψ subscript — which a general LaTeX renderer cannot, since they are not LaTeX commands. - It is honest: a region the compiler would reject renders as its source plus the error, never as pretty output.
- It emits a node tree, not HTML, and the UI maps that to MathML, so nothing is injected and no font or typesetting library ships.
Reading choices worth preserving: / and \frac both become a fraction;
\sqrt[n]{x} reads as a root again although the parser rewrote it to a power;
x_i stays a subscript while m["key"] becomes a bracket index; and clicking a
formula flips that one back to its LaTeX.
Two rendering details that were each a visible bug: MathML puts no gap between two
adjacent <mi>, so a keyword needs an explicit <mspace> or if collides with
its condition; and a <math display="block"> centres its content, which is wrong
for a program, so the box is shrunk to its content with width: fit-content
(text-align does not reach MathML layout).
- spec:
02-ohm-language
☑ Completion, hover and signature help#
component
Monaco providers, all driven by EditorSettings pushed in from the renderer:
- Completion after
\offers commands with snippets, every operator with its family and signature, math functions, and library entries as\Usecalls; afterobj.it offers that object's host API, and afterlib.the entries that actually exist. - Hover explains operators, commands, host API members and library entries, showing an entry's body.
- Signature help finds the call the cursor sits in by scanning back for an
unclosed
(, and highlights the argument by counting commas — so it works for\CoT_{\Psi}(q; C)as well astab.waitFor(sel, ms).
Every one of these is switchable, and "insert placeholders" decides whether a completion inserts tab stops or plain text.
- spec:
04-models-and-settings
☑ The editor#
component
Monaco with Ohm syntax highlighting, completion after \ and after browser. /
tab., live syntax errors from the real compiler, the Code/Math/Lua switch,
F5 to save and run, Ctrl+S to save, Shift+F5 to stop.
Because compilation preserves line numbers, clicking an error in the console jumps to
the right line of the .ohm source.
- spec:
02-ohm-language— line-for-line compilation
☑ Review findings#
☐ Open a .ohm file passed on the command line#
task
Nothing reads process.argv for a file path, so a double-clicked script would open
an empty window. This is the prerequisite for registering the .ohm file
association in the installers.
- spec:
13-packaging
☐ The editor API table is out of date#
note low
The completion table documents browser, tab, ai, specs, models,
fs, json and ohm but omits project, prompts, curves and
experiments, which the runtime does provide — so completion under-reports the
real surface.
- spec:
02-ohm-language
Links between nodes#
graph LR
import_and_export_never_overwrite["Import and export never overwrite"] -.-> script_files["ScriptFiles"]