Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Introduction

Version License GitHub

stacy is a modern workflow tool for Stata. It runs scripts with proper exit codes, manages packages with lockfiles, and integrates Stata into reproducible pipelines.

For those familiar with other ecosystems:

If you know…stacy is like…Key similarity
RustCargoManifest + lockfile + build orchestration
Pythonuv or PoetryProject dependencies + reproducible environments
JavaScriptnpmpackage.json / package-lock.json workflow
RrenvProject-local library snapshots
Stata(nothing existed)This is what stacy provides

The Problem

Stata’s defaults leave two critical things implicit:

Dependencies are global and unversioned. Packages install to a global path. Versions are whatever SSC has today. When a package updates, every project using it changes silently. A replication package that worked six months ago may fail today because reghdfe changed its defaults.

Execution always returns success. Stata’s batch mode (stata-mp -b do script.do) exits with code 0 even when scripts fail. Errors are buried in logs. Build systems, CI pipelines, and orchestration tools cannot detect failure–they proceed as if nothing went wrong.

The Solution

stacy makes both sides explicit:

# Execution: proper exit codes
stacy run analysis.do
echo $?  # 0 on success, 1-10 on various errors

# Environment: lockfile-based packages
stacy add estout reghdfe    # Adds to stacy.toml, creates stacy.lock
stacy install               # Installs exact versions from lockfile

Now your builds stop on errors and your environments reproduce:

results/output.dta: analysis.do data/input.dta
    stacy run analysis.do   # Stops on failure

Before and After

Without stacyWith stacy
stata -b do script.do returns 0 even on errorstacy run script.do returns 1-10 on error
Packages are global, unversionedstacy.lock pins exact versions
Errors buried in log filesErrors displayed with documentation links
“It worked on my machine”Same versions everywhere via lockfile
Manual ssc install in scriptsstacy install from lockfile

Key Features

FeatureWhat it provides
Proper exit codesMaps 182 official Stata error codes to Unix exit codes
Lockfile managementstacy.lock pins exact versions with SHA256 checksums
Global package cachePackages cached at ~/.cache/stacy/packages/, shared across projects
Build system integrationWorks with Make, Snakemake, CI/CD
Single binaryNo runtime dependencies, easy to deploy

Note: Error detection uses 182 official Stata error codes from the Stata Programming Reference Manual–not heuristics.

Incremental Adoption

Even minimal usage restores critical functionality:

LevelWhat you doWhat you getWho this is for
1stacy run script.doExit codes workAnyone using Make/CI
2stacy initProject configurationTeams wanting standards
3stacy add pkgLocked dependenciesReproducibility needs
4Add [scripts]Task automationComplex workflows
5Integrate with Make/CIFull pipelinePublication-ready research

Quick Example

# Run with error detection
stacy run analysis.do

# Initialize a project and add packages
stacy init
stacy add estout reghdfe

# Install all packages from lockfile (like npm install)
stacy install

# Check system configuration
stacy doctor

How to Use These Docs

Next Steps

Installation

stacy is a single static binary with no runtime dependencies.

Quick Install

macOS / Linux:

curl -fsSL https://raw.githubusercontent.com/janfasnacht/stacy/main/install.sh | bash

Windows (PowerShell):

irm https://raw.githubusercontent.com/janfasnacht/stacy/main/install.ps1 | iex

Both install to ~/.local/bin/ (or equivalent). Ensure this directory is in your PATH.

Other Methods

Homebrew:

brew install janfasnacht/stacy/stacy

Cargo (from source):

cargo install --git https://github.com/janfasnacht/stacy.git

Manual download: Get binaries from the releases page.

Verify Installation

stacy --version    # Check version
stacy doctor       # Check Stata detection and configuration

Stata Detection

stacy automatically finds Stata in common locations:

PlatformSearched paths
macOS/Applications/Stata*/, /Applications/StataNow/
Linux/usr/local/stata*, ~/stata*
WindowsC:\Program Files\Stata*\

If Stata is elsewhere, configure via (in precedence order):

  1. CLI flag: stacy run --engine /path/to/stata-mp script.do
  2. Environment: export STATA_BINARY=/path/to/stata-mp
  3. Config file: ~/.config/stacy/config.toml

Troubleshooting

Common installation issues:

ProblemSolution
stacy: command not foundAdd ~/.local/bin to PATH, restart terminal
macOS blocks binaryRun xattr -d com.apple.quarantine ~/.local/bin/stacy
Stata not foundSet STATA_BINARY env var or config file

See Troubleshooting for detailed solutions.

Updating

Re-run the install command, or:

brew upgrade stacy              # Homebrew
cargo install ... --force     # Cargo

Update Notifications

stacy checks for new releases on startup and prints a notification to stderr if one is available:

Update available: v0.1.0 → v0.2.0
Run `brew upgrade stacy` to update

The check uses a local cache refreshed every 24 hours in the background. It never slows down commands.

Update notifications are automatically suppressed in CI environments, non-interactive sessions, and piped output. To disable globally, set update_check = false in ~/.config/stacy/config.toml or set the STACY_NO_UPDATE_CHECK environment variable.

Uninstalling

rm ~/.local/bin/stacy           # Remove binary
rm -rf ~/.config/stacy          # Remove config (optional)
rm -rf ~/.cache/stacy           # Remove package cache (optional)

Next Steps

Quick Start

1. Verify Setup

stacy doctor

This checks that stacy can find Stata. If it fails, see Troubleshooting.

2. Run a Script

stacy run analysis.do

On success: exit code 0. On failure: non-zero exit code with error details.

❌ Failed: analysis.do (0.08s)

   Error: r(199) - unrecognized command
   See: https://www.stata.com/manuals/perror.pdf#r199

That’s it. Your existing scripts work unchanged.

3. Initialize a Project

stacy init

Creates stacy.toml (project configuration) and .gitignore.

4. Add Packages

stacy add estout reghdfe

This adds packages to stacy.toml, downloads them to the cache, and creates stacy.lock with exact versions.

To install from an existing lockfile:

stacy install

Your dependencies are now pinned. Anyone running stacy install gets the same versions.

5. Define Tasks

Add a [scripts] section to stacy.toml:

[scripts]
clean = "clean_data.do"
analysis = "run_analysis.do"
all = ["clean", "analysis"]

Run tasks by name:

stacy task clean       # Run one script
stacy task all         # Run sequence

This replaces master.do with explicit, named tasks that stop on error.

For complex pipelines with dependency tracking, see Build Integration.

Common Options

stacy run -v analysis.do       # Stream log output
stacy run -c 'display 2+2'     # Run inline code
stacy run --format json ...    # Machine-readable output

Next Steps

Project Config (stacy.toml)

The stacy.toml file configures project-level settings. Created by stacy init.

Location

my-project/
├── stacy.toml    # Project config (this file)
├── stacy.lock    # Package lockfile
└── ...

Full Reference

[project]
name = "my-analysis"
authors = ["Jane Doe <jane@university.edu>"]
description = "Economic analysis of market dynamics"
url = "https://github.com/user/my-analysis"

[run]
log_dir = "logs"
show_progress = true
progress_interval_seconds = 10
max_log_size_mb = 50

[packages.dependencies]
estout = "ssc"
reghdfe = "github:sergiocorreia/reghdfe"

[packages.dev]
assert = "ssc"

[scripts]
clean = "src/01_clean.do"
build = ["clean", "src/02_build.do", "src/03_analyze.do"]

Sections

[project]

Project metadata. Optional but recommended for collaborative projects.

FieldTypeDefaultDescription
namestringdirectory nameProject name
authorsarray[]List of authors
descriptionstringnoneProject description
urlstringnoneProject URL

[run]

Settings for stacy run command.

FieldTypeDefaultDescription
log_dirstring"logs"Directory for log files
show_progressbooltrueShow progress during execution
progress_interval_secondsint10Progress update interval
max_log_size_mbint50Log size warning threshold

[packages.dependencies], [packages.dev], [packages.test]

Package dependencies by group. Format: package_name = "source".

[packages.dependencies]
estout = "ssc"                              # From SSC
reghdfe = "github:sergiocorreia/reghdfe"    # From GitHub

[packages.dev]
assert = "ssc"

[packages.test]
mytest = "ssc"

Sources:

  • "ssc" - Install from SSC
  • "github:user/repo" - Install from GitHub (default branch)
  • "github:user/repo@tag" - Install from GitHub at specific tag/branch

[scripts]

Task definitions for stacy task. Supports three formats:

[scripts]
# Simple: run a single script
clean = "src/01_clean.do"

# Sequential: run tasks/scripts in order
build = ["clean", "src/02_build.do", "src/03_analyze.do"]

# Parallel: run scripts concurrently
test = { parallel = ["test/test1.do", "test/test2.do"] }

Important Notes

Stata Binary

stacy auto-detects Stata in common locations. If detection fails, configure manually:

# Environment variable (recommended)
export STATA_BINARY=/path/to/stata-mp

# Or per-command
stacy run --engine /path/to/stata-mp script.do

# Or user config file (see User Config docs)
stata_binary = "/path/to/stata-mp"

Run stacy doctor to verify detection.

All Fields are Optional

An empty stacy.toml is valid:

# This file can be empty - all fields have defaults

Paths are Relative

Paths in stacy.toml are relative to the project root (e.g., script paths in [scripts]).

Global Package Cache

Packages are installed to a global cache at ~/.cache/stacy/packages/ and shared across all projects. Use stacy cache packages list to view cached packages.

Examples

Minimal

[project]
name = "analysis"

With Packages

[project]
name = "analysis"

[packages.dependencies]
estout = "ssc"
reghdfe = "github:sergiocorreia/reghdfe"

With Tasks

[project]
name = "analysis"

[packages.dependencies]
estout = "ssc"

[scripts]
clean = "src/01_clean.do"
build = ["clean", "src/02_build.do"]
all = ["build", "src/03_report.do"]

CI-Friendly

[project]
name = "analysis"

[run]
show_progress = false  # Cleaner CI logs

Validation

stacy validates the config on load. Invalid TOML causes an error:

Error: Failed to parse stacy.toml: expected `=` at position 15-16

Use stacy env to verify your configuration is loaded correctly.

See Also

User Config (~/.config/stacy/config.toml)

Machine-specific settings that should not be committed to version control.

This is separate from project config (stacy.toml), which lives in the project directory and is shared with collaborators.

Location

PlatformPath
macOS / Linux~/.config/stacy/config.toml
Windows%APPDATA%\stacy\config.toml

Created automatically by stacy init if it doesn’t exist, or create it manually.

Full Reference

# Stata binary path (overrides auto-detection)
stata_binary = "/Applications/StataNow/StataMP.app/Contents/MacOS/stata-mp"

# Check for updates on startup (default: true)
# update_check = false

Fields

stata_binary

Override Stata auto-detection with an explicit path.

# macOS
stata_binary = "/Applications/StataNow/StataMP.app/Contents/MacOS/stata-mp"

# Linux
stata_binary = "/usr/local/stata18/stata-mp"

# Windows
stata_binary = "C:\\Program Files\\Stata18\\StataMP-64.exe"

stacy validates the path on load. If the file doesn’t exist, you’ll get an error with a hint to fix it.

Precedence for Stata binary resolution (highest first):

  1. --engine CLI flag
  2. STATA_BINARY environment variable
  3. stata_binary in user config
  4. Auto-detection from common install paths

update_check

Controls whether stacy checks for new releases on startup. Enabled by default.

# Disable update notifications
update_check = false

When enabled, stacy:

  1. Reads a local cache (~/.cache/stacy/version-check.json) on startup
  2. Prints a notification to stderr if a newer version is available
  3. Refreshes the cache in the background (every 24 hours)

The check never blocks or slows down commands. The background refresh uses the GitHub Releases API with a 3-second timeout.

Environment Variables

These environment variables affect stacy behavior independently of the config file:

VariableEffect
STATA_BINARYStata binary path (overrides config file)
STACY_NO_UPDATE_CHECKSuppress update notifications (set to any value)
CISuppresses update notifications automatically
GITHUB_ACTIONSSuppresses update notifications automatically

Update Notification Suppression

Update notifications are automatically suppressed when:

  • update_check = false in user config
  • STACY_NO_UPDATE_CHECK environment variable is set
  • CI or GITHUB_ACTIONS environment variable is set
  • stderr is not a terminal (piped output, cron jobs, etc.)

The notification looks like:

Update available: v0.1.0 → v0.2.0
Run `brew upgrade stacy` to update

The upgrade instruction adapts to your install method (Homebrew, Cargo, or manual download).

Cache Directory

stacy stores cached data at:

PlatformPath
macOS / Linux~/.cache/stacy/
Windows%LOCALAPPDATA%\stacy\cache\

Contents:

FilePurpose
packages/Global package cache (shared across projects)
version-check.jsonLast update check result
update-availableFlag file for Stata-side notifications

To clean everything: rm -rf ~/.cache/stacy (packages will be re-downloaded on next stacy install).

Examples

Minimal (just Stata path)

stata_binary = "/usr/local/stata18/stata-mp"

CI / headless server

stata_binary = "/usr/local/stata18/stata-mp"
update_check = false

Default (auto-detect everything)

An empty file or no file at all is valid. stacy auto-detects Stata and enables update checks.

See Also

Commands Overview

stacy provides commands for Stata execution, package management, and project workflows.

By Category

Execution

Packages

Project

Utility

Getting Help

stacy --help          # General help
stacy run --help      # Command-specific help

See Exit Codes for exit code reference.

stacy run

Execute a Stata script with error detection

Synopsis

stacy run [SCRIPT] [OPTIONS]

Description

Executes Stata scripts in batch mode and parses log files for errors. Unlike stata-mp -b, returns proper exit codes that reflect whether the script succeeded or failed—enabling integration with Make, Snakemake, and CI/CD.

The command runs Stata with -b -q, parses the log for error patterns, and returns an appropriate exit code (0 for success, 1-10 for various errors).

By default, clean output is shown after execution (boilerplate stripped). On failure, error details with official Stata documentation links and the log file path are displayed. Use -v to stream the raw log in real-time instead, or -q to suppress all output.

Multiple scripts can be run sequentially (default, fail-fast) or in parallel (--parallel). Parallel mode runs all scripts regardless of failures.

For interactive use where you want to quickly check a result, see stacy eval.

Arguments

ArgumentDescription
<SCRIPT>Script to execute

Options

OptionDescription
--cdChange to script’s parent directory
-c, --codeInline Stata code
-C, --directoryRun Stata in this directory
--profileInclude execution metrics
-q, --quietSuppress output
--traceEnable execution tracing at given depth
--verboseExtra output

Examples

Run a script

stacy run analysis.do

Multiple scripts (sequential)

Runs in order, stops on first failure

stacy run clean.do analyze.do report.do

Parallel execution

Run all scripts concurrently for faster execution

stacy run --parallel *.do
stacy run --parallel -j4 a.do b.do c.do

Inline code

Execute Stata code without creating a file

stacy run -c 'display 2+2'
stacy run -c 'sysuse auto, clear
summarize price'

Working directory

Run in a specific directory (script paths resolved before cd)

stacy run -C reports/pilot/ table.do
stacy run --cd reports/pilot/table.do

Verbose output

Stream log file in real-time

stacy run -v long_analysis.do

JSON output

Machine-readable output for CI/CD

stacy run --format json analysis.do

Execution tracing

Enable Stata’s set trace on for debugging

stt run --trace 2 analysis.do
stt run --trace 2 -v analysis.do

Exit Codes

CodeMeaning
0Success
1Stata error (r() code detected)
2Syntax error
3File error (not found, permission denied)
4Memory error
5Internal stacy error
10Environment error (Stata not found)

See Exit Codes Reference for details.

See Also

stacy bench

Benchmark script execution

Synopsis

stacy bench <SCRIPT> [OPTIONS]

Description

Runs a Stata script multiple times and reports timing statistics (mean, median, min, max, stddev). Includes warmup runs by default to account for JIT and caching effects.

Arguments

ArgumentDescription
<SCRIPT>Stata script to benchmark (required)

Options

OptionDescription
--no_warmupSkip warmup runs
-q, --quietSuppress progress output
-n, --runsNumber of measured runs
-w, --warmupNumber of warmup runs

Examples

Benchmark a script

stacy bench analysis.do

Custom run count

stacy bench -n 20 analysis.do

Exit Codes

CodeMeaning
0Success
1Script failed during benchmark
3Script not found

See Exit Codes Reference for details.

See Also

stacy init

Initialize new stacy project

Synopsis

stacy init <PATH> [OPTIONS]

Description

Creates a new stacy project with standard directory structure and configuration. This sets up stacy.toml for project settings and ado/ for local packages.

Run this in an existing directory or specify a path to create a new one.

Arguments

ArgumentDescription
<PATH>Project directory (default: current)

Options

OptionDescription
--forceOverwrite existing files
--nameProject name
--yesSkip interactive prompts (always set in Stata)

Examples

Initialize in current directory

stacy init

Initialize in new directory

stacy init my-project

Initialize with project name

stacy init --name "My Analysis"

Exit Codes

CodeMeaning
0Project created successfully
1Initialization failed

See Exit Codes Reference for details.

See Also

stacy add

Add packages to project

Synopsis

stacy add <PACKAGES> [OPTIONS]

Description

Adds packages to your project’s stacy.toml and installs them. Supports SSC (default) and GitHub sources. Packages are recorded with versions for reproducible installs via stacy install.

Arguments

ArgumentDescription
<PACKAGES>Package names to add (required)

Options

OptionDescription
--devAdd as development dependency
--sourcePackage source: ssc or github:user/repo[@ref]
--testAdd as test dependency

Examples

Add from SSC

stacy add estout
stacy add estout reghdfe

Add from GitHub

stacy add --source github:sergiocorreia/ftools ftools

Add as dev dependency

stacy add --dev assert

Exit Codes

CodeMeaning
0Success
1All packages failed to add

See Exit Codes Reference for details.

See Also

stacy remove

Remove packages from project

Synopsis

stacy remove <PACKAGES> 

Description

Removes packages from stacy.toml and deletes them from the local ado/ directory. Does not affect globally installed packages.

Arguments

ArgumentDescription
<PACKAGES>Package names to remove (required)

Examples

Remove a package

stacy remove estout

Remove multiple packages

stacy remove estout reghdfe

Exit Codes

CodeMeaning
0Success
1No packages removed

See Exit Codes Reference for details.

See Also

stacy update

Update packages to latest versions

Synopsis

stacy update <PACKAGES> [OPTIONS]

Description

Checks for newer versions of installed packages and updates them. Updates both stacy.toml and stacy.lock to reflect new versions. Use --dry-run to preview changes without applying them.

Arguments

ArgumentDescription
<PACKAGES>Package names to update (default: all)

Options

OptionDescription
--dry_runShow what would be updated without making changes

Examples

Update all packages

stacy update

Update specific package

stacy update estout

Preview updates

stacy update --dry-run

Exit Codes

CodeMeaning
0Success
1All updates failed

See Exit Codes Reference for details.

See Also

stacy install

Install packages from lockfile or SSC/GitHub

Synopsis

stacy install <PACKAGE> [OPTIONS]

Description

Installs packages defined in stacy.lock (or stacy.toml if no lockfile exists). This ensures reproducible environments by installing exact versions from the lockfile. Can also install individual packages directly from SSC or GitHub.

Arguments

ArgumentDescription
<PACKAGE>Package name (optional)

Options

OptionDescription
--fromSource: ssc or github:user/repo

Examples

Install from lockfile

Install all packages at locked versions

stacy install

Install specific package

stacy install estout

Exit Codes

CodeMeaning
0Success
1Installation failed
3Package not found

See Exit Codes Reference for details.

See Also

stacy list

List installed packages

Synopsis

stacy list [OPTIONS]

Description

Shows all packages installed in the current project with their versions and sources. Use --tree to group by dependency type (production, dev, test).

Options

OptionDescription
--treeGroup packages by dependency type

Examples

List packages

stacy list

List by dependency group

stacy list --tree

Exit Codes

CodeMeaning
0Success

See Exit Codes Reference for details.

See Also

stacy outdated

Check for package updates

Synopsis

stacy outdated 

Description

Compares installed package versions against the latest available from their sources. Shows which packages have updates available without modifying anything.

Examples

Check for updates

stacy outdated

Exit Codes

CodeMeaning
0Success

See Exit Codes Reference for details.

See Also

stacy lock

Generate or verify lockfile

Synopsis

stacy lock [OPTIONS]

Description

Generates stacy.lock from stacy.toml, recording exact versions of all packages. The lockfile ensures reproducible installs across machines. Use --check in CI to verify the lockfile is up-to-date.

Options

OptionDescription
--checkVerify lockfile matches stacy.toml without updating

Examples

Generate lockfile

stacy lock

Verify lockfile (for CI)

stacy lock --check

Exit Codes

CodeMeaning
0Success / in sync
1Out of sync (with –check)

See Exit Codes Reference for details.

See Also

stacy deps

Show dependency tree for Stata scripts

Synopsis

stacy deps <SCRIPT> [OPTIONS]

Description

Analyzes a Stata script to find all files it depends on (via do, run, include). Shows a tree view of the dependency graph, detects circular dependencies, and identifies missing files.

Arguments

ArgumentDescription
<SCRIPT>Script to analyze (required)

Options

OptionDescription
--flatShow flat list instead of tree

Examples

Show dependency tree

stacy deps main.do

Show flat list

stacy deps --flat main.do

Exit Codes

CodeMeaning
0Analysis complete
3Script not found

See Exit Codes Reference for details.

See Also

stacy task

Run tasks from stacy.toml

Synopsis

stacy task <TASK> [OPTIONS]

Description

Runs named tasks defined in stacy.toml. Tasks are like npm scripts—define sequences of commands once and run them by name. Use --list to see available tasks.

Arguments

ArgumentDescription
<TASK>Task name to run

Options

OptionDescription
--frozenFail if lockfile doesn’t match stacy.toml
--listList available tasks

Examples

Run a task

stacy task build

List available tasks

stacy task --list

Exit Codes

CodeMeaning
0Success
1Task failed
5Task not found

See Exit Codes Reference for details.

See Also

stacy test

Run tests

Synopsis

stacy test <TEST> [OPTIONS]

Description

Discovers and runs test scripts from the test/ directory. Tests are Stata scripts that use assertion commands. Supports filtering, parallel execution, and verbose output for debugging failures.

Arguments

ArgumentDescription
<TEST>Specific test to run

Options

OptionDescription
-f, --filterFilter tests by pattern
--listList tests without running
--parallelRun tests in parallel
-q, --quietSuppress progress output
-V, --verboseShow full log context for failures

Examples

Run all tests

stacy test

Run specific test

stacy test test_regression

Filter tests

stacy test -f 'regression*'

Exit Codes

CodeMeaning
0All tests passed
1One or more tests failed
5Test not found

See Exit Codes Reference for details.

See Also

stacy cache info

Show cache statistics

Synopsis

stacy cache info 

Description

Displays information about the build cache used by stacy run --cache. Shows number of cached entries and approximate size. The cache stores results to skip re-execution of unchanged scripts.

Use stacy cache clean to remove old entries.

Examples

Show cache info

stacy cache info

Clean old entries

stacy cache clean
stacy cache clean --older-than 7

Exit Codes

CodeMeaning
0Success
10Not in project

See Exit Codes Reference for details.

See Also

stacy env

Show environment configuration

Synopsis

stacy env 

Description

Displays the current stacy configuration: Stata binary location, project root, path settings, and adopath order. Useful for debugging configuration issues.

Examples

Show environment

stacy env

Exit Codes

CodeMeaning
0Success
10Environment error (Stata not found)

See Exit Codes Reference for details.

See Also

stacy doctor

Run system diagnostics

Synopsis

stacy doctor 

Description

Checks your system configuration and reports any issues. Verifies Stata installation, project detection, and write permissions. Run this first when troubleshooting.

Examples

Run diagnostics

stacy doctor

Exit Codes

CodeMeaning
0All checks passed
1One or more checks failed

See Exit Codes Reference for details.

See Also

stacy explain

Look up Stata error code details

Synopsis

stacy explain <CODE> 

Description

Displays detailed information about Stata error codes. Includes the error name, category, full description from the Stata Programming Manual, and link to official documentation. Useful for understanding r() return codes.

Arguments

ArgumentDescription
<CODE>Error code (e.g., 199 or r(199)) (required)

Examples

Look up error code

stacy explain 199

Using r() syntax

stacy explain r(601)

Exit Codes

CodeMeaning
0Error code found
1Unknown error code

See Exit Codes Reference for details.

See Also

How It Works

Technical details on stacy’s architecture.

Contents


Error Detection

The Problem

Stata’s batch mode (stata -b do script.do) always exits with code 0, even when scripts fail. Errors are only visible in log files.

stacy’s Solution

  1. Execute: stacy runs Stata with -b -q flags
  2. Parse: After Stata exits, stacy parses the log file
  3. Detect: Matches against 182 official error patterns
  4. Report: Returns appropriate exit code (1-10)
┌───────────┐     ┌───────┐     ┌─────────┐     ┌──────────┐
│ stacy run │ ──▶ │ Stata │ ──▶ │ Log     │ ──▶ │ Exit     │
│           │     │ -b -q │     │ Parser  │     │ Code 0-10│
└───────────┘     └───────┘     └─────────┘     └──────────┘

Error Patterns

stacy recognizes errors in two forms:

r() codes (primary):

r(199);

Error messages (secondary):

unrecognized command: foobar
file myfile.dta not found

Official Stata Error Codes

stacy includes all 182 error codes from the Stata Programming Reference Manual:

RangeCategoryExamples
r(1-99)General errorsr(1) generic error
r(100-199)Syntax/variable errorsr(111) not found, r(199) unrecognized command
r(400-499)System limitsr(459) not sorted
r(600-699)File errorsr(601) file not found, r(603) file exists
r(900-999)Resource errorsr(950) insufficient memory

10 Most Common Errors

CodeNameTypical Cause
r(100)varlist requiredCommand needs variable list
r(109)type mismatchString operation on numeric or vice versa
r(111)not foundVariable doesn’t exist in dataset
r(198)invalid syntaxMalformed command
r(199)unrecognized commandCommand doesn’t exist or package missing
r(459)not sortedData must be sorted
r(601)file not foundFile doesn’t exist
r(603)file already existsNeed replace option
r(950)insufficient memoryOperation too large

Accuracy

Error detection achieves 97% accuracy on common patterns. Edge cases:

  • capture blocks: Intentionally suppressed errors are not reported (captured errors don’t produce r(N); after the “end of do-file” marker)
  • Custom programs: User-written error messages may not match patterns
  • Unusual formatting: Some packages produce non-standard log output

Package Isolation

The Problem

Stata packages install globally to ~/ado/plus/. Every project shares the same versions. When SSC updates a package, all projects change silently.

stacy’s Solution

stacy uses a global cache with per-project isolation:

~/.cache/stacy/packages/
├── estout/
│   ├── 2024.01.15/
│   │   └── estout.ado
│   └── 2024.03.15/
│       └── estout.ado
└── reghdfe/
    └── 6.12.3/
        └── reghdfe.ado

Cache benefits:

  • Multiple versions coexist
  • Shared across projects (disk efficient)
  • Offline installation from cache

Runtime Isolation

When you run stacy run script.do, stacy:

  1. Reads stacy.lock to determine required packages
  2. Builds a custom S_ADO path pointing to cached versions
  3. Launches Stata with this adopath
Project A (stacy.lock):          Project B (stacy.lock):
  estout = 2024.01.15            estout = 2024.03.15
  reghdfe = 6.12.3               reghdfe = 6.12.3

Both use the same cache, but see different versions.

Lockfile Verification

The lockfile includes SHA256 checksums:

[packages.estout]
version = "2024.03.15"
checksum = "sha256:14af94e03edd..."

On stacy install, checksums are verified to ensure:

  • Downloaded files match expected content
  • Cached packages haven’t been modified
  • SSC hasn’t silently updated the package

Output Streaming

Real-time Logs

Use -v (verbose) to stream Stata’s log output as it runs:

stacy run -v long_analysis.do

This displays log lines in real-time, useful for:

  • Monitoring long-running scripts
  • Debugging interactively
  • Seeing progress indicators

Progress Reporting

For scripts without verbose mode, stacy shows periodic progress:

⠋ Running: analysis.do (45s elapsed)

Configure the interval in stacy.toml:

[run]
progress_interval_seconds = 30

Structured Logging

For automated pipelines, combine --format json with verbose output:

stacy run --format json -v analysis.do 2>log.txt
  • stdout: JSON result
  • stderr: Real-time log stream

Machine Interface

stacy is designed for integration with other tools.

JSON Output

Every command supports --format json:

stacy run --format json analysis.do
stacy install --format json
stacy doctor --format json

See JSON Output for complete schemas.

Exit Codes

Stable, semantic exit codes for scripting:

CodeMeaning
0Success
1Stata error
2Syntax error
3File error
4Memory error
5Internal error
10Environment error

See Exit Codes for mapping details.

Build System Integration

stacy’s exit codes enable integration with any tool that respects Unix conventions:

Make:

results.dta: analysis.do
	stacy run analysis.do  # Stops on non-zero

Shell scripts:

stacy run analysis.do || exit 1

CI pipelines:

- run: stacy run analysis.do  # Fails job on error

Programmatic Usage

Python:

import subprocess, json

result = subprocess.run(
    ['stacy', 'run', '--format', 'json', 'analysis.do'],
    capture_output=True
)
data = json.loads(result.stdout)
if not data['success']:
    print(f"Failed: {data['errors']}")

R:

result <- system2("stacy", c("run", "--format", "json", "analysis.do"),
                  stdout = TRUE)
data <- jsonlite::fromJSON(paste(result, collapse = "\n"))

See Also

Lockfile (stacy.lock)

Records installed package versions for reproducible environments. Auto-generated by stacy lock and stacy install.

Purpose

  • Reproducibility: Ensures identical packages across machines and over time
  • Verification: SHA256 checksums detect corruption or tampering
  • Documentation: Records exact sources for each package
  • Collaboration: Teammates get the same versions you tested with

Format Specification

The lockfile uses TOML format with a defined schema:

# Auto-generated by stacy. Do not edit manually.
version = "1"                    # Lockfile format version

[packages.<name>]                # One section per package
version = "<version>"            # Version string (date or semver)
checksum = "sha256:<hash>"       # SHA256 of package contents

[packages.<name>.source]         # Where the package came from
type = "SSC" | "GitHub"          # Source type
name = "<name>"                  # Package name (SSC only)
repo = "<owner>/<repo>"          # Repository (GitHub only)
tag = "<ref>"                    # Git ref (GitHub only)

Annotated Example

# Auto-generated by stacy. Do not edit manually.
# Lockfile format version - stacy checks compatibility
version = "1"

# ─────────────────────────────────────────────────────────────
# SSC Package
# ─────────────────────────────────────────────────────────────
[packages.estout]
# Version comes from SSC metadata (typically a date)
version = "2024.03.15"
# SHA256 hash of all .ado and .sthlp files concatenated
checksum = "sha256:14af94e03edd2e5f12021a8967afe1eee2dc7ebd..."

[packages.estout.source]
type = "SSC"
name = "estout"

# ─────────────────────────────────────────────────────────────
# GitHub Package
# ─────────────────────────────────────────────────────────────
[packages.reghdfe]
# Version from git tag or commit
version = "6.12.3"
checksum = "sha256:8f9234ab12cd56ef78901234567890abcdef..."

[packages.reghdfe.source]
type = "GitHub"
repo = "sergiocorreia/reghdfe"
# Tag, branch, or commit SHA
tag = "v6.12.3"

How Checksums Work

Checksums verify that the installed package matches exactly what was recorded:

  1. On install: stacy downloads the package, computes SHA256 of the contents
  2. On lock: Computed hash is stored in stacy.lock
  3. On verify: Cached package is re-hashed and compared to lockfile

The checksum covers all .ado and .sthlp files in the package, sorted and concatenated. This catches:

  • Corrupted downloads
  • SSC updates that changed the package
  • Manual modifications to cached files

If checksums don’t match, stacy install fails with an error explaining the mismatch.

Fields Reference

FieldRequiredDescription
versionYesLockfile format version (currently “1”)
packages.<name>.versionYesPackage version string
packages.<name>.checksumYesSHA256 hash prefixed with sha256:
packages.<name>.source.typeYes"SSC" or "GitHub"
packages.<name>.source.nameSSC onlyPackage name on SSC
packages.<name>.source.repoGitHub onlyowner/repo format
packages.<name>.source.tagGitHub onlyGit ref (tag, branch, or commit)

Workflow

Creating a lockfile

# Add packages (creates/updates lockfile automatically)
stacy add estout reghdfe

# Or generate lockfile from existing stacy.toml
stacy lock

Installing from a lockfile

# Clone a project
git clone https://github.com/user/project
cd project

# Install exact versions from lockfile
stacy install

Verifying in CI

# Fails if lockfile doesn't match stacy.toml
stacy lock --check

Updating packages

# Update one package to latest
stacy update reghdfe

# Update all packages
stacy update

Version Control

FileCommit?Why
stacy.tomlYesDeclares dependencies
stacy.lockYesEnsures reproducibility
~/.cache/stacy/packages/NoCache, not source

Always commit both stacy.toml and stacy.lock. The lockfile is what ensures everyone gets the same package versions.

Troubleshooting

“Lockfile out of sync”

The lockfile doesn’t match stacy.toml:

stacy lock  # Regenerate

“Checksum mismatch”

The cached package differs from what’s in the lockfile:

stacy cache packages clean  # Clear cache
stacy install               # Re-download

Merge conflicts in lockfile

After a git merge with conflicts:

# Resolve stacy.toml conflicts first, then:
stacy lock  # Regenerate lockfile

See Also

Exit Codes

stacy uses consistent exit codes to indicate success or failure type.

Exit Code Table

CodeNameDescription
0SuccessOperation completed successfully
1Stata ErrorStata r() code detected in log
2Syntax ErrorInvalid Stata syntax
3File ErrorFile not found, permission denied, data errors
4Memory ErrorInsufficient memory
5Internal Errorstacy itself failed (not Stata)
10Environment ErrorStata not found or configuration invalid

Stata r() Code Mapping

stacy maps Stata’s r() error codes to exit codes:

Exit CodeStata r() Codes
1most r() codes not in other categories
2r(198), r(199)
3r(601), r(603), r(610), r(639), r(2000-2999)
4r(950)

Usage

Shell

stacy run analysis.do
echo $?  # 0 on success, 1-10 on failure

Makefile

results.dta: analysis.do
	stacy run analysis.do  # Stops on non-zero exit

Stability

Exit codes 0-10 are stable and will not change meaning. New categories may be added with codes 11+.

See Also

JSON Output

stacy supports JSON output for machine-readable results.

Usage

Add --format json to any command:

stacy run --format json analysis.do
stacy install --format json
stacy env --format json

Output Schemas

stacy run

Success:

{
  "success": true,
  "script": "analysis.do",
  "duration_secs": 12.45,
  "exit_code": 0,
  "log_file": "analysis.log"
}

Failure:

{
  "success": false,
  "script": "analysis.do",
  "duration_secs": 0.45,
  "exit_code": 2,
  "log_file": "analysis.log",
  "errors": [
    {
      "type": "StataCode",
      "r_code": 199,
      "name": "unrecognized command",
      "line": 15,
      "context": "reghdfe price mpg, absorb(make)"
    }
  ]
}
FieldTypeDescription
successboolWhether script completed without errors
scriptstringPath to script that was run
duration_secsfloatExecution time in seconds
exit_codeintstacy exit code (0-10)
log_filestringPath to Stata log file
errorsarrayError details (only on failure)
errors[].typestringError type (StataCode, Syntax, File)
errors[].r_codeintStata r() code if applicable
errors[].namestringHuman-readable error name
errors[].lineintLine number if detected
errors[].contextstringCode that caused the error

stacy install

{
  "success": true,
  "installed": [
    {
      "name": "estout",
      "version": "2024.03.15",
      "source": "SSC"
    },
    {
      "name": "reghdfe",
      "version": "6.12.3",
      "source": "GitHub"
    }
  ],
  "already_cached": [
    {
      "name": "ftools",
      "version": "2.49.0",
      "source": "SSC"
    }
  ],
  "failed": []
}
FieldTypeDescription
successboolWhether all packages installed
installedarrayPackages downloaded this run
already_cachedarrayPackages found in cache
failedarrayPackages that failed to install

stacy list

{
  "packages": [
    {
      "name": "estout",
      "version": "2024.03.15",
      "source": "SSC",
      "locked": true
    },
    {
      "name": "reghdfe",
      "version": "6.12.3",
      "source": "GitHub",
      "locked": true
    }
  ]
}

stacy env

{
  "stata": {
    "binary": "/Applications/StataNow/StataMP.app/Contents/MacOS/stata-mp",
    "version": "18.0",
    "flavor": "MP",
    "source": "user config"
  },
  "project": {
    "root": "/Users/user/projects/analysis",
    "has_config": true,
    "has_lockfile": true
  },
  "cache": {
    "path": "/Users/user/.cache/stacy/packages",
    "package_count": 12
  }
}

stacy doctor

{
  "ready": true,
  "checks": [
    {
      "name": "Stata binary",
      "status": "ok",
      "message": "Found at /Applications/StataNow/StataMP.app/Contents/MacOS/stata-mp"
    },
    {
      "name": "Stata version",
      "status": "ok",
      "message": "Stata 18.0 MP"
    },
    {
      "name": "Project config",
      "status": "ok",
      "message": "Found stacy.toml"
    },
    {
      "name": "Lockfile",
      "status": "warning",
      "message": "No stacy.lock found"
    }
  ]
}
StatusMeaning
okCheck passed
warningNon-blocking issue
errorBlocking issue

stacy deps

{
  "root": "master.do",
  "files": [
    "master.do",
    "config/settings.do",
    "src/01_clean_data.do",
    "src/utils/helpers.do"
  ],
  "missing": [],
  "circular": []
}

jq Examples

Check if a run succeeded

stacy run --format json analysis.do | jq '.success'

Get exit code

stacy run --format json analysis.do | jq '.exit_code'

Extract error codes

stacy run --format json analysis.do | jq '.errors[]?.r_code'

List installed package names

stacy list --format json | jq -r '.packages[].name'

Get Stata binary path

stacy env --format json | jq -r '.stata.binary'

Check if project has lockfile

stacy env --format json | jq '.project.has_lockfile'

Find failed doctor checks

stacy doctor --format json | jq '.checks[] | select(.status == "error")'

Count dependencies

stacy deps --format json master.do | jq '.files | length'

Get packages that need downloading

stacy install --format json | jq '.installed[].name'

Using JSON in Scripts

Shell

#!/bin/bash
result=$(stacy run --format json analysis.do)
if echo "$result" | jq -e '.success' > /dev/null; then
    echo "Success!"
else
    echo "Failed with errors:"
    echo "$result" | jq -r '.errors[].name'
    exit 1
fi

Python

import subprocess
import json

result = subprocess.run(
    ['stacy', 'run', '--format', 'json', 'analysis.do'],
    capture_output=True,
    text=True
)
data = json.loads(result.stdout)

if data['success']:
    print(f"Completed in {data['duration_secs']:.2f}s")
else:
    for error in data.get('errors', []):
        print(f"Error r({error['r_code']}): {error['name']}")

R

library(jsonlite)

result <- system2("stacy", c("run", "--format", "json", "analysis.do"),
                  stdout = TRUE, stderr = TRUE)
data <- fromJSON(paste(result, collapse = "\n"))

if (data$success) {
  cat(sprintf("Completed in %.2fs\n", data$duration_secs))
} else {
  cat("Errors:\n")
  print(data$errors)
}

Stability

The JSON schema follows semantic versioning:

  • Core fields (success, exit_code, errors) are stable from v1.0
  • New fields may be added in minor versions (backward compatible)
  • Field removal or type changes only in major versions

Tip: Use jq’s -e flag to handle missing fields gracefully in scripts.

See Also

Build Integration

stacy integrates with build systems through standard Unix exit codes. Any tool that stops on non-zero exit works with stacy.

Quick Examples

Make:

results.dta: analysis.do data.dta
	stacy run analysis.do

Snakemake:

rule analysis:
    input: "analysis.do", "data.dta"
    output: "results.dta"
    shell: "stacy run {input[0]}"

Shell:

stacy run step1.do && stacy run step2.do

GNU Make

Basic Makefile

STATA := stacy run

# Final output depends on analysis
results/tables.tex: src/03_tables.do results/estimates.dta
	$(STATA) $<

# Estimates depend on clean data
results/estimates.dta: src/02_analysis.do data/clean.dta
	$(STATA) $<

# Clean data depends on raw data
data/clean.dta: src/01_clean.do data/raw.dta
	$(STATA) $<

.PHONY: all clean
all: results/tables.tex
clean:
	rm -f data/clean.dta results/*.dta results/*.tex

With Package Installation

.PHONY: install
install:
	stacy install

results.dta: analysis.do | install
	stacy run $<

See GNU Make documentation for more patterns.


Snakemake

Basic Snakefile

rule all:
    input: "results/tables.tex"

rule clean:
    input: "src/01_clean.do", "data/raw.dta"
    output: "data/clean.dta"
    shell: "stacy run {input[0]}"

rule analysis:
    input: "src/02_analysis.do", "data/clean.dta"
    output: "results/estimates.dta"
    shell: "stacy run {input[0]}"

rule tables:
    input: "src/03_tables.do", "results/estimates.dta"
    output: "results/tables.tex"
    shell: "stacy run {input[0]}"

Parallel Execution

snakemake --cores 4

See Snakemake documentation for workflows, clusters, and more.


CI/CD

GitHub Actions

# .github/workflows/analysis.yml
name: Analysis
on: [push, pull_request]

jobs:
  build:
    runs-on: self-hosted  # With Stata installed
    steps:
      - uses: actions/checkout@v4

      - name: Install stacy
        run: |
          curl -fsSL https://raw.githubusercontent.com/janfasnacht/stacy/main/install.sh | bash
          echo "$HOME/.local/bin" >> $GITHUB_PATH

      - name: Install packages
        run: stacy install --frozen

      - name: Run analysis
        run: stacy run analysis.do

      - name: Upload results
        uses: actions/upload-artifact@v4
        with:
          name: results
          path: output/

Note: --frozen fails if lockfile doesn’t match stacy.toml, catching uncommitted dependency changes.

GitLab CI

# .gitlab-ci.yml
analysis:
  stage: build
  before_script:
    - curl -fsSL https://raw.githubusercontent.com/janfasnacht/stacy/main/install.sh | bash
    - export PATH="$HOME/.local/bin:$PATH"
    - stacy install
  script:
    - stacy run analysis.do
  artifacts:
    paths: [output/]

Caching Packages

- uses: actions/cache@v4
  with:
    path: ~/.cache/stacy/packages/
    key: stata-packages-${{ hashFiles('stacy.lock') }}

Stata Licensing in CI

Stata requires a license. Options:

  1. Self-hosted runner with Stata installed
  2. Docker container with Stata
  3. Skip Stata steps in CI (validate config only)

See GitHub Actions docs or GitLab CI docs for more.


Best Practices

  1. Use --frozen in CI to catch lockfile drift
  2. Commit stacy.lock for reproducibility
  3. Cache packages to speed up builds
  4. Use JSON output for programmatic checks: stacy run --format json
  5. Upload artifacts on failure for debugging

See Also

Migration Guide

How to adopt stacy in existing Stata projects.

Overview

stacy works with existing Stata scripts unchanged. Migration is incremental–start with error detection, add package management when ready.

Current workflowstacy equivalent
stata -b do script.dostacy run script.do
ssc install pkgstacy add pkg
master.do[scripts] section

From Batch Mode to stacy run

Before

stata-mp -b do analysis.do
# Always exits 0, even on error
# Must manually check analysis.log

After

stacy run analysis.do
# Exits 1-10 on error
# Shows error with documentation link

What changes:

  • Exit codes now reflect success/failure
  • Errors display with Stata documentation links
  • Build systems (Make, Snakemake) can detect failures

What stays the same:

  • Your .do files work unchanged
  • Output goes to the same log file
  • Stata runs in the background

Updating scripts

For shell scripts that check logs:

# Before: parse log for errors
stata-mp -b do analysis.do
if grep -q "^r(" analysis.log; then
    echo "Error!"
    exit 1
fi

# After: just check exit code
stacy run analysis.do
if [ $? -ne 0 ]; then
    echo "Error!"
    exit 1
fi

# Or more simply
stacy run analysis.do || exit 1

From ssc install to Lockfiles

Before

* At the top of master.do or a setup script
ssc install estout
ssc install reghdfe

Problems:

  • Different versions on different machines
  • “It worked last month” failures
  • No record of what’s actually installed

After

# One-time setup
stacy init
stacy add estout reghdfe

# Creates stacy.toml (what you want) and stacy.lock (what you have)
git add stacy.toml stacy.lock
git commit -m "Add stacy package management"

For collaborators:

git pull
stacy install  # Gets exact same versions

Step-by-step migration

  1. List current packages

    ado dir
    
  2. Initialize stacy

    stacy init
    
  3. Add each package

    stacy add estout reghdfe ftools
    
  4. Remove ssc install lines from scripts Delete or comment out ssc install commands–stacy handles this now.

  5. Commit both files

    git add stacy.toml stacy.lock
    git commit -m "Switch to stacy package management"
    

Handling GitHub packages

If you install from GitHub:

* Before
net install reghdfe, from("https://raw.githubusercontent.com/sergiocorreia/reghdfe/master/src/")
# After
stacy add github:sergiocorreia/reghdfe

From master.do to [scripts]

Before

* master.do
do "01_clean_data.do"
do "02_analysis.do"
do "03_tables.do"

Problems:

  • Running one script requires editing master.do
  • No parallelization
  • Error in script 2 still runs script 3 (unless you add capture logic)

After

Add to stacy.toml:

[scripts]
clean = "01_clean_data.do"
analysis = "02_analysis.do"
tables = "03_tables.do"
all = ["clean", "analysis", "tables"]

Run individual tasks or sequences:

stacy task clean      # Run just cleaning
stacy task analysis   # Run just analysis
stacy task all        # Run all in order

Benefits:

  • Named tasks are self-documenting
  • Each task stops on error by default
  • Can run tasks individually for debugging

Keeping master.do

You don’t have to remove master.do. Both can coexist:

# Using stacy tasks
stacy task all

# Or using master.do through stacy (still get exit codes)
stacy run master.do

From Make to Make + stacy

If you already use Make:

Before

%.log: %.do
    stata-mp -b do $<

After

%.log: %.do
    stacy run $<

That’s it. Make now stops on Stata errors.

Adding package management

# Ensure packages are installed before running
.PHONY: install
install:
    stacy install

results/analysis.dta: analysis.do install
    stacy run analysis.do

Checklist

Minimal migration (exit codes only)

  • Install stacy
  • Replace stata -b do with stacy run in scripts/Makefile
  • Verify stacy doctor passes

Full migration (packages + tasks)

  • Run stacy init
  • Add packages with stacy add
  • Remove ssc install lines from scripts
  • Add [scripts] section for common tasks
  • Commit stacy.toml and stacy.lock
  • Update CI to run stacy install before tests
  • Tell collaborators to run stacy install after pulling

See Also

FAQ

Getting Started

Do I need to change my Stata scripts?

No. stacy runs your existing .do files unchanged.

Can I use stacy with existing projects?

Yes. Run stacy init in any directory to create stacy.toml. Existing scripts work as before.

What if I don’t use Make or Snakemake?

stacy works standalone. You get error detection, lockfile packages, and the task runner:

[scripts]
clean = "clean_data.do"
all = ["clean", "analysis.do"]
stacy task all

How is stacy different from batch mode?

Batch modestacy
Always exits 0Exits 1-10 on errors
Errors in log onlyErrors shown with docs link
No package managementLockfile pins versions

Package Management

How is the lockfile different from net install?

net install gets whatever version exists today. The lockfile records exact versions with checksums. stacy install reproduces those exact versions.

Can I use packages not on SSC?

Yes:

stacy add github:sergiocorreia/reghdfe
stacy add github:user/repo@v1.2

What happens if SSC is down?

Packages are cached at ~/.cache/stacy/packages/. Cached packages work offline.

Where are packages stored?

Global cache at ~/.cache/stacy/packages/, organized by name/version. stacy sets S_ADO at runtime for project isolation.

Technical

How does stacy detect errors?

Runs Stata with -b -q, parses the log for r() patterns, returns appropriate exit code. See How It Works.

Does stacy modify my Stata installation?

No. stacy manages packages in its own cache and sets S_ADO at runtime.

What are the exit codes?

CodeMeaning
0Success
1Stata error
2Syntax error
3File error
4Memory error
5Internal error
10Environment error

Updates

Does stacy check for updates automatically?

Yes. On startup, stacy checks a local cache for available updates and prints a notification to stderr. The cache is refreshed in the background every 24 hours via the GitHub Releases API. This never blocks or slows down commands.

How do I disable update checks?

Either set update_check = false in ~/.config/stacy/config.toml, or set the STACY_NO_UPDATE_CHECK environment variable. Update checks are also suppressed automatically in CI and non-interactive environments. See User Config for details.

Compatibility

Does stacy work on Windows?

Yes. Windows, macOS, and Linux.

Which Stata versions are supported?

Stata 14+ (MP, SE, BE, StataNow).

Can I use stacy in Docker?

Yes. Set STATA_BINARY environment variable.

Does stacy work with Stata GUI?

stacy is for command-line workflows (batch mode). Use Stata directly for interactive work.

Troubleshooting

Installation

stacy: command not found

Add ~/.local/bin to PATH:

export PATH="$HOME/.local/bin:$PATH"  # add to ~/.zshrc

Restart terminal.

Installation script fails

mkdir -p ~/.local/bin
curl -fsSL https://raw.githubusercontent.com/janfasnacht/stacy/main/install.sh | bash

macOS blocks the binary

xattr -d com.apple.quarantine ~/.local/bin/stacy

Stata Detection

Stata not found

Set path explicitly:

export STATA_BINARY=/path/to/stata-mp

Or create ~/.config/stacy/config.toml:

stata_binary = "/path/to/stata-mp"

Run stacy doctor to verify.

Wrong Stata version detected

stacy env  # see what was found
export STATA_BINARY=/path/to/correct/stata-mp

Permission denied running Stata

chmod +x /path/to/stata-mp

Runtime

Exit code doesn’t match error

Possible causes:

  • Script uses capture to suppress errors
  • stacy only catches r() errors, not warnings
  • Custom program writes non-standard messages

Report missed errors.

Script works in GUI but fails with stacy

Working directory: stacy runs from current shell directory.

Missing packages: Run stacy add packagename.

Profile.do: stacy uses -q flag, skipping profile.do.

Log file not found

Check write permissions. Try stacy run -v script.do for verbose output.

Packages

Failed to download from SSC

Check network: curl -I https://www.stata.com

Retry: stacy add packagename

Checksum mismatch

SSC updated the package: stacy update packagename

Or clear cache: stacy cache packages clean && stacy install

Package installed but Stata can’t find it

stacy list  # verify it's listed

Check package docs for unlisted dependencies.

Lockfile

Conflicts after git merge

Resolve stacy.toml conflicts first, then:

stacy lock

Lockfile out of sync

stacy lock          # regenerate
stacy lock --check  # verify

Different results on teammate’s machine

  1. Verify lockfile committed: git status stacy.lock
  2. Both have same lockfile: git diff origin/main -- stacy.lock
  3. Reinstall: stacy install
  4. Check Stata versions: stacy env

Update Notifications

How do I disable update notifications?

Set update_check = false in ~/.config/stacy/config.toml:

update_check = false

Or set an environment variable:

export STACY_NO_UPDATE_CHECK=1

Notifications don’t appear

Update notifications are suppressed when:

  • stderr is not a terminal (piped output, cron, scripts)
  • CI or GITHUB_ACTIONS environment variable is set
  • STACY_NO_UPDATE_CHECK environment variable is set
  • update_check = false in user config

If you want to check manually: stacy --version and compare with the releases page.

Notification shows wrong upgrade command

stacy detects the install method from the binary path. If detection is wrong (e.g., after moving the binary), the fallback shows the GitHub releases URL.

Getting Help

  1. Run stacy doctor
  2. Run failing command with -v
  3. Open an issue

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

Unreleased

1.0.0 - 2026-02-15

Initial public release.

Added

  • stacy run — Execute Stata scripts with proper error detection and exit codes
  • stacy run -c — Run inline Stata code
  • stacy run --parallel — Parallel execution of multiple scripts
  • stacy init — Initialize project with stacy.toml
  • stacy add / stacy remove — Manage dependencies
  • stacy install — Reproducible installs from lockfile
  • stacy update / stacy outdated — Keep packages current
  • stacy lock — Generate and verify lockfile
  • stacy task — Task runner (npm-style scripts in stacy.toml)
  • stacy deps — Script dependency analysis
  • stacy env / stacy doctor — Environment diagnostics
  • stacy explain — Error code lookup
  • Error codes dynamically extracted from user’s Stata installation
  • SSC and GitHub package sources (github:user/repo@tag)
  • Global package cache at ~/.cache/stacy/packages/
  • --format json and --format stata output modes
  • Cross-platform support: macOS, Linux, Windows

Contributing