DOC_INDEX
THEME
DOCS/Learn OrchStep/Project Layout

Project Layout

Where files live - workflows, env files, local modules, remote modules, registries, and the cache - shown as directory trees

This chapter is a map. Each scenario below shows the exact files on disk for a way of organizing OrchStep, from a single workflow to a company module registry. Resolution rules are taken from the v0.7.1 module resolver.

1. Single workflow project

The minimum: one file, run from its directory.

my-automation/
`-- orchstep.yml          # tasks live here; `orchstep run <task>`

2. Classic project (workflow + envs + var files)

deploy-checkout/
|-- orchstep.yml          # references env_config: { env_dir: environments }
|-- environments/         # hierarchical env files (see Environments chapter)
|   |-- defaults.yml
|   |-- nonprod.yml
|   |-- nonprod-dev.yml
|   `-- prod-production.yml
|-- overrides/            # ad-hoc --vars-file payloads
|   `-- load-test.yml
`-- README.md
orchstep run deploy --env nonprod-dev
orchstep run deploy --env prod-production --vars-file overrides/load-test.yml

3. Project with local modules

Any directory containing an orchstep.yml is a module - no manifest needed (an "implicit module"):

data-pipeline/
|-- orchstep.yml                    # modules: - {name: source, source: "./modules/sales-source"}
`-- modules/
    |-- sales-source/
    |   `-- orchstep.yml            # the module: defaults + tasks
    |-- quality-gate/
    |   `-- orchstep.yml
    `-- notify/
        |-- orchstep.yml
        `-- orchstep-module.yml     # OPTIONAL manifest: metadata, config
                                    # schema, permissions, exports

The import in the workflow:

modules:
  - name: source
    source: "./modules/sales-source"     # ./ or ../ or absolute = local

4. Remote module from a git repo (single-module repo)

One repo = one module. The repo root is the module root:

github.com/acme/deploy-tools          # the module repository
|-- orchstep.yml                      # module tasks
|-- orchstep-module.yml               # recommended for shared modules
`-- README.md

Consumed as:

modules:
  - name: deploy
    source: "github.com/acme/deploy-tools"     # https:// added automatically
    version: "^1.2.0"                          # resolved against git tags v1.2.0...

5. Scoped registry repo (many modules, one repo)

A registry is a git repo with modules under modules/@<scope>/<name> - this exact layout is how the official registry works:

github.com/orchstep/orchstep          # the default registry repo
`-- modules/
    |-- @orchstep/                    # official tier
    |   |-- health-check/
    |   |   |-- orchstep.yml
    |   |   `-- orchstep-module.yml
    |   |-- git-release/
    |   |   `-- ...
    |   `-- slack-notify/
    |-- @community/                   # verified community tier
    |   `-- github_action_git-checkout/
    `-- @ai/                          # AI-generated tier

Built-in scopes resolve with zero configuration:

modules:
  - name: health
    source: "@orchstep/health-check"        # -> github.com/orchstep/orchstep
    version: "^1.0.0"                       #    subpath modules/@orchstep/health-check

Versioning inside a registry repo uses per-module git tags:

health-check/v1.0.0
git-release/v1.1.2
slack-notify/v2.0.0

6. Company registry (custom scope)

Host your own registry: same layout, your repo, plus one registries: entry. Note the key is the scope without the @:

github.com/examplecorp/orchstep-modules     # your private/internal repo
`-- modules/
    `-- @examplecorp/
        |-- deploy-standards/
        |   |-- orchstep.yml
        |   `-- orchstep-module.yml
        |-- incident-tools/
        `-- compliance-gate/
registries:
  examplecorp:                                   # scope key, no @
    url: "github.com/examplecorp/orchstep-modules"

modules:
  - name: standards
    source: "@examplecorp/deploy-standards"      # resolves into your repo
    version: "~1.4.0"

Tag releases in that repo as deploy-standards/v1.4.0 and consumers pin with semver constraints. (The @private/ scope is different - it is the Pro-licensed private registry feature.)

7. Where remote modules land: the cache

Remote sources are fetched once and cached under your home directory:

~/.orchstep/
`-- cache/
    `-- modules/          # cloned module sources, keyed by source+version

Delete it freely - the next run re-fetches. A project-local orchstep.lock records resolved versions where lockfile support is in use.

Source string cheat sheet (from the resolver)

FormExampleResolves to
Local path./modules/notifythat directory
Git URLgithub.com/acme/toolhttps clone of the repo
Git URL (ssh)git@github.com:acme/tool.gitssh clone
Built-in scope@orchstep/health-checkofficial registry, modules/@orchstep/health-check
Custom scope@examplecorp/xyour registries: repo, modules/@examplecorp/x
Legacygit:https://...#refstill accepted

Where to go next

Using Modules covers config and with: parameter flow; the Modular Data Pipeline use case shows scenario 3 running for real.