Skip to main content

OniHarness for Python

Run Oxygen Not Included mod tests from Python and read paused game observations through a local OniMcp server. Developed with Python 3.15 and uv; the Python API supports Python 3.10+. This is an early 0.2.0 preview.

uv pip install oniharness

For a uv project, use uv add oniharness instead.

Native simulation tests

Native tests require the separate OniHarness CLI, .NET 10, and your own local ONI installation. The Python wheel contains no game binaries and no .NET backend. To build the backend from the official source checkout:

git clone https://github.com/LIghtJUNction/OniHarness.git
from oniharness import Cell, Scenario, Suite, expect, parametrize

suite = Suite(
    checkout="./OniHarness", build=True,
    game_path="/path/to/OxygenNotIncluded",
)

@suite.scenario(repeat=3)
@parametrize(temperature=[280, 300, 320])
@expect.mass_conserved()
def oxygen(temperature):
    return Scenario(fill=Cell("Oxygen", temperature=temperature))

print(suite.run(report_path="results/oxygen.json"))  # PASS: 9/9 tests passed

Decorators register definitions; importing the test file never builds a backend or runs physics. suite.run() prepares every selected definition before any backend execution, then uses isolated CLI workers. Each parameter combination has a readable case name. suite.run(filter="temperature=300") selects one. Decorator order is flexible. Multiple/stacked parameter axes form a Cartesian product. Empty selections and duplicate case names are explicit errors.

Assertions work both as decorators and values: Scenario().expect(expect.mass_conserved()). Cell, Region and Scenario describe fixture inputs; the backend performs the physical/schema validation. expect also provides total_mass, cell_mass and cell_temperature, with min and/or max bounds. report.save(path) atomically saves the JSON report.

The original Harness API remains available. If oniharness is already installed on PATH, use Harness(game_path=...) or Suite(game_path=...). Use test_scenarios(path) for JSON files/directories and test_assembly(path, filter="...") for trusted C# test assemblies.

Failures, unsupported binaries, crashes and worker timeouts raise TestFailure; its .report retains the original results. check=False returns those failed results for inspection. Setup failures raise CommandError; .stdout, .stderr and .returncode retain the diagnostics. Empty selections fail.

The verified native adapter is Linux x64 / ONI build 744825, with exact installed-file hashes. Other binaries fail explicitly. Fixture tests never launch Steam, ONI or Unity. They do not establish full colony/mod compatibility. Temperature is Kelvin, mass is kilograms and energy is kilojoules.

Observe a running game

This only needs Python and an already running game with OniMcp enabled. Installation and explicit Steam launch are described in the runtime guide.

from oniharness import Game

game = Game()  # connects locally; reads ONIHARNESS_MCP_TOKEN when set
observation = game.observe()  # pauses, verifies pause, reads near camera
print(observation["map"]["text"])
print(observation["dupes"])

The game remains paused. observe(bounds=(x1, y1, x2, y2)) selects inclusive coordinates, up to 1600 cells. No game launch, resume or camera movement occurs. JSON, SSE and TOON responses are decoded; tool errors raise McpError. Connections accept HTTP loopback addresses only, with no proxies or redirects.

For a composed synchronous operation, @game.paused verifies pause before the body and again in finally, including when the body raises. It preserves the function's name, signature and return value. Async/generator work is rejected so it cannot escape the pause scope. This is not a bounded stepping API.

game.client.call_tool(name, arguments) exposes the installed tool catalog directly. This low-level API can write to the game and does not add pause protection; use the usual pause → observe → plan → act → short run → pause → verify loop.

More examples and development instructions: Python guide.

Original framework code uses AUL 1.0-draft.1, a custom license which is not OSI-approved. Dependencies and ONI retain their own terms. See LICENSE and LICENSING.md. Unofficial community project; not affiliated with Klei or Unity.

Metadata

Release files for oniharness 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for oniharness 0.2.0
File Size Uploaded Provenance
oniharness-0.2.0.tar.gz 104.3 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for oniharness 0.2.0
File Interpreter ABI Platform
oniharness-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 129.8 kB

Release files / oniharness-0.2.0.tar.gz

Download URL oniharness-0.2.0.tar.gz
Size 104.3 kB
Tags Source
SHA-256 checksum
How to use checksums
ce4a10d1ec83ecb903eee0b438c0dd1e1d782f9229309c9884e7f1b56207df16
BLAKE2b-256 checksum
How to use checksums
a91823ebf86d39f6e71cf0140d8570976e7153b605fe43717795bbc5d2630567
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Omarchy","version":"4.0.4","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Release files / oniharness-0.2.0-py3-none-any.whl

Download URL oniharness-0.2.0-py3-none-any.whl
Size 25.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7ea613ade1fdd89da19fa7316199c3f43e418f7cb9730c2fa26eea189f1bf8ad
BLAKE2b-256 checksum
How to use checksums
b9e0e2bf9fb604614e32b8268782ccd20e7bdaa9a04e8c1bc7c00afe62fd4203
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.0 {"installer":{"name":"uv","version":"0.13.0","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Omarchy","version":"4.0.4","id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

Security for oniharness 0.2.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page