
Security News
Ruby's Bundler 4.0.18 Extends Cooldown to bundle lock and bundle cache
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.
Terraform-like CLI for managing Typesense collections, aliases, synonyms, and curations
A declarative infrastructure-as-code CLI for managing Typesense collections, aliases, synonyms, and curations.
npm install -g tsctl
# or
npx tsctl
tsctl init
This creates:
tsctl.config.ts - Your infrastructure definition.env - Connection settingsEdit .env:
TYPESENSE_HOST=localhost
TYPESENSE_PORT=8108
TYPESENSE_PROTOCOL=http
TYPESENSE_API_KEY=your-api-key-here
Edit tsctl.config.ts:
import { defineConfig } from "tsctl";
export default defineConfig({
collections: [
{
name: "products",
fields: [
{ name: "name", type: "string" },
{ name: "description", type: "string", optional: true },
{ name: "price", type: "float" },
{ name: "category", type: "string", facet: true },
{ name: "tags", type: "string[]", facet: true, optional: true },
],
default_sorting_field: "price",
},
],
aliases: [
{
name: "products_live",
collection: "products",
},
],
});
tsctl plan
Output:
Typesense Plan:
+ collection.products (create)
+ name: "products"
+ fields: [...]
+ alias.products_live (create)
+ name: "products_live"
+ collection: "products"
Summary:
2 to create, 0 to update, 0 to delete, 0 unchanged
tsctl apply
| Command | Description |
|---|---|
tsctl init | Initialize a new project |
tsctl validate | Validate config file |
tsctl plan | Show planned changes |
tsctl apply | Apply changes to Typesense |
tsctl destroy | Destroy all managed resources |
tsctl import | Import existing resources |
tsctl state list | List managed resources |
tsctl state show | Show full state JSON |
tsctl state clear | Clear state (keeps resources) |
tsctl env list | List available environments |
tsctl env show | Show current environment config |
tsctl drift | Detect changes made outside of tsctl |
tsctl migrate | Blue/green migration for collections |
Global Options:
--env <name> - Use environment-specific .env.<name> filetsctl supports multiple configuration file formats and locations. Files are searched in the following order:
| File | Format |
|---|---|
package.json | "tsctl" property |
.tsctlrc | JSON or YAML |
.tsctlrc.json | JSON |
.tsctlrc.yaml / .tsctlrc.yml | YAML |
.tsctlrc.js / .tsctlrc.cjs / .tsctlrc.mjs | JavaScript |
.tsctlrc.ts / .tsctlrc.cts / .tsctlrc.mts | TypeScript |
tsctl.config.js / tsctl.config.cjs / tsctl.config.mjs | JavaScript |
tsctl.config.ts / tsctl.config.cts / tsctl.config.mts | TypeScript |
tsctl.config.json | JSON |
tsctl.config.yaml / tsctl.config.yml | YAML |
typesense.config.* | Legacy (all formats) |
TypeScript (recommended):
// tsctl.config.ts
import { defineConfig } from "tsctl";
export default defineConfig({
collections: [{ name: "products", fields: [...] }],
});
JSON:
// tsctl.config.json
{
"collections": [{ "name": "products", "fields": [...] }]
}
YAML:
# tsctl.config.yaml
collections:
- name: products
fields:
- name: title
type: string
package.json:
{
"name": "my-app",
"tsctl": {
"collections": [{ "name": "products", "fields": [...] }]
}
}
{
name: "products",
fields: [
{
name: "title",
type: "string", // Required
optional: true, // Allow null/missing
facet: true, // Enable faceting
index: true, // Index for search (default: true)
sort: true, // Enable sorting
infix: true, // Enable infix search
locale: "en", // Language for stemming
stem: true, // Enable stemming
store: true, // Store original value
num_dim: 384, // Vector dimensions
vec_dist: "cosine", // Vector distance metric
reference: "users.id", // JOINs
range_index: true, // For numeric range queries
},
],
default_sorting_field: "created_at",
token_separators: ["-", "/"],
symbols_to_index: ["#", "@"],
enable_nested_fields: true,
}
string, string[] - Textint32, int32[], int64, int64[] - Integersfloat, float[] - Decimalsbool, bool[] - Booleansgeopoint, geopoint[] - Coordinatesobject, object[] - Nested objectsauto - Auto-detect typestring* - Auto-embeddingimage - Image embedding{
name: "products_live",
collection: "products",
}
{
id: "smartphone-synonyms",
collection: "products",
synonyms: ["phone", "mobile", "smartphone", "cell phone"],
}
For one-way synonyms (root word):
{
id: "tv-synonym",
collection: "products",
root: "television",
synonyms: ["tv", "telly", "television set"],
}
{
id: "pin-featured",
collection: "products",
rule: {
query: "featured",
match: "exact",
},
includes: [
{ id: "product-123", position: 1 },
{ id: "product-456", position: 2 },
],
}
Additional options:
{
id: "boost-category",
collection: "products",
rule: {
query: "shoes",
match: "contains",
},
filter_by: "category:=footwear",
sort_by: "popularity:desc",
remove_matched_tokens: true,
effective_from_ts: 1672531200,
effective_to_ts: 1704067200,
}
{
description: "Search-only key for frontend",
actions: ["documents:search"],
collections: ["products", "categories"],
}
With expiration:
{
description: "Temporary admin key",
actions: ["*"],
collections: ["*"],
expires_at: 1735689600, // Unix timestamp
}
Note: API key values are only shown once when created. If you update an API key's configuration, a new key will be generated and the old one will be deleted.
State is stored in a special Typesense collection (_tsctl_state). This means:
If you have existing collections/aliases:
tsctl import
This will:
tsctl.imported.config.ts fileReview the generated config, then rename it to tsctl.config.ts.
| Variable | Default | Description |
|---|---|---|
TYPESENSE_HOST | localhost | Typesense host |
TYPESENSE_PORT | 8108 | Typesense port |
TYPESENSE_PROTOCOL | http | http or https |
TYPESENSE_API_KEY | - | API key (required) |
Manage multiple Typesense environments (development, staging, production) using environment-specific .env files.
Initialize with environment files:
tsctl init --with-environments
This creates:
.env - Default/development settings.env.development - Development environment.env.staging - Staging environment.env.production - Production environmentUse the --env flag to target a specific environment:
# Plan changes against staging
tsctl plan --env staging
# Apply to production
tsctl apply --env production
# Import from development
tsctl import --env development
# List available environments
tsctl env list
# Show current environment configuration
tsctl env show
# Show specific environment
tsctl --env production env show
.env file is always loaded first--env <name> is specified, .env.<name> is loaded and overrides base valuesDetect when resources have been modified outside of tsctl (e.g., via Typesense dashboard or API).
tsctl drift
Output shows:
The drift command exits with code 1 if drift is detected, making it useful for CI pipelines:
# In your CI pipeline
tsctl drift --env production || echo "Drift detected!"
For programmatic use:
tsctl drift --json
Perform zero-downtime collection schema updates using the blue/green deployment pattern.
products_1706486400000)Full migration in one command:
tsctl migrate -a products_live -c tsctl.config.ts
For more control, migrate in stages:
# Step 1: Create the new collection
tsctl migrate -a products_live -c tsctl.config.ts --create-only
# Step 2: Index your data to the new collection
# (use your own indexing process)
# Step 3: Switch the alias to the new collection
tsctl migrate -a products_live -c tsctl.config.ts --switch-only
# Step 4: Delete the old collection when ready
tsctl migrate -a products_live -c tsctl.config.ts --cleanup products_1706486400000
| Option | Description |
|---|---|
-a, --alias <name> | Alias to migrate (required) |
-c, --config <path> | Path to config file (required) |
--collection <name> | Collection from config (if multiple) |
--skip-delete | Keep old collection for rollback |
--create-only | Only create new collection |
--switch-only | Only switch alias |
--cleanup <name> | Delete old collection |
If something goes wrong, switch the alias back:
# List collection versions
tsctl state list
# Manually switch alias back
# Edit your config to point to the old collection and run:
tsctl apply
MIT
FAQs
Terraform-like CLI for managing Typesense collections, aliases, synonyms, and curations
We found that tsctl demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
The supply chain control that delays freshly published gems now covers lockfile generation and gem vendoring in Ruby projects.

Security News
During a UK cyber test, a Mythos 5 agent used sockpuppets, social engineering, and prompt injection to try to get a maintainer to merge malware.

Company News
Socket is now in the AWS Security Hub Extended plan. Adopt it through AWS, apply committed spend, and block malicious open source packages.