---
title: Libraries
description: >-
  Reusable kScript libraries: the library() header, import with aliases and
  version pinning, precedence rules, sandboxing, and hot reload.
---

<div class="flex gap-3 mb-6">
  <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-purple-50 text-purple-600 text-sm font-medium">
    Advanced
  </span>
  <span class="inline-flex items-center gap-1.5 px-3 py-1 rounded-full bg-gray-100 text-gray-600 text-sm font-medium">
    10 min read
  </span>
</div>

## Introduction

Libraries let you write a function and type collection **once** and import it from any script: your TA helpers, your zone structs, your formatting utilities. A library is itself kScript, runs under exactly the same sandbox, and hot-reloads while you develop it.

## Writing a library

A library is a source whose first statement is a `library()` header, followed by **only** function and type declarations:

```javascript
library("my_ta", "1.0.0")

type Band {
  basis: number,
  upper: number,
  lower: number
}

func zscore(src, period) {
  var m = sma(source=src, period=period)
  var sd = stdev(source=src, period=period)
  return (src - m) / sd
}

func makeBand(src, period, mult) {
  var m = sma(source=src, period=period)
  var sd = stdev(source=src, period=period)
  return Band.new(basis=m, upper=m + sd * mult, lower=m - sd * mult)
}
```
- The name must be lowercase (`[a-z][a-z0-9_]*`); the version is optional semver.
- Anything else at top level (`define`, plots, `input`, data sources, bare expressions) is a compile error with line/column: libraries declare, consumers run.

## Importing

```javascript
import "my_ta"                    // latest version, plain names: zscore(...)
import "my_ta@1.0.0"              // pinned to an exact version
import "my_ta" as ta              // aliased: ta.zscore(...), ta.Band.new(...)
```
- **Plain import** brings the library's functions and types in under their own names.
- **Alias import** namespaces everything behind the alias, like the built-in `math.` namespace. Aliased imports can never collide with anything.
- **Pinning**: `name@version` selects an exact registered version; a bare name takes the latest. Unknown names and versions error with the list of what is available.
- `import` is contextual (old scripts using the word as an identifier keep parsing), and duplicate imports of the same library are reported as exactly that.

## Precedence and integrity rules

Worked out so that nothing ever changes meaning silently:

1. **Your script wins.** If a plain import collides with a function the script itself defines, the script's version is used at the script's call sites, and the compiler emits a warning telling you so.
2. **Libraries are internally sealed.** A library function calling its sibling always gets *its own* sibling, even when the consumer overrides that name. Imports cannot be middleman-ed.
3. **Import-vs-import plain collisions are errors** (ambiguity has no safe default); alias one of them.
4. **Aliases are validated**: `as math` (a builtin namespace) or `as close` (a global) is a compile error.

## Sandbox and attribution

Library code is ordinary kScript: every limit in the [sandbox manifest](../faq/limitations.md) applies unchanged, and errors raised inside a library carry the **library's own line and column**, so a runaway loop in `my_ta` says so, not some opaque consumer position.

## Versioning and updates

Registering a new version of a library leaves existing pins untouched: scripts pinned to `@1.0.0` keep their behavior; bare imports pick up the latest on their next run. Re-registering the *same* version is an error: versions are immutable once published.

## Hot reload in the playground

The playground has a library editor alongside the script editor. Edit the library, run the script, and the new library code is picked up immediately: same page, no reload, registry updated in place. The development loop for a shared helper is exactly the development loop for a script.

## Pine comparison

Pine libraries exist but are publish-bound (TradingView-hosted, review queues, no local hot iteration) and export only functions over Pine's types. kScript libraries are local-first, version-pinned, hot-reloadable, can export your own structured types, and their consumers keep every compile-time guarantee (typed fields, precedence warnings, sandbox attribution) the rest of v3 provides.
