This guide explains the required environment variables for working with wrkstrm packages and tools. This guide is specifically for M class Macs.
Codex harness reminder
The checked-in Codex CLI harness is a generic profile. New contributors must run through the setup steps below and intentionally opt into repo-specific behaviors (agents, timers, logging). Do not assume the harness auto-detects todo3 conventions; wire them in explicitly during onboarding.
-
Homebrew
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"After installation, make sure Homebrew is in your PATH:
eval "$(/opt/homebrew/bin/brew shellenv)"
-
Development Tools
Install required development tools using Homebrew:
# Install Fastlane for iOS automation and localization brew install fastlane # Install linting tools brew install swiftlint
Install
markdownlint-cli2globally with npm for Markdown linting:npm install -g markdownlint-cli2
-
GitHub Local Runner
Install GitHub's local runner to execute workflows on your machine. For additional configuration options, see GitHub's self-hosted runner documentation:
mkdir actions-runner && cd actions-runner curl -o actions-runner-osx-arm64.tar.gz -L https://github.com/actions/runner/releases/latest/download/actions-runner-osx-arm64.tar.gz tar xzf actions-runner-osx-arm64.tar.gz ./config.sh --url https://github.com/YOUR_ORG/YOUR_REPO --token YOUR_TOKEN ./run.sh
After starting the runner, confirm it shows as
onlinein your repository's Settings > Actions > Runners page. You can verify the installation at any time:./run.sh --version
-
Environment Setup
Add the following to your
~/.zprofile:# Package Steward Configuration # Controls whether to use local dependencies (true) or remote dependencies (false) export SPM_USE_LOCAL_DEPS=true
This environment variable controls dependency resolution behavior:
true: Uses local dependencies for developmentfalse: Uses remote dependencies (useful for CI environments)
-
Install CLIs (preferred: experimental‑install)
Prefer SwiftPM’s install to the user bin so tools are available consistently:
# From a package directory that builds an executable target # Example: CLIA cd code/mono/apple/spm/universal/clia/clia-agent swift package experimental-install --configuration release # Ensure ~/.swiftpm/bin is in your PATH (e.g., in ~/.zprofile) export PATH="$HOME/.swiftpm/bin:$PATH" clia --help
Optional: repo‑local bin for scoped installs (does not touch user PATH):
# From the repo root mkdir -p .clia/bin/swift export PATH="$(pwd)/.clia/bin/swift:$PATH" # optional, current shell only # Build then link a tool into the local bin (example: CLIA) (cd code/mono/apple/spm/universal/clia/clia-agent && swift build -c release) ln -sf "$(pwd)/code/mono/apple/spm/universal/clia/clia-agent/.build/release/clia" \ ".clia/bin/swift/clia"
Notes:
- Preferred:
experimental-installto~/.swiftpm/binfor user‑level availability. - Alternative: repo‑local
.clia/bin/swift/to avoid modifying global PATH.
- Preferred:
Verify your installations:
# Check Homebrew
brew --version
# Check Fastlane
fastlane --version
# Check SwiftLint
swiftlint version
# Check markdownlint
markdownlint-cli2 --version
# Check GitHub Local Runner (run from the actions-runner directory)
./run.sh --versionAfter adding the variable to your .zprofile, verify your setup:
source ~/.zprofile
echo $SPM_USE_LOCAL_DEPSThis should output: true
Use markdownlint-cli2 with the repository's configuration to lint Markdown files:
markdownlint-cli2 --config linting/.markdownlint.jsonc "**/*.md"- Use the Xcode Default toolchain for Apple SDK builds. A mismatched compiler/SDK (e.g., Swift 6.1.x compiler vs Xcode 26 SDK built with Swift 6.2) will fail with Darwin module errors.
- If
swiftly toolchain listdoes not include your current Xcode toolchain, do not force Swiftly; remove the pinned entry (e.g.,swiftly toolchain remove swift-6.1.2-RELEASE) and rely on Xcode Default. - Sanity checks:
xcodebuild -version,xcrun swift --version, and ensureSWIFT_EXEC/TOOLCHAINSare unset.
If you encounter any issues:
-
Update Homebrew and all packages:
brew update && brew upgrade -
Check for any Homebrew problems:
brew doctor
-
Ensure Homebrew's binary location is in your PATH:
echo $PATH | grep brew
If the variable isn't being set:
-
Ensure your
.zprofileis being sourced by adding to.zshrc:if [ -f "$HOME/.zprofile" ]; then source "$HOME/.zprofile" fi
-
Check file permissions:
chmod 600 ~/.zprofile -
Verify the variable after opening a new terminal:
echo $SPM_USE_LOCAL_DEPS
Use the top‑level setup helper to create or update your ~/.zshrc. It prefers the Swift CLI (zshift)
and installs common Zsh extras by default.
bash tools/scripts/setup-zsh.sh -yFlags:
--install-plugins: install fzf, zsh‑autosuggestions, zsh‑syntax‑highlighting via Homebrew (default)--no-install-plugins: skip installing optional plugins--link-only: only link~/.zshrcusing zshift (no installs)--no-backup: skip backup of existing~/.zshrc-y/--yes: non‑interactive mode
If Swift is unavailable, the script falls back to writing the bundled template
(zshift/Sources/Zshift/Resources/zshrc.txt) into ~/.zshrc with clear markers.
zshift is a small Swift utility that links your .zshrc to the shared configuration in this
repository. To run the setup script:
cd zshift
./setup.shAfter running the script, a new .zshrc symlink will be created and your configuration reloaded.
zshift resolves configuration from flags, environment variables, user config files, and bundled team defaults with a clear precedence. This removes hard‑coded lists and keeps behavior predictable across hosts.
- CLI flags (
--excluded-path,--liked-path,--themes-dir) - Environment variables (
ZSHIFT_EXCLUDED,ZSHIFT_LIKED,ZSH_THEMES_DIR) - XDG config:
($ZSHIFT_CONFIG_HOME || $XDG_CONFIG_HOME || ~/.config)/zshift/ - Bundled team defaults (read-only):
Resources/{excluded_zsh_themes.txt, liked_zsh_themes.txt} - Empty (no embedded fallbacks); use
zshift config initto seed user files
The same precedence applies to FIGlet font lists via --excluded-fonts-path, --liked-fonts-path, and the ZSHIFT_FONT_EXCLUDED/ZSHIFT_FONT_LIKED environment variables.
- User config directory:
($ZSHIFT_CONFIG_HOME || $XDG_CONFIG_HOME || ~/.config)/zshift/ - User files (created by
zshift config init):excluded.txt: newline‑delimited theme names to excludeliked.txt: newline‑delimited theme names to preferfonts/excluded.txt: newline‑delimited FIGlet fonts to suppressfonts/liked.txt: newline‑delimited FIGlet fonts to prefer
ZSHIFT_EXCLUDED: path to excluded list fileZSHIFT_LIKED: path to liked list fileZSHIFT_FONT_EXCLUDED: path to excluded FIGlet fonts listZSHIFT_FONT_LIKED: path to liked FIGlet fonts listZSH_THEMES_DIR: path to directory containing.zsh-themefilesZSHIFT_CONFIG_HOME: overrides the config root (defaults to XDG)XDG_CONFIG_HOME: standard XDG config root (defaults to~/.config)ZSHIFT_ZSHRC_TEMPLATE: optional path used bylink-zshrcwhen no flag is passed
zshift random --excluded-path <path> --liked-path <path> --themes-dir <dir> \--excluded-fonts-path <path> --liked-fonts-path <path>zshift like <name> --kind theme|font [--liked-path <path>] [--liked-fonts-path <path>]zshift exclude <name> --kind theme|font [--excluded-path <path>] [--excluded-fonts-path <path>]zshift link-zshrc --custom-zshrc <path> [--backup]
zshift config init [--config-dir <dir>] [--force]- Seeds
excluded.txtandliked.txtunder the user config dir with team defaults.
- Seeds
zshift config show [--json]- Prints resolved paths and sources (flag/env/xdg/bundle).
zshift list available|liked|excluded|available-fonts|liked-fonts|excluded-fonts [--json] \ [--themes-dir <dir>] [--excluded-path <p>] [--liked-path <p>] [--excluded-fonts-path <p>] \ [--liked-fonts-path <p>]- Lists effective theme or FIGlet font entries for scripting or inspection.
# 1) Initialize user config with team defaults
zshift config init
# 2) Pick a theme (excludes liked/excluded lists by default)
zshift random
# 3) Curate your lists
zshift like ys
zshift exclude robbyrussell
# Prefer a FIGlet font
zshift like block --kind font
# 4) Inspect current resolution
zshift config show --json | jq .zshift randomerrors with “No themes directory found”:- Install Oh My Zsh, or provide
--themes-dir /path/to/themes, or setZSH_THEMES_DIR.
- Install Oh My Zsh, or provide
- Team template not found for
link-zshrc:- Provide
--custom-zshrcor setZSHIFT_ZSHRC_TEMPLATE, or runzshift doctorfor hints.
- Provide
- Use
zshift doctorto print resolved config dir, list paths and sources, themes dir, and bundle availability.
zshift uses SwiftFigletKit’s random rendering API to print a themed banner. The equivalent Swift snippet is:
import SwiftFigletKit
let theme = "ys" // dynamically chosen by zshift
let font = SFKFonts.randomName() ?? "standard"
let banner = SFKRenderer.render(
text: "ZShift x " + theme,
font: .named(font),
color: .mixedRandom(),
options: .init(newline: false)
)
let canonicalFont = ZShiftConfig.canonicalFontName(font)
print(banner)
print("FIGLET_FONT=\(canonicalFont)")
print("ZSH_THEME=\(theme)") // the team template expects the theme as the last lineKeep login shells stable by sourcing the shared team template first, then your personal overrides. This ensures the figlet banner and theme logic always run, while your aliases and helpers remain.
-
Replace
~/.zshrcwith this minimal shim:#!/usr/bin/env zsh # wrkstrm ~/.zshrc shim — team first, then personal overrides. : ${ZSHIFT_PATH:="$HOME/todo3/code/mono/apple/spm/configs/zshift"} TEAM_CFG="$ZSHIFT_PATH/Sources/Zshift/Resources/zshrc.txt" PERSONAL_CFG="$HOME/todo3/code/configs/zshrc" LOCAL_CFG="$HOME/.zshrc.local" # Team template (figlet/theme/OMZ) if [[ -f "$TEAM_CFG" ]]; then source "$TEAM_CFG" else print -u2 -- "wrkstrm: team zshrc not found at $TEAM_CFG (set ZSHIFT_PATH?)" fi # Personal overrides [[ -f "$PERSONAL_CFG" ]] && source "$PERSONAL_CFG" [[ -f "$LOCAL_CFG" ]] && source "$LOCAL_CFG"
-
Persist required environment in
~/.zprofile:# Team configs location for the shim export ZSHIFT_PATH="$HOME/todo3/code/mono/apple/spm/configs/zshift" # Ensure repo‑installed SwiftPM tools (e.g., zshift) are on PATH export PATH="$HOME/.swiftpm/bin:$PATH"
-
Open a new Terminal tab or
source ~/.zshrcand verify:- Expect a figlet banner and a final
ZSH_THEME=...line (template parses this to set the theme). command -v zshiftshould resolve (typically~/.swiftpm/bin/zshift).
- Expect a figlet banner and a final
The team template loads a lean, guarded plugin set:
- Base:
git,history-substring-search. - Optional (loaded only if present):
zsh-autosuggestions,zsh-syntax-highlighting(last),xcode(macOS),vscode(whencodeis on PATH). - Explicitly not loaded:
fzf(to avoid warnings on hosts without fzf).
If you need additional plugins, propose changes to the team template rather than duplicating plugin setup in personal configs.