CLI Reference
ulis <command> [options]
Running ulis with no command prints help. All commands exit non-zero on error with a message on stderr.
ulis init
Scaffold a new .ulis/ source tree with empty folders, template YAML files, and schema-backed headers.
ulis init [-g | --global]| Flag | Effect |
|---|---|
-g, --global | Scaffold ~/.ulis/ instead of ./.ulis/. No .gitignore is written in this mode. |
Project mode:
- Creates
./.ulis/withconfig.yaml,mcp.yaml,permissions.yaml,skills.yaml,extensions.yaml, and emptyagents/,skills/,commands/,raw/subfolders. - Reads the project name from
./package.json(falls back to the directory name). - Appends
/.ulis/generated/to.gitignore(creating the file if missing). - Prints a hint suggesting you also gitignore
./.claude/,./.cursor/,./.codex/,./.opencode/, and./.forge/if you don't want to commit generated configs.
Fails if .ulis/ (or ~/.ulis/ in global mode) already exists.
ulis build
Parse, validate, and generate configs into <source>/generated/<platform>/ without installing anything.
ulis build [-g | --global] [--source <path>] [--target <platforms>] [--preset <names>]| Flag | Effect |
|---|---|
-g, --global | Read from ~/.ulis/ instead of ./.ulis/. |
--source <path> | Explicit source path. Takes precedence over --global. |
--target <platforms> | Comma-separated subset of claude,codex,cursor,opencode,forgecode. Default: all. |
--preset <names> | Apply preset(s) before the base source (comma-separated). Resolved from ~/.ulis/presets/<name>/ first, then bundled presets shipped with the CLI. |
Output is always written under <source>/generated/<platform>/. Existing contents there are cleared before each build.
ulis install
Run build and then deploy the generated configs onto the target platform directories.
ulis install [-g | --global] [--source <path>] [--target <platforms>]
[-y | --yes] [--no-rebuild] [--backup] [--preset <names>]
[--link-mode <copy|symlink>] [--runner <npx|bunx>] [--no-extensions]| Flag | Effect |
|---|---|
-g, --global | Read ~/.ulis/ and write to ~/.claude/, ~/.codex/, ~/.cursor/, ~/.config/opencode/ (Windows: %USERPROFILE%\.config\opencode\), and ~/.forge/. |
--source <path> | Override source (still writes to CWD or home depending on --global). |
--target <platforms> | Only build/install the listed platforms. |
-y, --yes | Skip the "about to overwrite" confirmation prompt. |
--no-rebuild | Don't rebuild — install whatever is already under <source>/generated/. |
--backup | Copy each existing platform dir to <dir>.backup.YYYYMMDD_HHMMSS before writing. |
--preset <names> | Same resolution as ulis build --preset (user-global directory, then bundled). |
--link-mode <mode> | Local skill install mode. copy keeps generated skill copies in each platform config. symlink delegates eligible local skills to skills@latest. |
--runner <name> | Package runner used for extensions.yaml entries. npx or bunx. Overrides runner in config.yaml. Default: auto-detect (bunx if present). |
--no-extensions | Skip running entries from extensions.yaml. Useful in CI where network installs are not desired. |
Preset resolution: Each name maps to a directory. ULIS checks ~/.ulis/presets/<name>/ first; if that folder is missing, it uses the matching bundled preset next to the CLI (dist/presets/ when installed). A preset in your home tree with the same folder name shadows the bundled one. Multiple --preset values merge left to right, then the base source (from --source, ./.ulis/, or ~/.ulis/) is applied last — the base wins on conflicts. Interactive runs prompt to continue when a name is missing; with --yes, missing presets fail immediately.
Install strategy per platform:
| Platform | Managed dirs (replaced) | Preserved native config |
|---|---|---|
| Claude | agents/, commands/, rules/, hooks/, … | settings.json hooks, UI/plugin settings; .claude.json mcpServers |
| OpenCode | target dir contents | opencode.json mcp |
| Codex | target dir contents | config.toml projects, hooks, mcp_servers, tui, notice, features |
| Cursor | agents/ (.mdc files) | mcp.json mcpServers |
| ForgeCode | .forge/agents, .forge/skills, AGENTS.md | .forge/.mcp.json mcpServers, .forge.toml |
Install preserves only the allowlisted native config values and files above. Generated output wins at the same config path, and raw fragments win through the generated output because raw is merged during build. Existing non-allowlisted native config values are removed. If --backup is set, backups are created before parsing preserved native config.
--link-mode symlink affects eligible local skills only. ULIS stages native-safe generated skills, then runs npx skills@latest add <staged-dir> with the selected project/global scope and target agents. The skills library manages .agents/skills/, symlinks on macOS/Linux, junctions on Windows, and copy fallback if linking fails. After a successful linked install, ULIS removes duplicate generated native skill copies; failed linked installs keep the generated copies as fallback. Skills with platform-specific skill config or extra generated files are copied by ULIS.
ulis tui
Launch the interactive terminal dashboard. Use it to choose a source, select presets and platforms, validate without writing files, build generated outputs, or install with an explicit destination review.
ulis tuiThe TUI supports project .ulis/, global ~/.ulis/, and custom source paths. Install destinations are explicit: project-local configs or home-level configs. If a project or global source is missing, the TUI can initialize it before continuing. Installs require a review screen where backup, rebuild, and linked local skill installs can be toggled before execution.
Keyboard controls:
j/kor arrow keys move selection.Enterconfirms selections and runs actions.xorSpacetoggles checkbox-style options (destination, presets, platforms, install options).Backspacegoes back to the previous screen.qorCtrl+Cexits from non-input screens.
ulis preset
List presets from both ~/.ulis/presets/ and the bundled preset set. User presets are preferred when the same folder name exists in both places.
ulis preset [--list]
ulis preset list-l / --list is accepted. The default action is list. Each line shows the directory name (what you pass to --preset), a user or bundled label, optional name / description from preset.yaml, and the display title when it differs from the folder name.
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success. |
| 1 | Source missing, validation error, user declined prompt, or I/O failure. |
All errors print a single human-readable line on stderr before exiting.
Examples
Scaffold a project and install for Claude + Cursor only:
ulis init
# edit .ulis/agents/*.md, .ulis/mcp.yaml, etc.
ulis install --target claude,cursor --yesRebuild global configs after editing ~/.ulis/:
ulis install --global --yes --backupDry-run against a fixture without touching home:
ulis build --source ./exampleReinstall from an existing build without regenerating:
ulis install --no-rebuild --yesBuild with reusable presets:
ulis preset list
ulis build --preset team-default,typescript
ulis install --preset team-default --yes