Host-side runtime for ChuMicro project workspaces — config merge, secrets resolution, deploy orchestration, command dispatch.
Project description
chumicro-workspace
Host CLI for ChuMicro project workspaces — onboard a board, write app code, deploy to one or many targets, watch the REPL.
Wraps chumicro-deploy and chumicro-repl with the workspace-shaped pieces those packages don't own: a deploy-time config-merge pipeline (gitignored secrets.toml + projects/*/project_config.toml → runtime_config.msgpack), a CLI that reads workspace.yml, three-zone devices.yml round-trip, board-state onboarding, firmware URL derivation, and the boot-shim layout that lets a single board host one project without you writing a code.py.
Part of the ChuMicro family — small, focused Python libraries for microcontrollers and laptops. Browse all workbench tools. This is a workbench tool — runs on your laptop, not on the board. The on-device side is
chumicro-config, which reads the msgpack this package writes.
Install
pip install chumicro-workspace
chumicro-deploy (and its pyserial / mpremote deps) plus msgpack and ruamel.yaml come along. The starter workspace lives at ChuMicro/ChuMicro-Workspace-Template — typical bootstrap is git clone it (or click "Use this template" on GitHub) then run python run.py setup, which creates a venv and installs this package.
Experimental (pre-release) versions and channel switching
Pre-release builds publish automatically when the package version is bumped.
pip install chumicro-workspace-experimental
Quick example
The workspace template ships a run.py shim that forwards to chumicro-workspace — typical day-zero is:
# Inside a freshly cloned workspace:
python run.py setup # one-time bootstrap
python run.py bootstrap --port /dev/cu.usbmodem1101 --device-id back-porch
# (the wizard probes the runtime, registers the device, deploys
# the built-in demo payload — pass --no-demo to skip the demo step.)
# Then iterate:
python run.py new my_project # scaffold from projects/_template/
python run.py deploy my_project # ship + run on the active device
python run.py deploy my_project --tail 30 # ship + run, then tail for 30 s
python run.py repl # interactive REPL on the active device
How config flows from your edits to the device
The runtime config a project receives at boot is the deep-merge of two host-side sources, both sharing the same section-namespaced shape:
secrets.toml ──────────────────► projects/<name>/project_config.toml
(gitignored — workspace-wide (per-project knobs — sample period,
credentials + device defaults mqtt topic, sensor pins; gitignored
in one place; deep-merge when scaffolded by `new`)
loser to per-project)
│
▼
merge_configs ← chumicro_workspace.merge
│ (deep per-key merge:
▼ higher-precedence layer
wins at any key)
packb (msgpack) ← chumicro_workspace.writer
│ (use_single_float=True so
▼ CircuitPython's native
/runtime_config.msgpack on device msgpack module accepts it)
│
▼
chumicro_config.runtime ← READS the msgpack on the device
chumicro-workspace dump-config <project> prints the merged dict your project would receive without actually deploying — useful when debugging which layer a key landed in.
What's included
CLI subcommands
chumicro-workspace <subcommand> (or python run.py <subcommand> from a workspace).
| Group | Commands |
|---|---|
| Bootstrap / setup | setup, update, bootstrap (workspaces are created by cloning the template repo, not a command) |
| Authoring | new <path> (project), new --library <name> (chumicro-style library) |
| Config | dump-config <project>, config-validate <project> |
| Devices | add-device, probe, discover, devices, remove-device, reset-device, rename --device |
| Deploy / run | deploy <project> [--tail SECONDS], deploy-example, demo, repl [--tail SECONDS], projects [--flat] |
| Libraries | library list|add|update|remove|forget|switch-channel |
| Health | status, doctor (also runs as a fast pre-deploy gate; deploy --skip-health-check opts out) |
| Quality | test, lint, preflight (chains lint + test; respects workspace.yml's quality: block) |
| Firmware | install-firmware, upgrade-firmware, reset-board |
libs/ vs libraries/ — when to use each
Both hold code your projects can import. Pick by weight:
| Want to ship… | Drop it under | Imports look like | Notes |
|---|---|---|---|
| A 50-line helper your projects share | libs/foo.py |
from libs.foo import bar |
No tests, no version, no scaffolding. |
| A full chumicro-style library you might publish someday | libraries/<name>/ (via new --library) |
import <name> |
Gets src/, tests/, docs/, examples/, pyproject.toml, VERSION — the publishable-library layout. |
| A third-party package | packages/ (via sync) |
import <name> |
Gitignored mirror cache. |
The import-graph search path resolves explicit library_sources: overrides → libs/ → every libraries/<name>/src/ (auto-discovered) → packages/.
Boot-shim layout
When the project ships app.py with a run() callable and no code.py / main.py of its own, deploy auto-detects boot-shim mode and ships this on-device shape:
/code.py # synthesised three-line shim: from app import run; run()
# (or /main.py on MicroPython — only the runtime-matching file lands)
/app.py # your code — def run(): ...
/runtime_config.msgpack # merged config (see pipeline above)
/lib/<chumicro_libs>/... # libraries the project imports (when --import-graph composes)
Two responsibilities, one synthesised shim file: deploy owns /code.py (or /main.py) at the device root and the user owns everything else. One project per board — switch by redeploying.
When the project ships its own code.py / main.py, plain mode kicks in and deploy ships project files at the device root verbatim, no shim synthesis. The runtime-matching filename declares intent: deploying a code.py-only project to a MicroPython board (or main.py-only to CircuitPython) surfaces as a clear user error before any bytes leave the host.
Where this fits
Depends on chumicro-deploy (transport) and chumicro-repl (lazily loaded for repl tail/interactive mode and deploy --tail). Top-level umbrella CLI — most users reach for chumicro-workspace, not the lower-level tools directly. The on-device side is chumicro-config, which reads the msgpack this package writes.
Public Python API
from chumicro_workspace import (
# Config merge
build_runtime_config, compose_runtime_config, merge_configs,
read_workspace_yaml, read_project_config,
write_runtime_config, WorkspaceConfigError,
read_workspace_yml_template,
# Deploy sources
WithRuntimeConfig, project_directory_source,
project_boot_source, project_import_graph_source,
# devices.yml three-zone round-trip
add_device, update_device_address, update_device_hardware,
rename_device, set_runtime_default, load_devices, dump_devices,
# Onboarding
BoardState, OnboardingDiagnosis, detect_board_state, find_uf2_drive,
# Firmware URL derivation
derive_firmware_url, latest_circuitpython_url, latest_micropython_url,
list_circuitpython_versions, list_micropython_builds,
micropython_board_for_machine, UnresolvedFirmwareError,
# Import-graph
build_search_paths, read_library_sources,
# Per-project → per-device mapping
read_deploy_targets,
# Constants
RUNTIME_CONFIG_DEVICE_PATH, GENERATED_DIRNAME,
BOOT_MODULE_DEVICE_PATH, PROJECTS_PACKAGE_INIT_DEVICE_PATH,
SHIM_ENTRYPOINT_SOURCE,
)
Plus chumicro_workspace.workspace.WorkspaceLayout, chumicro_workspace.health.*, chumicro_workspace.recovery.*, chumicro_workspace.scaffold.*, and chumicro_workspace.quality.* for the workspace-ecosystem add-ons.
Companions
| Workbench tool | Why you'd use it alongside |
|---|---|
chumicro-deploy |
Lower-level transport + flashing. Workspace composes on top |
chumicro-repl |
Interactive + tail serial REPL |
chumicro-pytest-device |
Run tests on real boards via pytest |
Examples
This package is a CLI tool — there's no "use it in your code" example shape that doesn't just mirror a CLI subcommand. See the user guide for end-to-end walkthroughs (config pipeline, deploy modes, library scaffolding, board onboarding) and chumicro-workspace --help for the full command surface.
The Python API surface (the from chumicro_workspace import ... block above) exists so chumicro-deploy, the workspace template's run.py shim, and the chumicro-workspace CLI itself can compose against it — not as a "build your own workspace tool" surface. If you find yourself reaching for it, the CLI probably already exposes what you want; file an issue if it doesn't.
Contributing
Working on chumicro-workspace itself? Clone the mono-repo if you haven't already — the rest of the workflow assumes you're inside that workspace.
pip install -e .[test]
pytest tests/ # host-side tests
pytest functional_tests/ # on-device tests (needs a board registered in devices.yml)
Register a board before running functional tests: chumicro-workspace add-device <id> --address <port>.
Docs
📖 Stable docs · Experimental docs
Find this library
- PyPI: chumicro-workspace
- Source: workbench/workspace
- Workspace template:
ChuMicro/ChuMicro-Workspace-Template
License
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file chumicro_workspace-0.50.1.tar.gz.
File metadata
- Download URL: chumicro_workspace-0.50.1.tar.gz
- Upload date:
- Size: 168.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e284eb9108e22bf8293d2e9f691100a581a9f1923c917b8edd5b31648a24d23
|
|
| MD5 |
f85be25a11d442e571fee2e790e2b8da
|
|
| BLAKE2b-256 |
4f2d04692e01856ee5c5b724af709918f2c09a6c69040ced634b7d7a11861a34
|
Provenance
The following attestation bundles were made for chumicro_workspace-0.50.1.tar.gz:
Publisher:
promote.yml on ChuMicro/ChuMicro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chumicro_workspace-0.50.1.tar.gz -
Subject digest:
9e284eb9108e22bf8293d2e9f691100a581a9f1923c917b8edd5b31648a24d23 - Sigstore transparency entry: 2200863648
- Sigstore integration time:
-
Permalink:
ChuMicro/ChuMicro@f0371ee3184710a808c548acf3b1a9391dcf072e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChuMicro
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
promote.yml@f0371ee3184710a808c548acf3b1a9391dcf072e -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file chumicro_workspace-0.50.1-py3-none-any.whl.
File metadata
- Download URL: chumicro_workspace-0.50.1-py3-none-any.whl
- Upload date:
- Size: 209.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
040391e85414cfcb37f2c42d50b22b31b4f078c44a9d0b1c7876763f4f9cde84
|
|
| MD5 |
00096b52e433135203e8ef2b09e9d391
|
|
| BLAKE2b-256 |
e7682504dad3cb8c3b650be8fbbef4ba60673d7272f48180351d9682dd29ff71
|
Provenance
The following attestation bundles were made for chumicro_workspace-0.50.1-py3-none-any.whl:
Publisher:
promote.yml on ChuMicro/ChuMicro
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
chumicro_workspace-0.50.1-py3-none-any.whl -
Subject digest:
040391e85414cfcb37f2c42d50b22b31b4f078c44a9d0b1c7876763f4f9cde84 - Sigstore transparency entry: 2200863659
- Sigstore integration time:
-
Permalink:
ChuMicro/ChuMicro@f0371ee3184710a808c548acf3b1a9391dcf072e -
Branch / Tag:
refs/heads/main - Owner: https://github.com/ChuMicro
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
promote.yml@f0371ee3184710a808c548acf3b1a9391dcf072e -
Trigger Event:
workflow_dispatch
-
Statement type: