Skip to content

Core Concepts

Understanding the key ideas behind SkyState will help you use it effectively and avoid common mistakes. This page covers the building blocks: accounts, projects, environments, configs, and versioning.


Accounts

An account is the top-level identity in SkyState. It maps to one GitHub user and has:

  • A unique account slug — a short lowercase identifier used in public URLs and the CLI. It is derived from your GitHub username and can be changed in account settings.
  • A subscription tierfree, hobby, or pro — which determines how many projects you can create and how many API requests are counted per month.

Authentication is done via GitHub OAuth. There is no username/password — your GitHub identity is the credential.


Projects

A project is the unit of organization for a set of related configs. You might have one project per application, or one project per service in a larger system.

Each project has:

  • A name — a human-readable display name.
  • A slug — a lowercase alphanumeric identifier unique within your account, used in CLI commands and API paths. Example: my-api, web-app, marketing-site.
  • Three fixed environments: development, staging, and production.

Projects are created from the dashboard or with skystate project create.

A local repository is linked to a project by skystate init, which writes the project slug to skystate.json at the repository root.

Project Limits by Tier

TierMax Projects
Free3
Hobby7
Pro15

Environments

Every project has exactly three environments: development, staging, and production. They are created automatically when the project is created — there is nothing to provision.

Environments are isolated from one another. Pushing a config to development has no effect on staging or production. This lets you iterate safely:

  1. Push and test in development.
  2. Promote to staging when the change is ready.
  3. Promote to production when staging is verified.

Promoting Between Environments

The skystate promote command copies the latest config from one environment to another:

bash
skystate promote --from staging --to production

This creates a new version in the target environment that is identical to the source. It does not modify the source environment.

Environment Slugs and Aliases

CLI commands accept both full names and short aliases:

Full nameAlias
developmentdev
stagingstg
productionprod

For example, skystate push config.json --env dev is equivalent to --env development.


Configs

A config is a JSON object stored for a specific project and environment. It holds all the remote values your application reads at runtime.

Key properties of configs:

  • JSON objects only — configs must be JSON objects ({}), not arrays or primitives.
  • Flat or nested — you can use dotted keys like "banner.enabled" or nested objects like {"banner": {"enabled": true}}. The SDK reads individual keys by path.
  • Read-only for clients — end users of your application can read configs via the SDK (using a dev key or a public project key), but cannot write to them. Only authenticated admin actions (CLI, dashboard, or your backend using your JWT) can push changes.
  • Versioned — every push creates an immutable new version. Previous versions are retained according to your tier's retention policy.

Example Config

json
{
  "maintenance.enabled": false,
  "banner.enabled": true,
  "banner.text": "Spring sale — 20% off all plans!",
  "banner.color": "#3b82f6",
  "features.darkMode": false,
  "features.maxItems": 10,
  "limits.maxUploadMb": 25
}

Config Size

Each config is stored as a JSON blob. The size limits depend on your subscription tier. Configs that exceed the limit are rejected at push time with a clear error message.


Semantic Versioning

Every config is versioned using semantic versioning (major.minor.patch). SkyState automatically determines the appropriate version bump based on what changed between the previous version and the new one.

Automatic Bump Detection

When you run skystate push, the CLI fetches the current config and compares it to the file you are pushing:

What changedBump typeExample
A key was removedmajor1.2.32.0.0
A value's type changed (e.g. string became boolean)major1.2.32.0.0
A new key was addedminor1.2.31.3.0
Only values changedpatch1.2.31.2.4
No changes detectedpatch1.2.31.2.4

The first push to any environment always creates version 1.0.0.

Overriding the Bump Type

You can override automatic detection with the --bump flag:

bash
skystate push config.json --env production --bump minor

Valid values: major, minor, patch.

Major Milestone Flag

The --major flag marks a version as a major milestone for retention purposes. This is independent of the semver bump type:

bash
skystate push config.json --env production --bump patch --major

Major milestones are retained longer than ordinary versions under retention pruning policies.

Viewing Version History

Use skystate show to see the current version of a config:

bash
skystate show --env production

Use skystate diff to compare two versions:

bash
skystate diff --env production --from 1.0.0 --to 2.0.0

API Keys

SkyState uses two types of API keys.

Dev API Keys

A dev API key (sk_dev_...) is generated by skystate init for local development. It is:

  • Scoped to a single project's development environment only.
  • Read-write — the SDK uses it to auto-create config keys when they are not found on the server (dev-mode auto-provisioning).
  • Written to your project's .env file as SKYSTATE_DEV_KEY.
  • Safe to expose to the client bundle in development (Vite, Next.js, etc. via environment variables). The server rejects it for staging or production requests, so accidental leaks cannot affect live environments.

Dev API keys can be rotated at any time from the dashboard (Settings → Dev Keys) or by re-running skystate init.

Never commit your .env file. skystate init offers to add .env to .gitignore automatically.

JWT (Admin Credential)

When you run skystate login, the CLI stores a JWT at ~/.config/skystate/credentials.json. This token:

  • Is tied to your account and grants full admin access to all your projects.
  • Expires after 30 minutes and is refreshed transparently.
  • Should never be shared or committed.

The CLI reads this token automatically for all skystate commands.


Configuration Files

SkyState uses two configuration files:

skystate.json (Project Config)

Written to the repository root by skystate init. Contains the project slug that links this repo to a SkyState project.

json
{
  "project_slug": "my-app"
}

Commit this file. It is not sensitive and must be present for skystate push and skystate show to work without extra flags.

~/.config/skystate/config.json (Global CLI Config)

Stores your personal CLI preferences. Written by skystate config set.

json
{
  "api_url": "https://api.skystate.io",
  "format": "table"
}

Available keys:

KeyDefaultDescription
api_urlhttps://api.skystate.ioAPI base URL. Override with SKYSTATE_API_URL env var.
default_project(empty)Fallback project slug when not in a repo with skystate.json.
default_env(empty)Fallback environment for push/show/diff commands.
formattableDefault output format: table, json, or plain.

Manage this file with skystate config set <key> <value>, skystate config get <key>, and skystate config list.

.env (Dev Key)

Written to the repository root by skystate init. Contains the dev API key as SKYSTATE_DEV_KEY.

SKYSTATE_DEV_KEY=sk_dev_abc123...

Do not commit this file. It contains a secret credential. Add it to .gitignore.


The Network-First Model

The SDK follows a network-first architecture. When a component mounts:

  1. The SDK immediately returns the defaultValue you provided in code, with isLoading: true.
  2. The SDK fetches the latest config from the server.
  3. On success: data is updated to the server value, isLoading: false.
  4. On failure: data stays on defaultValue, isLoading: false, error is populated.

This means your app is always functional even if SkyState is unreachable — it falls back to your hardcoded defaults. The skystate.json file on disk is not read at runtime; it is a developer tool for CLI operations only.

Built with VitePress