Workspace - Command-Line Tool Suite

Workspace is a tool suite for file operations, version management, and development workflow automation. Includes refac (string replacement), scrap (local trash folder), unscrap (file restoration), and state (automatic versioning).

View on GitHub

State Guide

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.

How Version Calculation Works

State uses a three-part versioning scheme:

Final Version Format: {major}.{minor}.{patch}

Example

# Repository state:
# - Major version set to 2 (via wsb version major 2)
# - Total commits: 150
# - Total line changes: 4200

# Result: 2.150.4200

Installation and Setup

1. Install Workspace

./install.sh

2. Install Git Hook

Navigate to your Git repository and install the pre-commit hook:

cd your-git-repo
wsb git install

This creates a pre-commit hook that automatically updates your version file before each commit.

3. Configure (Optional)

Create a .state.json configuration file in your repository root:

{
  "version": 1,
  "enabled": true,
  "version_file": "version.txt"
}

Configuration Options:

Basic Usage

Install Hook

wsb git install
wsb git install --force    # Force reinstall

Show Version Information

wsb git show
wsb version show
wsb version show --verbose
wsb version show --format json

Manual Version Update

wsb update                 # Update version and render templates
wsb update --git-add       # Also stage changed files
wsb update --no-git        # Skip git integration

Set Major Version

wsb version major 1        # Set major to 1
wsb version major 2        # Bump major to 2

Create Git Tag

wsb version tag                    # Tag with current version
wsb version tag --prefix "release-"  # Custom prefix
wsb version tag --message "Release"  # With message

Check Status

wsb git status

Uninstall Hook

wsb git uninstall

Workflow Integration

  1. Install the git hook once: wsb git install
  2. Work normally — commit as usual
  3. Version files are automatically updated before each commit:
    • version.txt (or custom version file)
    • All detected project files (Cargo.toml, package.json, etc.)
    • All .wstemplate files relevant to this project
  4. Updated output files are automatically staged (version.txt, rendered templates)

Note: The .wsb directory (containing state.json, logs, databases) is local project state and should be in .gitignore. It is never staged by wsb update.

Manual Mode

  1. Set "enabled": false in .state.json
  2. Run wsb update when needed
  3. Use wsb update --git-add to stage updated files
  4. Commit version changes manually

Project File Auto-Detection

State automatically detects and updates version fields in common project files:

Supported File Types:

Disable Auto-Detection:

{
  "auto_detect_project_files": false
}

Template System (.tera)

Workspace supports Tera templates for generating files with version information.

Managing Templates

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.

Wstemplate System (.wstemplate)

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.

Single-Entry Model

Each project has at most one wstemplate entry in its .wsb/state.json:

Cross-project references are resolved dynamically — no explicit cross-project entries are needed.

Setup

# 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:

Override with --alias:

wsb wstemplate add /path/to/workspace --alias mylib

Template Variables

Variable Description
`` Owning project’s full version
`` e.g., v0
`` Commit count
`` Line changes
`` Project name
`` Any discoverable project’s version
`` Same fields as project.*
`` RFC 3339 timestamp
`` YYYY-MM-DD
`` HH:MM:SS
`` Year
`` Month
`` Day

Example: Cargo.toml.wstemplate

[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.

Example: package.json.wstemplate

{
  "name": "@scope/my-app",
  "version": "",
  "dependencies": {
    "@scope/tagged-urn": ""
  }
}

How Template Selection Works

When wsb update (or wsb wstemplate render) runs for project X:

  1. All .wstemplate files in the scan root are discovered
  2. A template is rendered if:
    • It lives under project X’s root (own templates), OR
    • Its text contains `` (references to X)
  3. For each template, `` resolves to the owning project’s version
  4. `` resolves dynamically from the alias’s version.txt

Dynamic Cross-Project Resolution

The engine discovers all projects by scanning for .wsb/state.json files in the scan root. When a template references ``:

  1. The engine finds other_lib’s project root from its state.json
  2. Reads {project_root}/version.txt
  3. Parses the version and populates the template variable

Error Handling

All errors are hard failures — no silent fallbacks:

Batch Setup Script

For 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."

Wstemplate Commands

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

Troubleshooting

Hook Not Running

  1. Check if hook is installed: wsb git status
  2. Verify hook file exists: ls -la .git/hooks/pre-commit
  3. Ensure hook is executable: chmod +x .git/hooks/pre-commit

Version Not Updating

  1. Check git repository status: git status
  2. Test manually: wsb git show
  3. Check configuration: wsb git status

Wstemplate Not Rendering

  1. Check entry exists: wsb wstemplate list-entries
  2. Check for relevant templates: wsb wstemplate list
  3. Try explicit render: wsb wstemplate render
  4. Check that dependency projects have version.txt (run wsb update in them)

Removing Version Management

wsb git uninstall        # Remove git hook
rm .state.json            # Remove configuration (optional)
rm version.txt          # Remove version file (optional)
wsb wstemplate remove my_alias  # Remove wstemplate entry (optional)

Logging

State logs all actions to .wsb/logs/wsb.log:

tail -f .wsb/logs/wsb.log

Best Practices

  1. Install Early: Set up versioning when creating a new repository
  2. Use wsb version major: Set major version via database, not git tags
  3. Consistent Workflow: Let the hook handle versioning automatically
  4. Shared Scan Root: For multi-project workspaces, point all projects’ wstemplate to the common root
  5. Run wsb update After Setup: Ensure version.txt exists before other projects reference it
  6. Add .wsb to .gitignore: The .wsb directory is local state — do not commit it

Integration Examples

CI/CD Pipeline

VERSION=$(cat version.txt)
echo "Building version: $VERSION"
docker build -t myapp:$VERSION .

GitHub Actions

- 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 $

Makefile Integration

VERSION := $(shell cat version.txt)

build:
	@echo "Building version $(VERSION)"
	cargo build --release

See Also