Skip to main content

Overview

Vale’s package system allows you to distribute and share complete style configurations, including:
  • Style rules
  • Configuration files
  • Vocabularies and dictionaries
  • Custom templates and scripts
Packages can be loaded from URLs, local paths, or the official Vale library, making it easy to maintain consistent writing standards across teams and projects.

The Sync Command

The vale sync command downloads and installs packages defined in your .vale.ini configuration file.

Basic Usage

vale sync
This command:
  1. Reads the Packages section from your root .vale.ini
  2. Downloads each package from its source (URL, path, or library)
  3. Installs styles into your StylesPath
  4. Merges configuration files into .vale-config/
The sync command shows a progress bar for each package being installed.

Configuration

Define packages in your .vale.ini file:
[*]
BasedOnStyles = Vale, MyCompany

Packages = https://github.com/errata-ai/Microsoft/releases/latest/download/Microsoft.zip, \
           https://github.com/errata-ai/Google/releases/latest/download/Google.zip

Package Sources

Vale supports three types of package sources:
Download packages directly from URLs:
Packages = https://github.com/errata-ai/Microsoft/releases/latest/download/Microsoft.zip
Vale automatically:
  • Downloads the ZIP archive
  • Extracts it to a temporary directory
  • Installs the contents to your StylesPath
Only HTTP(S) protocols are supported. SSH or other protocols will return an error.

Package Structure

A Vale package can contain the following structure:
MyPackage/
├── styles/
│   ├── MyStyle/
│   │   ├── Rule1.yml
│   │   └── Rule2.yml
│   └── config/
│       ├── vocabularies/
│       ├── dictionaries/
│       └── templates/
└── .vale.ini

Package Installation Process

When Vale installs a package, it follows this process (see cmd/vale/sync.go:88-142):
For remote packages:
dir, err := os.MkdirTemp("", name)
if err = fetch(url, dir); err != nil {
    return err
}
Vale creates a temporary directory and downloads the package.
The styles/ directory is copied to your StylesPath:
path := filepath.Join(root, "styles")
if system.IsDir(path) {
    if err := moveDir(path, styles); err != nil {
        return err
    }
}
All style rules are made available immediately.
The config/ directories (vocabularies, templates, etc.) are merged:
for _, dir := range core.ConfigDirs {
    loc1 := filepath.Join(path, dir)
    if system.IsDir(loc1) {
        loc2 := filepath.Join(styles, dir)
        if err := moveDir(loc1, loc2); err != nil {
            return err
        }
    }
}
This preserves your existing configuration while adding package assets.
If the package includes a .vale.ini with its own Packages section:
if system.FileExists(cfg) {
    pkgs, err := core.GetPackages(cfg)
    for idx, pkg := range pkgs {
        if err = readPkg(pkg, styles, idx); err != nil {
            return err
        }
    }
}
Vale recursively installs nested dependencies, creating a complete style pipeline.

Configuration Pipeline

Vale stores package configurations in a special .vale-config/ directory within your StylesPath. This pipeline allows packages to:
  • Define their own configuration
  • Override base settings
  • Include additional packages

Pipeline Structure

StylesPath/
├── .vale-config/
│   ├── 0-Microsoft.ini
│   ├── 1-Google.ini
│   └── 2-MyCompany.ini
├── Microsoft/
├── Google/
└── MyCompany/
Configuration files are numbered to indicate load order.
The .vale-config/ directory is recreated during each sync. Don’t manually edit files here.

Initialization Process

Before syncing, Vale initializes the StylesPath (see cmd/vale/sync.go:15-33):
func initPath(cfg *core.Config) error {
    stylesPath := cfg.StylesPath()
    
    if !system.IsDir(stylesPath) {
        if err := os.MkdirAll(cfg.StylesPath(), os.ModePerm); err != nil {
            return err
        }
    }
    
    // Remove any existing .vale-config directory
    err := os.RemoveAll(filepath.Join(stylesPath, core.PipeDir))
    return err
}
This ensures a clean state for each sync operation.

Example Workflows

Share a common configuration across your team:
  1. Create a repository with your style package:
    company-style/
    ├── styles/
    │   └── Company/
    │       ├── Terminology.yml
    │       └── Branding.yml
    └── .vale.ini
    
  2. Host it on GitHub and create a release
  3. Team members add to their .vale.ini:
    Packages = https://github.com/company/style/releases/latest/download/company-style.zip
    
  4. Run vale sync to install

Error Handling

Vale provides detailed error messages for common issues:
Error: 'https://invalid' is not a valid URL or the directory doesn't exist
Occurs when Vale can’t access the package source. Check:
  • URL is accessible
  • Path exists
  • You have read permissions
Error: unsupported protocol scheme
Vale only supports HTTP(S) URLs. Convert git:// or ssh:// URLs to HTTPS.
If a library name isn’t found:
  • Check spelling
  • Verify the package exists in the library
  • Use the full URL as a fallback

Best Practices

Version Control

Pin package versions using specific release URLs rather than latest for reproducible builds.

Local Development

Use local paths during development, then switch to URLs for production.

Sync Regularly

Run vale sync when:
  • Pulling changes that modify .vale.ini
  • Updating to new package versions
  • Joining a new project

Package Organization

Structure packages with clear directories and include a README explaining the rules.

Build docs developers (and LLMs) love