Skip to content

houdini_package

houdini_package

Emit the Houdini package file that points at the installed plugin.

The plugin now ships inside this package, so its path depends on which Python you installed into. That path is easy to get wrong and easy to break: recreate a venv, switch to uv or pipx, move from 3.11 to 3.12, and a hand-typed path silently stops resolving. Houdini says nothing when a package path is missing, it just skips the file, which is what made issue #11 so confusing.

So nobody should type it. This resolves the path from the running interpreter and prints, or writes, the JSON.

fxhoudinimcp houdini-package                 # print the JSON and where to put it
fxhoudinimcp houdini-package --write DIR     # write it into DIR

The destination is not guessed. Houdini's preference directory is genuinely ambiguous on Windows, where OneDrive's Documents redirection means a desktop-launched Houdini and a shell-launched one can disagree, so candidates are listed and the choice is left to the operator.

Functions:

Name Description
candidate_package_dirs

Plausible Houdini packages directories that already exist.

existing_packages

Find already-installed package files and the plugin path each points at.

package_json

The Houdini package file contents pointing at path.

plugin_path

Absolute path to the Houdini plugin directory.

write_package

Write fxhoudinimcp.json into destination and return the file written.

Functions:

candidate_package_dirs

candidate_package_dirs() -> list[Path]

Plausible Houdini packages directories that already exist.

Only reports directories present on disk, and never picks one: on Windows with OneDrive's Documents redirection, a desktop-launched Houdini and a shell-launched one resolve different preference directories, and choosing wrongly reproduces the silent no-op this command exists to prevent.

existing_packages

existing_packages(exclude: Path | None = None) -> list[tuple[Path, str]]

Find already-installed package files and the plugin path each points at.

Two of these is a real hazard rather than a tidiness issue. Houdini processes every packages directory and lets the last one win, so a leftover file pointing at an old clone can silently override a fresh install. Houdini says so only under HOUDINI_PACKAGE_VERBOSE:

WARNING: var FXHOUDINIMCP overwritten with ...

Reported so the operator can delete the stale one.

package_json

package_json(path: Path | None = None) -> str

The Houdini package file contents pointing at path.

Forward slashes on every platform: Houdini accepts them, and backslashes in JSON need escaping, which is a common way to break this file by hand.

plugin_path

plugin_path() -> Path

Absolute path to the Houdini plugin directory.

Two layouts are valid. An installed wheel relocates the plugin to fxhoudinimcp/houdini; a source tree or editable install keeps it at the repository root. Preferring the packaged location means an installed user never picks up a stale clone that happens to sit nearby, while a contributor working from a checkout still gets a working command.

write_package

write_package(destination: Path, path: Path | None = None) -> Path

Write fxhoudinimcp.json into destination and return the file written.

Shared with fxhoudinimcp install so there is one place that knows the encoding rules. utf-8 without a BOM: Houdini's JSON parser rejects a BOM and skips the whole package silently, which is the trap behind issue #11.

Raises NotADirectoryError if destination does not exist, rather than creating it: a typo'd path would otherwise produce a package file in a directory Houdini never reads, and Houdini reports nothing when that happens.