Commands, package names, and image names on this page come from the open-source project that Mibyan Desktop is built on, and can differ from the Mibyan Desktop installer. For the supported Mibyan install and update path, see Install and update.
Contribution Priorities
We value contributions in this order:- Bug fixes — crashes, incorrect behavior, data loss
- Cross-platform compatibility — macOS, different Linux distros, WSL2
- Security hardening — shell injection, prompt injection, path traversal
- Performance and robustness — retry logic, error handling, graceful degradation
- New skills — broadly useful ones (see Creating Skills)
- New tools — rarely needed; most capabilities should be skills
- Documentation — fixes, clarifications, new examples
Common contribution paths
- Building a custom/local tool without modifying Mibyan core? Start with Build a Mibyan Plugin
- Building a new built-in core tool for Mibyan itself? Start with Adding Tools
- Building a new skill? Start with Creating Skills
- Building a new inference provider? Start with Adding Providers
Development Setup
Prerequisites
PM developer environment
Use the PM developer workflow for preparation, activation, everyday commands, dependency changes, and test environments. Select your development home before setup so experimental code does not migrate production data. Activate from the repository root in each new shell. Activation prepares the checkout through PM and syncs stale dependencies. Bash:mibyan for this checkout. Activation defines it as a function for this
worktree, so it hides a global mibyan alias and refuses outside the worktree.
PM activation syncs tools and Python dependencies before adding them to the shell. It does
not install JS workspaces or rewrite launchers and shell configuration. deactivate restores the prior shell environment and removes the function.
Manual development and test environment
Use the PM developer workflow to prepare Python 3.14 first. Run these commands from that checkout with its prepared Python. Keep the same developmentmibyan_HOME. PM must be able to start before it can build another
environment. On Windows, initialize the native C++ build environment for your
architecture before building source dependencies.
Build an independent interpreter for tests and editor tools:
test group includes native launcher test
dependencies and does not enter the application runtime. If tests require
another declared feature, add its --extra.
The output must not exist, even as an empty directory or symlink. To regenerate
it after a dependency change, stop its processes and intentionally remove only
that disposable environment first. PM does not delete an existing destination.
Do not run raw pip or uv commands to change a PM-built environment.
To keep the test environment outside the checkout, replace .venv with a fresh absolute
path. Set mibyan_PYTHON to that environment’s interpreter:
- POSIX:
export mibyan_PYTHON="/absolute/path/to/mibyan-dev/bin/python" - PowerShell:
$env:mibyan_PYTHON = 'C:\absolute\path\to\mibyan-dev\Scripts\python.exe'
.venv automatically. It clears
PYTHONPATH, so pytest must be installed in the interpreter’s own environment.
This test environment does not replace PM’s application selection or tool
store. Do not point a bundled app at it or install into an MSIX payload.
For an isolated development instance, select a disposable mibyan_HOME before
starting the source command. Use mibyan setup to configure it rather
than copying production credentials into the checkout.
JavaScript workspaces and website
From the repository root, runnpm ci for the desktop, TUI, dashboard, and
shared JS workspaces. The website is separate:
package.json engines.
Native desktop dependencies can also require the platform build toolchain.
Logos and icons are generated from assets/nous-girl-*.svg and
assets/backgrounds/. node scripts/generate-icons.mjs renders them with the
Mibyan runtime Python (mibyan_PYTHON, else python on PATH): Pillow and
resvg-py are core dependencies. Do not commit generated PNG/ICO/ICNS outputs.
Run tests
Use the canonical runner on every host:.venv or venv
contains pytest, the runner accepts the explicit mibyan_PYTHON above. It
clears credentials, isolates mibyan_HOME, and runs each test file in a separate
subprocess through scripts/run_tests_parallel.py. It does not use xdist.
When tests/conftest.py redirects a production mibyan_HOME to a temporary
session home, it sets the internal mibyan_TEST_SANDBOX_HOME marker. This lets
re-imported test fixtures recognize their own sandbox instead of flagging it as
real-home I/O. Do not set this marker yourself; set mibyan_HOME for a
disposable development home and let the test runner isolate it.
Run the relevant JS workspace checks for JS changes. Native install/update
E2E runs on disposable CI hosts, never against the developer’s live app.
See Package management for PM commands and runtime ownership.
Code Style
- PEP 8 with practical exceptions (no strict line length enforcement)
- Comments: Only when explaining non-obvious intent, trade-offs, or API quirks
- Error handling: Catch specific exceptions. Use
logger.warning()/logger.error()withexc_info=Truefor unexpected errors - Cross-platform: Never assume Unix (see below)
- Profile-safe paths: Never hardcode
~/.mibyan— useget_mibyan_home()frommibyan_constantsfor code paths anddisplay_mibyan_home()for user-facing messages. See AGENTS.md for full rules.
Cross-Platform Compatibility
See Platform Support. Native Windows uses Git Bash (from Git for Windows) for shell commands. The dashboard uses POSIX PTYs on Unix and thepywinpty/ConPTY bridge on Windows. Availability depends on that host’s native dependency support. If you’re doing Windows-heavy dev, run the Windows-footgun lint (scripts/check-windows-footguns.py) before pushing.
When contributing code, keep these rules in mind:
- Don’t add unguarded
signal.SIGKILLreferences. It’s not defined on Windows. Either route throughgateway.status.terminate_pid(pid, force=True)(the centralized primitive that doestaskkill /T /Fon Windows and SIGKILL on POSIX), or fall back withgetattr(signal, "SIGKILL", signal.SIGTERM). - Use
psutil.pid_exists()for process liveness. Do not useos.kill(pid, 0)on Windows; it is not a safe probe. - Don’t force the terminal to POSIX semantics.
os.setsid,os.killpg,os.getpgid,os.forkall raise on Windows — gate them withif sys.platform != "win32":orif os.name != "nt":. - Use explicit text encodings. User-authored UTF-8 reads use
utf-8-sigto accept a leading BOM. Writes useutf-8without adding a BOM. - Use
pathlib.Path/os.path.join— never manually concat with/. This matters less for strings the OS gives us back and more for strings we construct to hand to subprocesses.
1. File encoding
Some environments may save.env files in non-UTF-8 encodings:
2. Process management
os.setsid(), os.killpg(), and signal handling differ across platforms:
3. Path separators
Usepathlib.Path instead of string concatenation with /.
Security Considerations
Mibyan has terminal access. Security matters.Existing Protections
Contributing Security-Sensitive Code
- Always use
shlex.quote()when interpolating user input into shell commands - Resolve symlinks with
os.path.realpath()before access control checks - Don’t log secrets
- Catch broad exceptions around tool execution
- Test on all platforms if your change touches file paths or processes
Pull Request Process
Branch Naming
Before Submitting
- Run tests:
scripts/run_tests.shfor CI-parity. Use directpython -m pytest ...only when the wrapper is unavailable or you are intentionally debugging outside the wrapper. - Test manually: Run
mibyanand exercise the code path you changed - Check cross-platform impact: Consider macOS, Linux, WSL2, and native Windows. If you touch file I/O, process management, terminal handling, subprocesses, or signals, run
scripts/check-windows-footguns.py. - Keep PRs focused: One logical change per PR
PR Description
Include:- What changed and why
- How to test it
- What platforms you tested on
- Reference any related issues
Commit Messages
We use Conventional Commits:
Scopes:
cli, gateway, tools, skills, agent, install, whatsapp, security
Examples:
Repo-local review checklists: .agents/checks/*.md
Projects built on (or reviewed by) Mibyan can keep reviewer checklists inside the repository under .agents/checks/. Each file is a focused, plain-markdown checklist that an agent loads before reviewing a change touching the matching area:
- One concern per file, named after the concern. Small files get read in full; a monolithic
checklist.mdgets skimmed. - Write checks as verifiable actions (“run X and confirm Y”), not aspirations (“code should be secure”).
- State the trigger at the top — which paths or change types the checklist applies to — so an agent (or human) can skip irrelevant ones cheaply.
- Keep them in version control next to the code they guard: they evolve with the codebase, and a PR that changes the rules changes the checklist in the same diff.
.agents/checks/, tell it (or teach it via a skill) to read the relevant checklists first and report against them. This gives review agents the project-specific bar that generic review prompts miss.
Reporting Issues
- Use GitHub Issues
- Include: OS, Python version, Mibyan version (
mibyan --version), full error traceback - Include steps to reproduce
- Check existing issues before creating duplicates
- For security vulnerabilities, please report privately
Community
- Discord: discord.gg/NousResearch
- GitHub Discussions: For design proposals and architecture discussions
- Skills Hub: Upload specialized skills and share with the community

