Workspace is a tool suite for file operations, version management, and development workflow automation. Includes refactor (string replacement), scrap (local trash folder), unscrap (file restoration), and state (automatic versioning).
State is the version management component of Workspace. It integrates with Git to provide automatic semantic versioning, template rendering, and cross-project version stamping via .wstemplate files.
State uses a three-part versioning scheme:
wsb version major (stored in the project database)Final Version Format: {major}.{minor}.{patch}
# Repository state:
# - Major version set to 2 (via wsb version major 2)
# - Total commits: 150
# - Total line changes: 4200
# Result: 2.150.4200
./install.sh
Navigate to your Git repository and inspect the active git scope:
cd your-git-repo
wsb status
Create a .state.json configuration file in your repository root:
{
"version": 1,
"enabled": true,
"version_file": "version.txt"
}
Configuration Options:
enabled: Enable/disable automatic version updatesversion_file: Path to the file where version is written (default: version.txt)auto_detect_project_files: Automatically detect and update common project files (default: true)project_files: Array of additional project files to updatewsb status
wsb version show
wsb version show --verbose
wsb version show --format json
wsb update # Update version and render templates
wsb update --git-add # Also stage changed files
wsb update --no-git # Skip git integration
wsb version major 1 # Set major to 1
wsb version major 2 # Bump major to 2
wsb version tag # Tag with current version
wsb version tag --prefix "release-" # Custom prefix
wsb version tag --message "Release" # With message
wsb status
wsb update before commit boundaries when you want version files refreshedwsb update:
version.txt (or custom version file).wstemplate files relevant to this projectNote: The .wsb directory (containing state.json, logs, databases) is local project state and should be in .gitignore. It is never staged by wsb update.
"enabled": false in .state.jsonwsb update when neededwsb update --git-add to stage updated filesState automatically detects and updates version fields in common project files:
Supported File Types:
version = "x.y.z" in [package] section"version": "x.y.z"version = "x.y.z" in [tool.poetry] and [project] sectionsversion="x.y.z" parameter"version": "x.y.z"version: x.y.z<version>x.y.z</version>version = 'x.y.z'VERSION x.y.z in project() declarationDisable Auto-Detection:
{
"auto_detect_project_files": false
}
Workspace supports Tera templates for generating files with version information.
wsb template add version-header \
--template "Version: " \
--output version.h
wsb template list
wsb template show version-header
wsb template render
wsb template delete version-header
Templates are rendered automatically during wsb update.
The wstemplate system provides cross-project version stamping. A .wstemplate file is a Tera template that renders to the file with the .wstemplate suffix stripped.
Each project has at most one wstemplate entry in its .wsb/state.json:
.wstemplate files and peer .wsb/state.json filesCross-project references are resolved dynamically — no explicit cross-project entries are needed.
# Register this project with the wstemplate system
wsb wstemplate add /path/to/workspace
# Verify the entry
wsb wstemplate list-entries
# Output:
# 1 wstemplate entries:
# my_project -> /path/to/workspace
The alias is auto-derived from the project directory name:
my-project becomes my_projectAPI Service becomes api_service123abc becomes p_123abcOverride with --alias:
wsb wstemplate add /path/to/workspace --alias mylib
describes the project that owns the template file, and
exposes the same fields for any project in the workspace
— submodules included, since each is a project in its own right.
| Variable | Description |
|---|---|
| `` | Project name |
| `` | Absolute path to the project root |
| `` | Path from the workspace root, e.g. ext/gtest |
| `` | Full version being built, from version.txt |
| `` | e.g., v0 |
| `` | Commit count, as a number |
| `` | Line changes, as a number |
| `` | Highest tag in this clone, e.g. v1.648.6494 |
| `` | That tag without its v — the pin-ready form |
| `` | Newest tag reachable from HEAD |
| `` | Number of tags, as a number |
| `` | Highest tag on the remote (contacts the network) |
| `` | That tag without its v (contacts the network) |
| `` | Full HEAD commit hash |
| `` | Abbreviated HEAD commit hash |
| `` | HEAD commit date, YYYY-MM-DD |
| `` | HEAD commit timestamp, RFC 3339 |
| `` | Checked-out branch |
| `` | Whether HEAD is detached, as a boolean |
| `` | Whether the worktree is modified, as a boolean |
| `` | Remote the project publishes to |
| `` | Fetch URL of that remote |
| `` | RFC 3339 timestamp |
| `` | YYYY-MM-DD |
| `` | HH:MM:SS |
| `` | Year |
| `` | Month |
| `` | Day |
| `` | Seconds since the Unix epoch, as a number |
wsb wstemplate vars prints this table with the values resolved for a real
project, which is the fastest way to see what a template will actually stamp.
version versus latest_versionversion is the version being produced — version.txt is bumped on commit, so
it sits one step ahead of the newest published tag. That is correct for a
dependency resolved from a local checkout inside the workspace, and wrong for a
pin that somebody outside the workspace has to resolve from a registry: that pin
names a release which does not exist yet. Use latest_version there.
latest_tag reflects the tags in this clone. latest_remote_tag asks the remote
directly and is unaffected by how stale the clone is; those two fields are the
only ones that touch the network, and only when a template references them.
A field is either a real value or an error naming the reason — never an empty
string. A project with no tags has no latest_version, and a template asking for
one fails with “it has no tags” rather than writing "" into a manifest. Every
reference is checked before rendering starts, so a template that cannot resolve
leaves no half-written output behind.
[package]
name = "my-app"
version = ""
[dependencies]
my-lib = { path = "../my-lib", version = "" }
When wsb update runs in this project (or in my-lib), this template renders to Cargo.toml with actual version numbers.
{
"name": "@scope/my-app",
"version": "",
"dependencies": {
"@scope/tagged-urn": ""
}
}
When wsb update (or wsb wstemplate render) runs for project X:
.wstemplate files in the scan root are discoveredversion.txt for the
version fields, and its git repository for the tag and head fieldsThe engine discovers all projects by scanning for .wsb/state.json files in the scan root. When a template references ``:
other_lib’s project root from its state.json{project_root}/version.txtAll errors are hard failures — no silent fallbacks:
version.txt: Tells you to run wsb update in the dependency projectFor a multi-project workspace, create a setup script:
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "$0")" && pwd)"
register() {
local project="$1"
echo "=== $project ==="
cd "$ROOT/$project"
wsb wstemplate add "$ROOT"
echo
}
register my-lib
register my-app
register my-tests
echo "Done. Run 'wsb update' in any project to render its templates."
wsb wstemplate add <PATH> [--alias <ALIAS>] # Set scan root
wsb wstemplate remove <ALIAS> # Remove entry
wsb wstemplate list-entries # Show this project's entry
wsb wstemplate list # List relevant templates
wsb wstemplate render # Render all relevant templates
wsb statuswsb updategit statusgit statuswsb version showwsb updatewsb wstemplate list-entrieswsb wstemplate listwsb wstemplate renderversion.txt (run wsb update in them)rm .state.json # Remove configuration (optional)
rm version.txt # Remove version file (optional)
wsb wstemplate remove my_alias # Remove wstemplate entry (optional)
State logs all actions to .wsb/logs/wsb.log:
tail -f .wsb/logs/wsb.log
wsb version major: Set major version via database, not git tagswsb update After Setup: Ensure version.txt exists before other projects reference it.wsb to .gitignore: The .wsb directory is local state — do not commit itVERSION=$(cat version.txt)
echo "Building version: $VERSION"
docker build -t myapp:$VERSION .
- name: Get Version
id: version
run: echo "version=$(cat version.txt)" >> $GITHUB_OUTPUT
- name: Create Release
uses: actions/create-release@v1
with:
tag_name: v$
release_name: Release $
VERSION := $(shell cat version.txt)
build:
@echo "Building version $(VERSION)"
cargo build --release