# Variable
Variable is a type-safe feature configuration system.
You define features in `.var` files, then generate typed access code so application code never relies on ad-hoc string keys.
## Why Variable
- Type-safe flag access in application code
- Defaults are required and baked into generated code
- Stable wire IDs (`u32`) for feature/variable compatibility
- Binary snapshot tooling for transport and diagnostics
## Quick Example
Define features once:
```var
1: Feature Checkout = {
1: Variable enabled Boolean = true
2: Variable max_items Number = 50
3: Variable header_text String = "Complete your purchase"
}
```
Generate TypeScript:
```sh
variable generate --out ./src/generated features.var
```
Use strongly typed values:
```ts
import { VariableClient } from "@variable/runtime";
import { getCheckoutVariables } from "./generated/features.generated";
const client = new VariableClient();
const checkout = getCheckoutVariables(client);
checkout.enabled; // boolean
checkout.max_items; // number
checkout.header_text; // string
```
## Quick Start
### 1. Prerequisites
- [Rust](https://rustup.rs/) (1.85+)
- [Node.js](https://nodejs.org/) (for TypeScript consumers)
### 2. Build the CLI
```sh
git clone <repo-url> && cd variable
cargo build --release
```
Binary path:
```sh
./target/release/variable
```
### 3. Write a `.var` file
```var
1: Feature Search = {
1: Variable enabled Boolean = false
2: Variable max_results Number = 25
3: Variable placeholder String = "Search..."
}
```
### 4. Generate code
```sh
variable generate --out ./src/generated search.var
```
### 5. Optional: create and inspect binary snapshots
```sh
variable encode --schema-revision 1 --manifest-revision 42 search.var > search.snapshot.bin
variable decode --pretty search.snapshot.bin
```
`decode` is diagnostics-focused JSON output. It is not intended to reconstruct source `.var` files.
## CLI Commands
- `variable generate --out <dir> <file.var>`
- `variable encode [--schema-revision N] [--manifest-revision N] [--generated-at-unix-ms N] [--source TEXT] <file.var>`
- `variable decode [--pretty] [--fail-on-error] <file.bin>`
## DSL Reference
A `.var` file is a flat list of feature blocks. IDs are explicit and required.
```var
1: Feature Checkout = {
1: Variable enabled Boolean = true
2: Variable max_items Number = 50
}
2: Feature Search = {
1: Variable enabled Boolean = false
2: Variable query String = ""
}
```
Rules:
- Feature IDs are `u32` and unique per file/invocation
- Variable IDs are `u32` and unique within each feature
- Feature names are unique per file/invocation
- Variable names are unique within each feature
- Every variable must have a default value
- String escapes supported: `\n`, `\t`, `\\`, `\"`
Supported types:
| `Boolean` | `boolean` |
| `Number` | `number` |
| `String` | `string` |
## Runtime Model
Generated code imports `VariableClient` from `@variable/runtime`.
- Defaults come from generated code
- Provider data can override defaults
- Missing values fall back to defaults
Current TS provider shape:
```ts
interface Provider {
getManifest(): Record<string, Record<string, unknown>>;
}
```
## Binary Protocol
Wire format v1 details are documented in:
- `docs/binary-protocol-v1.md`
`variable-wire` provides Rust encode/decode tooling used by the CLI.
## Examples
- `examples/ts/basic`
Run:
```sh
cd examples/ts/basic
npm install
npm start
```
## Repository Layout
```text
variable-core/ parser, lexer, AST, validation
variable-codegen/ TypeScript generation
variable-wire/ binary protocol encode/decode tooling
variable-cli/ CLI (`generate`, `encode`, `decode`)
runtime/ts/ TypeScript runtime package (@variable/runtime)
examples/ runnable examples
fixtures/ sample .var inputs
```
## Development
```sh
cargo test
cargo build --release
cargo insta review
```
## License
MIT