/ documentation

Paths

Where the CLI writes skills and plugins: destinations by tool, Windows format, MALETA_CLI_HOME, the shared directory and temporary directories.

This page lists every path touched by maleta install and maleta sync. They are derived at runtime from --tool (or targetTool) and MALETA_CLI_HOME.

#Destination by tool

Destination for each skill, by tool
--toolResolved destination
claude~/.claude/skills/<skill.name>/
codex~/.agents/skills/<skill.name>/
agents~/.agents/skills/<skill.name>/
allBoth directories above. codex and agents collapse to the same path, so all produces exactly two distinct destinations.

<skill.name> is the skill's declared name, not the source repository name. A name is accepted only if it matches [A-Za-z0-9._-]+, is not exactly . or exactly .., and does not contain .. anywhere; on Windows, names ending in a period or space and reserved device names are also rejected (CON, PRN, AUX, NUL, COM1–COM9, LPT1–LPT9).

#How ~ is resolved

The ~ in the paths above is MALETA_CLI_HOME when the variable is set and non-empty; otherwise, it is the user's home directory returned by os.homedir(). The value is resolved by path.resolve, so a relative path is interpreted from the process cwd.

Unix format
text
~/.claude/skills/<skill.name>/
~/.agents/skills/<skill.name>/
Windows format
text
C:\Users\<usuário>\.claude\skills\<skill.name>\
C:\Users\<usuário>\.agents\skills\<skill.name>\

#Shared directory

When the plan contains at least one builtin skill, the shared directory from the local assets is automatically added to every destination with the label builtin:shared. It is materialized before the other actions and occupies <destino>/shared/. If a selected skill is named shared, the plan fails with target directory collision 'shared' between <prev> and builtin:shared.

  • With --tool all, shared is written once to ~/.claude/skills/shared/ and once to ~/.agents/skills/shared/.
  • If the shared directory does not exist in the local assets, no action is generated and nothing is announced.

#Temporary directories during application

Writes happen in two stages, both inside the destination's parent directory, so the final rename is atomic on the same file system:

  1. <parent>/.maleta-stage-XXXXXX/ — created by mkdtempSync, receives a copy of the existing destination tree and the plan's files. The suffix is random.
  2. <stage>.old — when the destination already exists, the old tree is renamed here before the stage takes its place. It is removed at the end, on success or error.

If application fails midway, destinations already swapped are restored from the corresponding .old and the error is propagated with exit code 1. The finally block removes any remaining stage, so an interrupted run does not leave .maleta-stage-* behind unless the process crashes abruptly.

#Files that are not touched

  • Unmanaged files and directories inside a destination skill: they are copied to the stage and survive the swap.
  • Skills not selected in maleta.json: no destination is calculated for them and nothing is removed from disk.
  • The maleta.json file itself: install and sync never rewrite it.