Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
29cee20
feat(installer): validate onboarding and ship dimup release assets
TomCC7 Sep 10, 2026
c8348c3
feat(installer): create pinned SDK applications with shared activation
TomCC7 Sep 10, 2026
d7f90f2
feat(cli): diagnose SDK applications without loading the runtime
TomCC7 Sep 10, 2026
9e0bf01
test(installer): preserve setup logs when acceptance fails
TomCC7 Sep 10, 2026
54e6303
fix(installer): make repository bootstrap usable before release
TomCC7 Sep 10, 2026
8973edd
fix(installer): allow application creation on manually prepared platf…
TomCC7 Sep 10, 2026
72db54a
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
3e0a00e
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 Sep 10, 2026
8409a5c
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
6c066f4
docs(installer): deliver and explain manually prepared platform support
TomCC7 Sep 10, 2026
bc645bc
fix(ci): use LCM for Point-LIO acceptance and correct docs branding
TomCC7 Sep 10, 2026
308b5a5
test(cli): cover SDK diagnostics and subprocess failures
TomCC7 Sep 10, 2026
dc5cf8b
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
e0e357c
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 Sep 10, 2026
2849c32
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
3dca333
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
ef1371d
fix(installer): use managed Python for reproducible SDK environments
TomCC7 Sep 10, 2026
e987adf
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
60c6fa7
fix(cli): diagnose Python builds without SQLite extension support
TomCC7 Sep 10, 2026
f4053be
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
85c9cb9
fix(installer): ship managed-Python project creation in bootstrap
TomCC7 Sep 10, 2026
ae101ae
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 Sep 10, 2026
84ad423
feat(installer): present project creation as clear CLI stages
TomCC7 Sep 10, 2026
13977d6
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
dabaaaf
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
ce5cfb2
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 Sep 10, 2026
72cdfcf
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
b6ec6d9
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
c747e17
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
01ce4c9
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 Sep 10, 2026
c6442ce
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
6e816b7
test(installer): ship and verify the polished CLI transcript
TomCC7 Sep 10, 2026
54ecccd
Merge branch 'fix/sdk-native-builds' into feat/dimup-init
TomCC7 Sep 10, 2026
eb95543
Merge branch 'feat/dimup-init' into feat/dimos-doctor
TomCC7 Sep 10, 2026
f5ac245
Merge branch 'feat/dimos-doctor' into feat/dimup-release
TomCC7 Sep 10, 2026
15c315f
chore(installer): refresh bootstrap after review cleanup
TomCC7 Sep 10, 2026
fe0f492
refactor(installer): consolidate the complete application workflow
TomCC7 Sep 10, 2026
7fc4c11
chore(installer): pin bootstrap to consolidated application feature
TomCC7 Sep 10, 2026
a30fde0
refactor(installer): exercise source bootstrap in application CI
TomCC7 Sep 10, 2026
37d3fd2
docs(installer): lead with the current PR test journey
TomCC7 Sep 10, 2026
cd14dd5
Merge branch 'fix/sdk-native-builds' into feat/dimup-release
TomCC7 Sep 10, 2026
e2cb004
Merge branch 'fix/sdk-native-builds' into feat/dimup-release
TomCC7 Sep 10, 2026
e53f4ef
feat(dimup): clone and prepare contributor checkouts
TomCC7 Sep 10, 2026
f4bedf6
fix(dimup): avoid repeating explicit contributor commit
TomCC7 Sep 10, 2026
7d0843f
Merge branch 'fix/sdk-native-builds' into feat/dimup-release
TomCC7 Sep 10, 2026
2aa46e6
fix(dimup): keep Python onboarding independent of Deno
TomCC7 Sep 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 37 additions & 5 deletions .github/workflows/dimup.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,45 @@ jobs:
steps:
- uses: actions/checkout@v7
- uses: astral-sh/setup-uv@v10.0.1
- name: Install shells for configuration tests
run: sudo apt-get update && sudo apt-get install -y zsh fish
- name: Installer and SDK packaging tests
- name: Install shell test tools
run: sudo apt-get update && sudo apt-get install -y zsh fish direnv
- name: Installer, packaging, and diagnostic tests
env:
PYTHONPATH: .
run: uv run --project installer --with pytest --with filelock --with setuptools --with pybind11 pytest --noconftest -c installer/pyproject.toml installer/src tests/packaging dimos/core/test_native_sources.py
run: uv run --project installer --with pytest --with filelock --with setuptools --with pybind11 pytest --noconftest -c installer/pyproject.toml installer/src tests/packaging dimos/core/test_native_sources.py dimos/cli/test_doctor.py
- name: Type check dimup
env:
MYPYPATH: installer/src
run: uv run --project installer --with mypy mypy --strict --follow-imports=silent installer/src/dimup/cli.py installer/src/dimup/process.py installer/src/dimup/setup.py installer/src/dimup/shell.py
run: uv run --project installer --with mypy mypy --strict --follow-imports=silent installer/src/dimup/cli.py installer/src/dimup/project.py installer/src/dimup/process.py installer/src/dimup/setup.py installer/src/dimup/sdk.py installer/src/dimup/shell.py installer/src/dimup/development.py
journey:
needs: unit
strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04, ubuntu-24.04, macos-14]
runs-on: ${{ matrix.os }}
timeout-minutes: 120
steps:
- uses: actions/checkout@v7
- name: Bootstrap from source and prepare machine
env:
DIMUP_REF: ${{ github.event.pull_request.head.sha || github.sha }}
run: |
export PATH="$HOME/.local/bin:$HOME/.cargo/bin:/opt/homebrew/bin:$PATH"
bash installer/bootstrap.sh
export PATH="$(uv tool dir --bin):$PATH"
echo "$(uv tool dir --bin)" >> "$GITHUB_PATH"
echo "$HOME/.local/bin" >> "$GITHUB_PATH"
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
dimup setup
- name: Create applications, prepare contributors, and run
env:
SDK_REF: ${{ github.event.pull_request.head.sha || github.sha }}
run: python3 installer/run/acceptance --ref "$SDK_REF" --results "$RUNNER_TEMP/dimup-results" --contributor --native
- uses: actions/upload-artifact@v7
if: always()
with:
name: dimup-${{ matrix.os }}
path: |
${{ runner.temp }}/dimup-results/
~/.local/state/dimup/setup.log
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,6 @@ site/

# Optuna study store, written by the relocalization eval (see lidar/eval.md)
optuna.db

# Local installer validation artifacts
/.dimos/
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ We want people to use Dimensional, learn it, and help us build it. You do not ne
Browse [open issues labeled](https://github.com/dimensionalOS/dimos/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22) `good first issue`. These are scoped tasks that maintainers have marked as approachable for newcomers. Pick one, read the description, and comment if you want to work on it or need clarification. Maintainers are happy to point you in the right direction.

**Get set up.**
Follow [AGENTS.md](AGENTS.md) for install (`uv sync --extra all`), running blueprints in simulation or replay, and the test workflow (`uv run pytest`). Most changes can be developed and validated without a physical robot.
Follow the [contributor setup guide](docs/installation/installer.md#work-on-dimos-itself): prepare your machine with the curl bootstrap, then run `dimup dev dimos --ref feat/dimup-release` while testing this PR. It clones dimOS, installs the editable environment and development tools, and installs commit hooks. See [AGENTS.md](AGENTS.md) for running blueprints and the test workflow. Most changes can be developed and validated without a physical robot.

**This still applies to you.**
The [critical rule](#the-critical-rule) and [AI policy](AI_POLICY.md) apply to every outside contribution, including yours. Use AI tools if they help you learn the codebase, but understand what you submit. Link your PR to the issue you are working on.
Expand Down
63 changes: 25 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,55 +137,42 @@ Dimensional is agent native -- "vibecode" your robots in natural language and bu

# Installation

## Interactive Install
## Test a dimOS SDK application

```sh skip
curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/main/scripts/install.sh | bash
```

> See [`scripts/install.sh --help`](scripts/install.sh) for non-interactive and advanced options.

## Manual System Install

To set up your system dependencies, follow one of these guides:

- 🟩 [Ubuntu 22.04 / 24.04](docs/installation/ubuntu.md)
- 🟩 [NixOS / General Linux](docs/installation/nix.md)
- 🟧 [macOS](docs/installation/osx.md)

> Full system requirements, tested configs, and dependency tiers: [docs/requirements.md](docs/requirements.md)

## Python Install

### Quickstart
Test the current installer PR on Ubuntu 22.04/24.04 x86_64 or Apple Silicon macOS
14+. Use both branch overrides below until the changes merge:

```bash
uv venv --python "3.12"
source .venv/bin/activate
uv pip install 'dimos[base,unitree]'

# Replay a recorded quadruped session (no hardware needed)
# NOTE: First run will show a black rerun window while ~75 MB downloads from LFS
dimos --replay run unitree-go2
curl -fsSL https://raw.githubusercontent.com/dimensionalOS/dimos/feat/dimup-release/installer/bootstrap.sh \
| DIMUP_REF=feat/dimup-release bash
dimup init my-robot --ref feat/dimup-release
cd my-robot
source .dimos/activate.sh
dimos run my-robot.demo
```

```bash
# Install with simulation support
uv pip install 'dimos[base,unitree,sim]'
The bootstrap installs `dimup` and prepares the machine; follow its printed PATH
instruction before running `dimup init`. That command creates an
editable application pinned to the resolved SDK commit from the PR branch. Its two-module
example generates images and prints their dimensions, without hardware or datasets.
Edit `src/my_robot/demo.py`, run `pytest`, and rerun the blueprint.

# Run quadruped in MuJoCo simulation
dimos --simulation run unitree-go2
See the [installation guide](docs/installation/installer.md) for machine setup,
SDK revision selection, cloning applications, diagnostics, and optional direnv.

# Run humanoid in simulation
dimos --simulation run unitree-g1-sim
```
To work on dimOS itself after the bootstrap:

```bash
# Control a real robot (Unitree quadruped over WebRTC)
export ROBOT_IP=<YOUR_ROBOT_IP>
dimos run unitree-go2
dimup dev dimos --ref feat/dimup-release
cd dimos
source .dimos/activate.sh
dimos doctor
git switch -c feat/my-change
```

This prepares an editable contributor checkout with test/lint tools and commit
hooks. See the [contributor setup procedure](docs/installation/installer.md#work-on-dimos-itself).

# Featured Runfiles

| Run command | What it does |
Expand Down
179 changes: 179 additions & 0 deletions dimos/cli/doctor.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
# Copyright 2026 Dimensional Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Read-only diagnostics for a DimOS application or contributor checkout."""

import argparse
import json
from pathlib import Path
import shutil
import subprocess
import sys
from typing import Any

if sys.version_info >= (3, 11):
import tomllib
else:
import tomli as tomllib


def project_root(path: Path) -> Path:
for root in (path.resolve(), *path.resolve().parents):
manifest = root / "pyproject.toml"
if manifest.is_file():
config = tomllib.loads(manifest.read_text())
if "dimos" in config.get("tool", {}).get("uv", {}).get("sources", {}) or (
config.get("project", {}).get("name") == "dimos" and (root / "dimos").is_dir()
):
return root
raise ValueError(
"No DimOS project found. Run inside an application created by dimup init or a checkout prepared by dimup dev."
)


def probe(python: Path, script: str, *args: str, cwd: Path) -> tuple[bool, str]:
try:
result = subprocess.run(
[str(python), "-I", "-c", script, *args],
capture_output=True,
text=True,
timeout=45,
check=False,
cwd=cwd,
)
except (OSError, subprocess.TimeoutExpired) as error:
return False, str(error)
if result.returncode:
return False, (result.stderr or result.stdout).strip()[-1500:]
return True, result.stdout.strip()


METADATA_CHECK = """import importlib.metadata as m, json, sys
from pathlib import Path
app = m.distribution(sys.argv[1])
sdk = m.distribution("dimos")
print(json.dumps({
"editable": json.loads(app.read_text("direct_url.json") or "{}"),
"sdk": json.loads(sdk.read_text("direct_url.json") or "{}"),
"entries": [e.name for e in app.entry_points if e.group == "dimos.blueprints"],
"version": sdk.version,
"source": str(Path(__import__("dimos").__file__).resolve()),
}))
"""
LIBRARY_CHECK = """import ctypes
from ctypes.util import find_library
import numpy as np
import sqlite3, sqlite_vec
from turbojpeg import TurboJPEG
import zenoh, lcm
with sqlite3.connect(":memory:") as connection:
if not hasattr(connection, "enable_load_extension"):
raise RuntimeError(
"Python lacks SQLite extension loading. Recreate .venv with uv-managed Python: "
"uv venv --clear --managed-python --python 3.12 && uv sync --locked"
)
connection.enable_load_extension(True)
sqlite_vec.load(connection)
connection.enable_load_extension(False)
connection.execute("SELECT vec_version()").fetchone()
for name in ("portaudio", "sndfile"):
path = find_library(name)
if not path:
raise RuntimeError(f"Missing host library: {name}; run dimup setup")
ctypes.CDLL(path)
codec = TurboJPEG()
image = np.zeros((8, 8, 3), dtype=np.uint8)
assert codec.decode(codec.encode(image)).shape == image.shape
"""


def diagnose(root: Path) -> list[tuple[bool, str, str]]:
manifest = tomllib.loads((root / "pyproject.toml").read_text())
name = manifest["project"]["name"]
contributor = name == "dimos"
python = root / ".venv/bin/python"
results = [
(
Path(sys.prefix).resolve() == (root / ".venv").resolve(),
"Active environment",
"source .dimos/activate.sh selects this project's interpreter",
)
]
if not python.is_file():
return [*results, (False, "Application environment", "Run uv sync --locked")]
ok, detail = probe(python, METADATA_CHECK, name, cwd=root)
if ok:
metadata: dict[str, Any] = json.loads(detail)
app = metadata["editable"]
editable = app.get("dir_info", {}).get("editable") and app.get("url") == root.as_uri()
if contributor:
source = metadata.get("source")
results.append(
(
bool(editable) and source == str(root / "dimos/__init__.py"),
"Editable DimOS checkout",
f"Expected {root}; imported {source}. Run uv sync --locked if they differ",
)
)
else:
results.append(
(
bool(editable),
"Editable application",
"Run uv sync --locked to install this application",
)
)
results.append(
(
bool(metadata["entries"]),
"Blueprint registration",
", ".join(metadata["entries"]) or "Run uv sync to refresh entry points",
)
)
expected = manifest["tool"]["uv"]["sources"]["dimos"]["rev"]
commit = metadata["sdk"].get("vcs_info", {}).get("commit_id")
results.append(
(
commit == expected,
"SDK revision",
f"Expected {expected}; installed {commit}. Run uv sync --locked if they differ",
)
)
else:
results.append((False, "Installed metadata", f"{detail}\nRun uv sync --locked"))
for tool in ("uv", "cargo", "nix", "git"):
found = shutil.which(tool)
results.append(
(found is not None, tool, found or "Run dimup setup, then activate the project")
)
ok, detail = probe(python, LIBRARY_CHECK, cwd=root)
results.append((ok, "Native libraries and image codec", detail or "Image round trip passed"))
return results


def main(argv: list[str] | None = None) -> int:
parser = argparse.ArgumentParser(prog="dimos doctor", description=__doc__)
parser.add_argument("--project-dir", type=Path, default=Path.cwd())
args = parser.parse_args(argv)
try:
results = diagnose(project_root(args.project_dir))
except (OSError, ValueError, KeyError, TypeError) as error:
results = [(False, "Application", str(error))]
for ok, label, detail in results:
print(f"{'PASS' if ok else 'FAIL'} {label}: {detail}")
return int(any(not ok for ok, _, _ in results))


if __name__ == "__main__":
raise SystemExit(main())
24 changes: 24 additions & 0 deletions dimos/cli/entrypoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Copyright 2026 Dimensional Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Keep diagnostics accessible before importing the robotics runtime."""

from importlib import import_module
import sys


def cli_main() -> None:

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we need this file?

if sys.argv[1:2] == ["doctor"]:
raise SystemExit(import_module("dimos.cli.doctor").main(sys.argv[2:]))
import_module("dimos.cli.dimos").cli_main()
Loading
Loading