<!-- Public documentation export; not library implementation source. -->
# Local data and capture

Open a session after widget readiness. Reads and capture need only the `read` effect:

```ts
// Run inside the widget's ready callback.
const chart = widget.activeChart();
const sdk = await chart.openAutomation({ commands: [], policy: { effects: ['read'] } });

const series = sdk.data.series();
const range = chart.getVisibleRange();
if (range && series.find(item => item.id === 'main')?.readiness === 'ready') {
  const result = await sdk.data.read({
    seriesId: 'main',
    from: Math.round(range.from * 1000),
    to: Math.round(range.to * 1000),
    limit: 2000,
  });
  console.log(result.rows, result.coverage);
}
const image = await sdk.capture.image();
console.log(image.blob, image.width, image.height);

// On component teardown (chart removal also closes the session):
sdk.close();
```

`commands: []` installs no native command families. Each call above uses a fresh request for the current chart; pass `sdk.request()` captured earlier to reject results from a chart that has since changed.

To avoid downloading the automation runtime for read-only use, bundle the SDK and create the session yourself. Keep the chart and screenshot index paired:

```ts
import { createNativeChartAutomation } from '@lumencharts/chart-automation/sdk';

const sdk = createNativeChartAutomation({
  chartId: 'primary',
  chart: widget.workspaceChart(0),
  capturePng: () => widget.takeClientScreenshot({ chartIndex: 0, strictCapture: true }),
  policy: { effects: ['read'] },
});
```

`capturePng` may return either a PNG data URL or a PNG `Blob`. A Blob is validated from its header only, so it avoids base64 decoding for large charts.

## Time, fields and coverage

SDK timestamps use integer UTC milliseconds. The native visible-range API uses seconds, hence the conversion above. Inside a command, read through `context.execute('data.read', input)` so the read shares the command's request, deadline and target fence. Main-series data is raw OHLCV, not transformed display candles. Open, high, low and close are required finite numbers; volume may be omitted.

Every discovered series declares its numeric fields, units and readiness. Fields are required and non-null by default. `optional: true` permits omission; `nullable: true` permits explicit `null`. Rows must contain an integer `time` and only declared fields. Timestamps must be unique, increasing and inside the requested range. Descriptors are snapshotted before asynchronous work so later provider changes cannot alter validation for a pending read.

The native adapter exposes main candles. Comparison, study and Pine output series require a host data adapter; they are not automatically extracted from arbitrary indicator buffers. Pending series reject local reads with `busy`; failed series reject with `unavailable`.

Reads never fetch missing history. An oversized matching window rejects instead of silently returning a partial slice. `coverage.complete` means the requested window is inside the reported loaded bounds; it does not promise a candle for every clock interval or exhaustive market history. `requestHistory` is a separate, optional host operation that requires the `external` effect.

## Capture and image transport

Capture returns a PNG Blob with dimensions, target, capture time, visible range and revision. The revision is a session change counter, not a persisted document version. Capture rejects stale work if the chart selection, data or visible range changes while it is pending.

The current capture scope is the exact chart at native dimensions. Cropping, custom dimensions, layer filtering and image editing are not SDK options. Your application can process the returned image separately. Uploads, attachment identities, retention and provider-specific image formats belong to that application.

## Events and cleanup

```ts
const unsubscribe = sdk.events.subscribe(event => {
  console.log(event.type, event.target, event.revision);
});
// Release when the observer is no longer needed.
unsubscribe();
```

Events include `selection`, `data`, `study-ready` and `disposed`. Data notifications are coalesced within a microtask; selection and disposal are immediate. A `study-ready` event first delivers any queued data notification, so events arrive in commit order. Payloads are immutable. The native session destroys itself when its chart is removed; explicit `destroy()` is also safe to call repeatedly.

[Add native commands and model tools →](https://docs.lumencharts.com/charting-library/automation/commands-and-tools)

---
Documentation page: https://docs.lumencharts.com/charting-library/automation/data-and-capture
