CLI Project Structure

How the Hammer CLI detects your project root, uses marker files, and determines what to build.

How the CLI Finds Your Project

When you run a hammer command, the CLI determines which directory to treat as the project root using this logic:

  1. Explicit path — If you pass --project <path>, that directory is used. If it doesn't exist, the CLI exits with an error.
  2. Marker file search — Without --project, the CLI walks upward from your current working directory looking for a content.config.json or .hammer-ignore file.
  3. Current directory fallback — If no marker files are found in any parent directory, the current directory is used as the project root.

This means you can run hammer build from anywhere inside your project tree and it will find the root automatically.

Tip: Any directory is a valid Hammer project. No configuration file is required for basic HTML/CSS/JS sites. Content Mode features activate only when content.config.json is present.

Project Marker Files

Marker files signal to the CLI where your project root is and how the project should be configured:

content.config.json

Enables Content Mode — collections, templates, field validation, and dynamic page generation. See Content Mode Configuration for the full schema.

.hammer-ignore

Lists glob patterns for files and directories to exclude from builds. Works similarly to .gitignore. For example:

references/
CLAUDE.md
README.md
*.sketch

Files matching these patterns are skipped during the build. They won't be processed or copied to the Build/ directory.

.site-description

A plain-text file containing a description of your site. Used to provide context for AI-assisted tools and reported by hammer info. This file doesn't affect builds.

Build Output

By default, the CLI writes built files to a Build/ directory inside your project root. You can change this with the --output flag:

# Default: Build/ inside the project
hammer build

# Custom output directory
hammer build --output ./dist

The build directory is created automatically if it doesn't exist. On each build, Hammer processes your source files and writes the compiled output to this directory.

Typical Project Layout

A Hammer project using Content Mode typically looks like this:

my-site/
├── assets/               # CSS, JS, images
│   ├── css/
│   ├── js/
│   └── images/
├── content/              # Content files (Markdown, YAML)
│   ├── posts/
│   └── docs/
├── includes/             # HTML partials (header, footer, etc.)
├── public/               # Static assets (copied to Build as-is)
├── templates/            # Content Mode templates
├── Build/                # Compiled output (generated by Hammer)
├── content.config.json   # Content Mode configuration
├── .hammer-ignore        # Files excluded from build
├── .site-description     # Site description for tooling
└── forgerc.txt           # Forge hosting configuration

For simpler sites without Content Mode, a project can be as minimal as a single directory with HTML files:

my-site/
├── index.html
├── about.html
├── includes/
│   ├── _header.html
│   └── _footer.html
├── assets/
│   └── style.css
└── Build/

Working with Projects in Other Directories

Use the --project flag to run commands against a project in a different directory without changing your working directory:

# Build a project elsewhere
hammer build --project /Users/me/Sites/other-project

# Check content in a specific project
hammer check --project ~/Sites/my-blog

# Get info about any project
hammer info --project ./clients/acme-site

This is especially useful for scripts that manage multiple Hammer sites:

# Build all sites in a directory
for site in ~/Sites/*/; do
  echo "Building $site..."
  hammer build --project "$site" --mode export
done

Next Steps