Skip to main content

Directory Structure

This page explains how to organize files in a Desktop Homunculus MOD. A MOD can be as simple as three files -- the only hard requirement is a package.json with the homunculus field. Everything else depends on what your MOD does.

Minimal MOD

A character MOD that spawns a VRM model needs just a package config, a service script, and the model file:

my-character/
├── package.json # Package config with homunculus field
├── index.ts # Service (runs on app launch)
└── assets/
└── MyModel.vrm # VRM character model

package.json -- Must include "type": "module" and the "homunculus" field declaring your service script and assets. See Package Configuration for details on every field.

index.ts -- The service script specified by "homunculus.service". The engine runs it automatically via tsx, so you can write TypeScript directly without a build step. This script typically spawns your character and sets up behaviors.

assets/ -- Convention for storing binary assets (VRM models, animations, sounds, images). The directory name is flexible -- the actual file paths are declared in package.json -- but assets/ is the standard across official MODs.

tip

This is all you need for a working MOD. Install it with hmcs mod install <path-to-mod> and your character appears on the desktop.

MOD with UI

A MOD that provides a settings panel or other UI adds a React app and on-demand bin commands:

my-settings-mod/
├── package.json # Declares assets, menus, and bin commands
├── commands/
│ └── open-ui.ts # Bin command script (invoked via HTTP API)
└── ui/
├── index.html # Vite entry point
├── vite.config.ts # Vite build config
├── tsconfig.json # TypeScript config for the UI app
└── src/
├── main.tsx # React entry point
├── App.tsx # Root component
├── index.css # Styles (Tailwind)
└── components/ # UI components

commands/

On-demand scripts exposed via the "bin" field in package.json. These run only when explicitly called through the HTTP API (POST /commands/execute). The conventional directory name is commands/ or bin/.

ui/

A React + Vite app that renders inside a WebView. The source lives in ui/src/ and builds to ui/dist/. The built ui/dist/index.html is declared as an html asset in package.json -- the engine loads it when opening the WebView.

UI apps typically import @hmcs/ui for shared components and use Tailwind for styling. This is the only part of a MOD that requires a build step (pnpm build from the ui/ directory).

Note that ui/dist/ is a build artifact and is not shown in the tree above. It is generated by running pnpm build in the ui/ directory.

info

This example has no index.ts at the root -- it uses only on-demand commands and a UI panel. A MOD can also combine both patterns: a service, a UI app, and bin commands in the same package.

File Reference

File / DirectoryPurposeRequired
package.jsonPackage config with homunculus fieldYes
index.tsService (runs on app launch)No
assets/Binary assets (VRM, VRMA, sounds, images)No
commands/ or bin/On-demand bin command scriptsNo
ui/WebView UI app (React + Vite)No
ui/dist/Built UI output (declared as html asset)Only if ui/ exists
lib/Shared utility code used by scriptsNo

Conventions

  • Store binary assets in assets/. The directory name is a convention, not a requirement -- actual file paths are declared in package.json.
  • Place bin command scripts in commands/ or bin/. Both are common across official MODs.
  • UI apps live in ui/ with build output in ui/dist/.
  • Shared helper code goes in lib/.
  • The only required file is package.json. Everything else depends on what your MOD does.

Next Steps