Skip to content

Export scripts

When the built-in CSV export isn’t enough, NowDoing lets you write your own export scripts in JavaScript. Use it for any output format: CSV variants, JSON, JSON Lines, Markdown daily notes, HTML reports or billing payloads for your accounting system.

Settings → Export scripts → “Open editor…” launches a full editor in its own window.

The editor is built on CodeMirror 6 running in a WKWebView and ships with:

  • JavaScript syntax highlighting
  • Line numbers and bracket matching
  • Search via ⌘F
  • Light/dark theme that follows the system
  • Shortcuts: ⌘↩ Run, ⌘S Save

Output appears in a text pane below the editor. ⌘C copies it; “Save as…” writes it to a file.

Scripts run in a JSContext and are fully offline:

  • no DOM
  • no fetch
  • no file I/O
  • 5-second soft timeout on wall-clock time — runaway scripts are aborted

Pre-injected into every run:

HelperPurpose
csvRow(values)Escapes per RFC 4180 and returns a CSV row
groupBy(items, key)Groups arrays by key
formatDate(date, format)Formats a date
console.log(...)Writes to the output pane

The complete save-file model is passed into your script — all entries, activities, groups, recurring templates, export scripts and metadata such as notes, billing numbers and colors. The formal description lives in the JSON schema under Specifications.

When you create a new script, you can scaffold from one of these templates:

TemplatePurpose
CSV (default)Mirrors the built-in CSV export — a starting point to customize
Markdown daily noteDay summary as Markdown for Obsidian, Bear or Notion
Markdown weekly reviewWeekly report grouped by activity
JSON Lines (NDJSON)One line per entry, ideal for pipelines
const today = entries.filter(e => e.date === input.date);
const lines = today.map(e =>
`- ${formatDate(e.start, "HH:mm")}${formatDate(e.end, "HH:mm")} **${e.activity}** ${e.note ?? ""}`
);
return `# ${input.date}\n\n${lines.join("\n")}`;

input.date comes from the input field above the editor; entries is the pre-loaded data array.

Export scripts run locally inside the app. The sandbox allows no network access and no file I/O — the only way to persist output is the manual “Save as…” dialog. Your data never leaves the Mac.