How CLI-Anything Merges CLI-Provided Tokens with Spec-Defined Tokens

CLI-Anything resolves token files through a strict precedence hierarchy where CLI-provided paths override spec-defined ones, with both subjected to directory-based security validation before falling back to bundled defaults.

The HKUDS/CLI-Anything repository provides a sketch generation framework that relies on JSON design tokens to maintain visual consistency across outputs. When executing a build, the system must determine which token definition file to load, balancing user customization with security constraints. Understanding how the tool merges CLI-provided tokens with spec-defined tokens ensures you can safely override defaults without triggering path-traversal protections.

The Three-Stage Token Resolution Process

In sketch/agent-harness/src/builder.js, the loadTokens function implements a deterministic resolution algorithm that selects exactly one token source. The process follows a strict precedence chain: CLI arguments take priority over spec configurations, which in turn supersede built-in defaults.

Stage 1: Loading the Default Token Set

The builder always initializes with the bundled default tokens as a failsafe. At lines 62-64, the system resolves the path to tokens/default.json relative to the builder's location.

const defaultTokensPath = path.resolve(__dirname, '..', 'tokens', 'default.json');

This default set serves as the foundation that remains active unless overridden by subsequent validation stages.

Stage 2: Evaluating CLI-Provided Tokens

When the user supplies the --tokens <path> flag, the CLI passes this path to loadTokens. The builder subjects the path to rigorous validation through the isSafePath helper before accepting it.

A CLI-provided path is considered safe only if it resides in one of three locations:

  • The repository's global tokens directory
  • The specification file's directory (specDir)
  • The current working directory (CWD)—the only location where explicit CLI overrides are permitted

If the path passes validation, it immediately becomes the sole token source, short-circuiting spec-level lookups. If validation fails, the system emits a warning and proceeds to evaluate spec-defined tokens.

The validation logic appears at lines 90-101:

if (cliTokensPath) {
  const resolved = path.resolve(cliTokensPath);
  if (
    isSafePath(resolved, tokensDir) ||
    (specDir && isSafePath(resolved, path.resolve(specDir))) ||
    isSafePath(resolved, process.cwd())
  ) {
    tokensPath = resolved;
  } else {
    console.warn(`Unsafe tokens path ignored: ${cliTokensPath}`);
  }
}

Stage 3: Falling Back to Spec-Defined Tokens

When no CLI token file is provided (or the provided path was rejected), the builder examines the design spec JSON for a tokens entry. The system resolves this path relative to the spec's directory and validates it against the global tokens folder or the spec's own directory—note that CWD is intentionally excluded from spec-defined token validation for security reasons.

The fallback logic at lines 103-110 demonstrates this behavior:

else if (specTokensPath) {
  const resolved = path.resolve(specDir, specTokensPath);
  if (isSafePath(resolved, tokensDir) || isSafePath(resolved, path.resolve(specDir))) {
    tokensPath = resolved;
  } else {
    console.warn(`Unsafe spec tokens path ignored: ${specTokensPath}`);
  }
}

If this check also fails, the builder retains the default token set loaded in Stage 1.

Security Validation with isSafePath

The isSafePath function (lines 67-85 in builder.js) prevents directory traversal attacks by canonicalizing both the candidate path and the allowed base directory. It ensures the relative path does not start with ../ (or equal ..), effectively blocking escapes from permitted directories. Notably, the validation permits directory names that begin with dots (such as ..brand), only rejecting actual parent-directory references.

Practical Usage Examples

To override tokens via CLI, specify the path using the -t or --tokens flag:

sketch-cli build -i design.json -o output.sketch -t ./my-tokens.json

To define tokens within your design specification, add a tokens field to your spec JSON:

{
  "tokens": "./tokens/my-spec-tokens.json",
  "pages": [ /* … */ ]
}

If you attempt to load a token file from an unsafe location, the CLI warns you and falls back to the spec-defined or default tokens:

sketch-cli build -i design.json -o out.sketch -t ../../secret.json

# → Unsafe tokens path ignored: ../../secret.json

Summary

  • CLI tokens override spec tokens: The presence of a valid --tokens argument short-circuits spec-level token resolution according to the source code in sketch/agent-harness/src/builder.js.
  • Security-first validation: Both CLI and spec token paths must pass isSafePath checks to prevent directory traversal attacks.
  • Directory constraints differ: CLI tokens may reside in the CWD, global tokens directory, or spec directory; spec-defined tokens are restricted to the global tokens directory or spec directory only.
  • Deterministic fallback: The system always loads default tokens first, then conditionally replaces them with validated CLI or spec tokens, ensuring the build pipeline always has a valid token object to process.

Frequently Asked Questions

What happens if I provide both CLI and spec token files?

The CLI-provided token file takes precedence exclusively. If the CLI path passes security validation, the builder uses it immediately and never checks the spec's tokens field. Only if the CLI path is missing or rejected does the builder evaluate spec-defined tokens.

Why does my token file path get rejected as unsafe?

The isSafePath function rejects paths that resolve outside permitted boundaries. For CLI tokens, the file must reside in the global tokens directory, the spec's directory, or the current working directory. For spec-defined tokens, only the global tokens directory or the spec's own directory are allowed. Paths containing ../ or absolute paths outside these locations trigger the safety warning.

Can I use a token file from outside the project directory?

Only when invoking the override through the CLI --tokens flag with a path in your current working directory. Spec-defined tokens cannot reference files outside the project's token directory or the spec's location. This restriction prevents malicious specs from accessing arbitrary files on the filesystem.

How do I know which token file was actually loaded?

The builder emits a console.warn message when ignoring an unsafe path, helping you diagnose configuration issues. You can also check the resolution logic: if you provided a CLI path and didn't see a warning, that file was used; otherwise, check for warnings about spec paths or confirm that defaults were loaded.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →