Repo
Docs
Core Concepts
File Inputs

File Inputs

By default, a workspace is considered to have been updated when any of the files in that workspace have changed. However, not every file change inside of the entire repo should result in rerunning a task. Turborepo gives you the tools to make sure that you can define every file that matters.

Global Files

Almost every repository has some configuration that appears at the root of the repository. These files have the potential to impact the behavior of child workspaces.

package.json and turbo.json

By default, Turborepo includes the root package.json and the root turbo.json file into the global hash. You do not need to specify them separately.

Specifying Additional Inputs

If there are additional files that should be considered for every single workspace, such as a root tsconfig.json you should specify that in globalDependencies:

{
  "$schema": "https://turbo.build/schema.json",
  "globalDependencies": ["tsconfig.json"],
  "pipeline": {
    "type-check": {}
  }
}

This customization is additive to Turborepo's default behavior for package.json and turbo.json.

In this example every single task in the turborepo would be rerun when the root tsconfig.json file changes.

Workspace Files

In addition to global files, which appear outside of any workspace, you may also specify which files to include on a per-workspace basis.

package.json and turbo.json

The contents of each workspaces's package.json and turbo.json (if it exists) are automatically considered for workspace hashes. This behavior is not configurable.

Turborepo's Default Behavior

The default behavior of Turborepo is to inspect the repository and identify which files should be included in the hash calculation. Turborepo typically uses Git to identify which files to consider:

  • All of the files which appear in the Git index which are children of the workspace directory.
  • All of the untracked files which are children of the workspace directory and are not .gitignored.

If Git is not available, or a repository has not been setup, we attempt to approximate the contents which would appear in the Git index using the following strategy:

  • Include all of the files which are children of a workspace directory.
  • Exclude all of the files which appear in the root .gitignore and the workspace directory's .gitignore.

These two approaches do not always produce identical results! The scenarios where this does not produce identical results:

  • .gitignore files at other places in the directory hierarchy.
  • Files added to the Git index which are also specified inside of a .gitignore.

You should aim to have both Git and the Git index of your repository available for maximum correctness.

Customizing the Behavior

Customizing the inputs immediately opts out of the default behavior. You must manually specify via pipeline.<task>.inputs all of the files that should be considered.

For convenience, you can use the special string $TURBO_DEFAULT$ within an inputs array to automatically include all files considered in the default behavior. This allows you to customize the inputs without needing to manually specify all of the files that would have been considered by default.

For some tasks it is worthwhile to reduce the number of file inputs into the task hash consideration. Very few tasks depend on the contents of README.md. Specifying just the files that matter can increase the frequency of cache hits.

For example, in many build tasks the only files that may matter might appear in the src directory. Alternatively, a test task may depend only on files in the src and test directory. You can specify this using glob patterns passed to pipeline.<task>.inputs:

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "inputs": ["src/**"]
    },
    "test": {
      "inputs": ["src/**", "test/**"]
    }
  }
}

These glob patterns are relative to the workspace's path, so, for build inside of the website app, it would treat /apps/website/src/** as file inputs, and, for build inside of the utils workspace it would consider /packages/utils/src/** as file inputs.

If a task depends on another task which specifies file dependencies they do not need to be listed again. Dependency relationships between tasks can be used to ensure that all file dependencies are met:

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "dependsOn": ["^build"],
      "inputs": ["src/**"]
    },
    "test": {
      // This task dependsOn build...
      "dependsOn": ["build"],
      // ...which means that it does not need to specify "src/**" here:
      "inputs": ["test/**"]
    }
  }
}

This pattern can be used to save yourself from needing to repetitively enumerate a list of file globs for every single task.

You may also want to keep the default behavior, but only include, or exclude a few files. You can use the special string $TURBO_DEFAULT$ to include all of the files that would have been considered by default:

{
  "$schema": "https://turbo.build/schema.json",
  "pipeline": {
    "build": {
      "inputs": ["$TURBO_DEFAULT$", "!README.md", "a-git-ignored-file.txt"]
    }
  }
}