# How the CLI-Anything Layout Engine Calculates Intrinsic Sizes for Different Layer Types

> Discover how the CLI-Anything layout engine calculates intrinsic sizes. Learn about its type-aware algorithm for spacers, text, and default dimensions.

- Repository: [✨Data Intelligence Lab@HKU✨/CLI-Anything](https://github.com/HKUDS/CLI-Anything)
- Tags: internals
- Published: 2026-08-16

---

**The CLI-Anything layout engine derives intrinsic sizes through a type-aware algorithm implemented in the `intrinsicSize` function, which processes spacers, explicit dimensions, text content, and type-specific defaults before returning a `{ width, height }` object.**

The HKUDS/CLI-Anything repository provides a declarative layout system for CLI applications, where each layer's natural dimensions must be determined before positioning logic executes. Understanding how the layout engine calculates these intrinsic sizes is essential for building responsive terminal interfaces. The core logic resides in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js) and handles multiple layer types through a cascading priority system.

## Core Layout Logic in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js)

The layout engine centers around the **`intrinsicSize`** function, which computes natural dimensions for any layer before the positioning algorithms (`vertical-stack`, `horizontal-stack`, or `absolute`) arrange elements on screen. This function implements a five-step resolution strategy that checks layer type and explicit specifications in priority order.

### The `intrinsicSize` Function Entry Point

Located in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js), the `intrinsicSize` function accepts layer configuration parameters and returns an object containing calculated `width` and `height` values. The algorithm processes layers through specific type checks, starting with spacers and proceeding through explicit dimensions, text estimation, and finally applying type-specific defaults.

## Layer-Type-Specific Size Resolution

The engine distinguishes between layer types to apply appropriate sizing logic. Each category follows distinct rules for determining natural dimensions when explicit values are absent.

### Handling Spacer Layers with Flexible Gaps

When `layer.type === 'spacer'`, the engine treats the element as a flexible gap rather than content. The function returns the explicitly provided `width` (or falls back to the parent container width) and the specified `height`, defaulting to **0** when height is unspecified. This allows spacers to absorb available space in stack layouts without requiring explicit pixel values.

### Resolving Explicit Dimensions and Fill Width

For all layer types, the engine first examines `layer.width` and `layer.height` properties. If the width value equals the string **`'fill'`**, the engine substitutes the parent container width (with a fallback of **300 px** if no parent exists). When a layer contains a `layer._resolvedStyle` object, the engine extracts width and height from these resolved styles, applying the same `'fill'` substitution logic. This enables responsive designs where elements expand to match container boundaries.

### Estimating Text Layer Dimensions

Text layers (`layer.type === 'text'`) require special handling when dimensions remain undefined after explicit checks. The engine invokes **`estimateTextSize`**, which calculates width based on character count (distinguishing between ASCII and CJK characters) and derives height from the specified line-height or a default multiplier of the font size. These computed estimates populate missing width or height slots, ensuring text layers naturally size to their content without manual specification.

### Default Sizing for Groups and Rectangles

If previous resolution steps fail to determine dimensions, the engine applies hardcoded defaults. Width defaults to **100 px** for all layer types. Height defaults to **40 px** for most layers, but **`group`** types receive a default height of **0 px** because their final dimensions derive from the sum of child elements during the subsequent layout pass. This distinction prevents groups from reserving unnecessary space before their children are positioned.

## Practical Code Examples

The following examples demonstrate how the intrinsic size logic behaves with different layer configurations. All examples assume the layout engine is imported from [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js):

```javascript
const { computeLayout } = require('./sketch/agent-harness/src/layout');

// Spacer inherits parent width when unspecified
const spacerSpec = [{ type: 'spacer', height: 20 }];
console.log(computeLayout(spacerSpec, { type: 'vertical-stack' }, 500, 300));
// → [{ index:0, x:0, y:0, width:500, height:20 }]

```

```javascript
// Text layers calculate size from content when dimensions are missing
const textSpec = [{ type: 'text', value: 'Hello world!' }];
console.log(computeLayout(textSpec, { type: 'absolute' }, 400, 200));
// → width ≈ 84 px, height ≈ 19 px (based on estimateTextSize)

```

```javascript
// 'fill' width matches parent container
const fillSpec = [{ type: 'image', width: 'fill', height: 150 }];
console.log(computeLayout(fillSpec, { type: 'absolute' }, 320, 240));
// → [{ index:0, x:0, y:0, width:320, height:150 }]

```

```javascript
// Groups default height to 0, deriving final size from children
const groupSpec = [{
  type: 'group',
  layout: { type: 'vertical-stack', gap: 5 },
  children: [
    { type: 'text', value: 'One' },
    { type: 'text', value: 'Two' }
  ]
}];
console.log(computeLayout(groupSpec, { type: 'absolute' }, 200, 200));
// → group width = 100 (default), height = sum of child heights + gaps

```

## Summary

- The **`intrinsicSize`** function in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js) serves as the central calculator for natural layer dimensions.
- **Spacer layers** default to parent width and zero height, functioning as flexible gaps.
- The **`'fill'`** string value triggers substitution with the parent container width, enabling responsive layouts.
- **Text layers** rely on **`estimateTextSize`** to compute dimensions based on character count and font metrics when explicit sizes are absent.
- **Groups** uniquely default to **0 px** height because they derive final dimensions from child layouts, while other layers default to **100 px** width and **40 px** height.

## Frequently Asked Questions

### What file contains the intrinsic size calculation logic?

The intrinsic size calculation logic resides in [`sketch/agent-harness/src/layout.js`](https://github.com/HKUDS/CLI-Anything/blob/main/sketch/agent-harness/src/layout.js) within the HKUDS/CLI-Anything repository. This file exports the `intrinsicSize` function alongside the `estimateTextSize` helper and three layout positioning algorithms.

### How does CLI-Anything handle text layers without explicit dimensions?

When text layers lack explicit width or height values, the engine calls `estimateTextSize` to compute natural dimensions based on character count (distinguishing ASCII from CJK characters) and line-height metrics. These estimates ensure text renders at appropriate sizes without manual pixel specification.

### What is the default size for groups versus other layers?

Groups default to **100 px** width and **0 px** height, while rectangles and other layer types default to **100 px** width and **40 px** height. The zero-height default for groups exists because their final dimensions are calculated from the sum of positioned children during the layout pass.

### How does the 'fill' width value work in CLI-Anything layouts?

The string value `'fill'` triggers the engine to substitute the parent container's width (with a fallback of **300 px** if undefined). This substitution occurs both in direct `layer.width` properties and within `layer._resolvedStyle` objects, allowing elements to expand responsively within their containers.