Skip to main content

osftool — Command-Line Tool

osftool is a verb-based command-line tool for working with Open Streaming Format files. It reads and writes OSF4 and OSF5, transparently handles compressed OSFZ files, and bundles the everyday tasks around OSF data into a single executable: merging files over a time interval, exporting channels to CSV or HDF5, inspecting metadata, computing statistics, converting between format versions, and checking file integrity.

osftool is built on the Delphi OSF library (implementations/delphi/src/). The primary build target is Windows 64-bit; the project also carries macOS (Intel and Apple Silicon) and Linux 64-bit build configurations. The current version is 1.1.0.

What osftool is for

osftool covers the recurring tasks of an OSF-based workflow from a script or a terminal — no IDE and no code required:

  • Combining field data. Many OSF/OSFZ files scattered across a directory tree are scanned and merged into a single file for a chosen time interval and channel selection.
  • Getting data into analysis tools. Channels are exported to CSV — one XY block per channel, or a single shared timeline with one column per channel — or, on the Windows build, to an HDF5 file.
  • Inspecting files quickly. Metadata, time range, channel lists, and per-channel statistics are available without opening the file in an application.
  • Migrating between format versions. OSF4 files are rewritten as OSF5 and vice versa.
  • Checking integrity. Files are walked block by block and verified for structural consistency.
  • Automation. Every command has a machine-readable --json mode and a uniform set of exit codes, so osftool composes cleanly into scripts and CI pipelines.

Installation

Windows installer

The quickest way to get osftool on Windows is the prebuilt installer:

Download osftool for Windows (64-bit)

The installer deploys OsfTool.exe together with the HDF5 runtime, adds the program directory to PATH, and lets you choose an all-users or a per-user installation. Once it finishes, osftool is available from any terminal.

Building from source

osftool is part of the OSF repository and is built with Embarcadero Delphi 12 (RAD Studio 23) or newer.

cd implementations/delphi/tools/osftool
dcc64 -B -Q OsfTool.dpr

This produces OsfTool.exe for Windows 64-bit. The OsfTool.dproj project file additionally carries OSX64, OSXARM64, and Linux64 build configurations for use from the RAD Studio IDE; the source is conditional-compilation clean for those targets.

Adding osftool to PATH

To call osftool from any directory, add its location to the search path:

osftool config install-path

On Windows this writes the executable's directory to the per-user PATH (HKCU\Environment) — no administrator rights required. On macOS and Linux the command prints the shell snippet to add to ~/.zshrc or ~/.bashrc. The change is undone with osftool config uninstall-path.

General usage

osftool <command> [options] [arguments]
osftool <command> --help

Running osftool with no arguments, or osftool --help, prints the global help with the command list. Appending --help to any command prints that command's detailed help without doing any work. osftool --version (or -V) prints the version and build timestamp; add --short for just the version number.

Commands

CommandPurpose
mergeMerge OSF files from a directory over a time interval
exportExport OSF channels to CSV or other formats
infoShow file metadata and time range
channelsList all channels in a file
statCompute statistics (min, max, mean, …) per channel
cacheManage .json sidecar cache files
configView and edit default settings
convertConvert between OSF4 and OSF5
verifyCheck file integrity and block consistency

Global options

These options are understood by every command:

OptionEffect
--jsonEmit a machine-readable JSON result on stdout instead of human-readable text
--quietSuppress informational prose; warnings and errors are still shown
--verbosePrint debug-level log messages to stderr

Results go to stdout, log messages and errors to stderr, so the two can be redirected independently. In --json mode stdout carries only the JSON document.

Exit codes

CodeMeaning
0Success
1Bad arguments
2File or directory not found
3I/O error
4Format error (invalid or corrupt OSF file)

The sidecar cache

Several commands can use a .json sidecar file stored next to each OSF file. The sidecar holds per-channel metadata — sample counts, first and last timestamps, the global time range — that the OSF metablock alone does not carry. With a valid sidecar present, commands such as info and channels answer instantly instead of scanning every block.

The sidecar is consulted automatically; pass --no-cache to ignore it and scan the source file directly. The cache command builds, rebuilds, inspects, and removes sidecars in bulk.

Command reference

merge

Scans a directory recursively for .osf and .osfz files, selects those overlapping a time interval, and merges the chosen channels into a single output file.

osftool merge <rootdir> <outputfile> [channel ...] [options]
ArgumentDescription
rootdirRoot directory; scanned recursively for .osf and .osfz
outputfileOutput file path (.osf)
channelOptional channel names; omit to merge all channels
OptionDescription
--start <ts>Interval start, ISO 8601 (default: 1970-01-01T00:00:00)
--end <ts>Interval end, ISO 8601 (default: the current date and time)
--osf4Write OSF4 output (default: from config output.format)
--overwriteOverwrite overlapping timestamps (default: from config output.overlap)
--no-cacheDo not read or write .json sidecar files
-q, --quietSuppress the live display; print only errors, on stderr
-v, --verbosePrint every log line (the classic scrolling output, no live bar)
--jsonEmit a machine-readable JSON-Lines event stream on stdout
--log <path>Write a full diagnostic log (every level) to a file

--start and --end are optional and independent: each defaults on its own, and a flag, when given, overrides only that bound. With neither flag, merge covers the full available range.

# Merge everything under ./field-data into one file
osftool merge ./field-data combined.osf

# Merge only two channels within a time window
osftool merge ./field-data window.osf Sensor/Temperature Sensor/Pressure \
--start 2026-05-05T10:00:00 --end 2026-05-05T12:00:00

By default merge shows a live progress display: a short header announces each phase — scanning the directory, reading the file metadata, reading the files, writing the output — and a single progress-bar line is redrawn in place beneath it, showing the percentage, the file counter, and the name of the file currently being processed. Warnings and errors scroll out above the bar as they occur; the low-level per-channel informational chatter stays suppressed.

Reading files...
[████████████████████░░░░░░░░░░░░░░░░░░░░] 50% (173/346) - 20260517_192802.osfz

The output flags change this presentation and are mutually exclusive: -v / --verbose prints the full scrolling log instead; -q / --quiet prints only errors on stderr and is otherwise silent; --json emits a JSON-Lines event stream for pipelines. --log <path> is orthogonal — it writes the complete diagnostic log to a file in any mode. When stdout is redirected to a pipe or file the live display is automatically replaced by periodic plain progress lines.

export

Exports the channels of a single OSF/OSFZ file to CSV — or, on the Windows build, to HDF5.

osftool export <inputfile> <outputfile> [channel ...] [options]
ArgumentDescription
inputfileSource .osf or .osfz
outputfileOutput file path
channelOptional channel names; omit to export all channels
OptionDescription
--format <fmt>csv (default) — one XY block per channel; unified-csv — a single shared timeline with one column per channel; hdf5 — an HDF5 file, one dataset per channel (Windows build only)
--timestamp-format <fmt>Timestamp format for unified-csv: datetime (default), seconds, iso8601, nanoseconds
--start <time>Only export samples from this UTC time (ISO 8601)
--end <time>Only export samples up to this UTC time (ISO 8601)
--decimal-sep <c>CSV decimal separator: comma (default) or dot
--encoding <enc>CSV encoding: iso-8859-1 (default) or utf-8
--chunk-size <n>HDF5: samples per dataset chunk (default 8192)
--deflate-level <n>HDF5: gzip compression level 09 (default 4)
--no-shuffleHDF5: disable the shuffle pre-compression filter
--namespace-sep <c>HDF5: separator that splits a channel name into an HDF5 group path (default .)
--hdf5-lib-dir <path>HDF5: directory to search for hdf5.dll
--exclude-emptySkip channels with zero samples

--start and --end must be supplied together — one without the other is rejected. The defaults for --decimal-sep and --encoding come from the configuration file.

The hdf5 format is available on the Windows build only. Each channel becomes a chunked, deflate-compressed 1-D dataset of {int64 timestamp_ns; value} records; the channel name is split on --namespace-sep into an HDF5 group hierarchy, and file- and channel-level metadata is written as HDF5 attributes. The export needs the HDF5 runtime: hdf5.dll must be reachable on the system search path or in the directory named by --hdf5-lib-dir. The --chunk-size, --deflate-level, --no-shuffle, and --namespace-sep flags apply to hdf5 only; --decimal-sep and --encoding apply to the CSV formats only.

osftool export motorbike.osf motorbike.csv --format unified-csv \
--timestamp-format iso8601 --decimal-sep dot

# HDF5 export (Windows build), stronger compression
osftool export motorbike.osf motorbike.h5 --format hdf5 --deflate-level 6

info

Shows file metadata and the global time range.

osftool info <file> [options]
OptionDescription
--no-cacheDo not consult the .json sidecar; scan the OSF file directly
--jsonOutput as JSON

The report includes the format version, creator and creation time, tag, reason, comment, channel count, the first and last data timestamps, and the resulting duration.

osftool info motorbike.osf

channels

Lists every channel in the metablock.

osftool channels <file> [options]
OptionDescription
--filter <pattern>Wildcard filter on the channel name, e.g. GPS.*
--no-cacheDo not consult the .json sidecar
--jsonOutput as a JSON array

Each row shows the channel index, name, data type, physical unit, and — when a valid sidecar is available — the sample count and first/last timestamps. Without the sidecar those columns report ?.

osftool channels motorbike.osf --filter "Sensor/*"

stat

Computes minimum, maximum, mean, and standard deviation per numeric channel, using Welford's single-pass online algorithm.

osftool stat <file> [channel ...] [options]
OptionDescription
--start <time>Only consider samples from this UTC time (ISO 8601)
--end <time>Only consider samples up to this UTC time (ISO 8601)
--jsonOutput as JSON

--start and --end are each independently optional. String, binary, and gpslocation channels are listed but marked not numeric. Int64/UInt64 channels are flagged for possible precision loss when converted to Double for the calculation.

osftool stat motorbike.osf --start 2026-05-05T10:00:00

cache

Manages the .json sidecar cache files for every .osf/.osfz file under a directory.

osftool cache <subcommand> <rootdir> [options]
SubcommandDescription
buildBuild missing sidecars; skip files whose sidecar is already valid
rebuildForce-rebuild every sidecar
cleanDelete all sidecars under rootdir
statusReport which files have no valid sidecar
OptionDescription
--no-recursiveRestrict to the root directory only (default: include subdirectories)
--jsonOutput as JSON
osftool cache build ./field-data
osftool cache status ./field-data

config

Inspects and changes the persistent settings used as default values by other commands, and manages the PATH entry.

osftool config Show all current settings
osftool config set <key> <value> Set a value
osftool config reset Reset all settings to defaults
osftool config install-path Add osftool to the user PATH
osftool config uninstall-path Remove osftool from the user PATH
osftool config --json Show settings as JSON

See Configuration below for the available keys.

convert

Converts a single file between OSF4 and OSF5 by round-tripping it through the merger.

osftool convert <inputfile> <outputfile> [options]
OptionDescription
--osf4Write the output as OSF4
--osf5Write the output as OSF5
--jsonOutput as JSON

--osf4 and --osf5 are mutually exclusive. When neither is given, the target version comes from the config key output.format. Note that the converter always emits absolute-timestamp data blocks regardless of the source layout.

osftool convert legacy.osf modern.osf --osf5

verify

Walks a file end to end and checks it for structural integrity.

osftool verify <file> [options]

The following checks are performed:

  1. Magic header readable and version recognised.
  2. Metablock parseable (valid XML or JSON).
  3. Every block's channel index is present in the metablock.
  4. No block declares a length exceeding the file size.
  5. Timestamps increase monotonically per channel.
  6. The file ends cleanly — the last block is not truncated.
OptionDescription
--strictTreat warnings as errors (affects the exit code)
--jsonOutput as JSON

Integrity-breaking problems are reported as errors and produce exit code 4; recoverable concerns (such as a truncated final block) are warnings. With --strict, warnings also produce exit code 4.

osftool verify motorbike.osf --strict

Configuration

osftool stores persistent settings in a JSON file. Other commands read it for their default values, so the configuration acts as a per-user policy.

PlatformLocation
Windows%APPDATA%\osftool\config.json
macOS / Linux~/.config/osftool/config.json

The file is optional — when it is missing, every setting falls back to its built-in default.

KeyDefaultMeaning
output.formatosf5Default output format for merge and convert
output.overlapskipOverlap strategy: skip or overwrite
export.decimal_sep,Default CSV decimal separator
export.encodingiso-8859-1Default CSV encoding
cache.enabledtrueUse .json sidecar files
cache.auto_buildtrueAuto-build the cache during a scan

Values are read and written with the config command:

osftool config # show all settings
osftool config set output.format osf4 # change a default
osftool config reset # restore the defaults

A command-line flag always overrides the configured default for that single invocation.