Usage

August 16, 2026 · View on GitHub

This guide covers the degit CLI and ESM API.

Quick start

Download the default branch of a GitHub repo to the current directory:

degit user/repo

Download to a new folder:

degit user/repo my-new-project

Download only specific files:

degit user/repo my-project --files README.md,src/index.ts

Use a specific ref:

degit user/repo#v1.0.0

Installation

npm install -g degit

degit requires Node.js 20 or later.

CLI reference

Basic syntax

degit <src>[#ref] [<dest>] [options]

src is the repository to copy. dest is the directory to extract into; if omitted, degit uses the current directory.

Supported sources

degit supports GitHub, GitLab, Bitbucket, and Sourcehut.

GitHub

degit user/repo
degit github:user/repo
degit https://github.com/user/repo
degit git@github.com:user/repo

GitLab

degit gitlab:user/repo
degit https://gitlab.com/user/repo
degit git@gitlab.com:user/repo

For a self-hosted GitLab instance, use the gitlab:// protocol:

degit gitlab://git.example.com/user/repo

Bitbucket

degit bitbucket:user/repo
degit https://bitbucket.org/user/repo
degit git@bitbucket.org:user/repo

Sourcehut

degit git.sr.ht/user/repo
degit https://git.sr.ht/user/repo
degit git@git.sr.ht:user/repo

Specify a tag, branch, or commit

Append #ref to any source:

degit user/repo#dev           # branch
degit user/repo#v1.2.3        # release tag
degit user/repo#1234abcd      # commit hash

If you omit the ref, degit resolves the repository's default branch.

Create a new folder

If dest is omitted, degit extracts into the current directory. The directory must be empty unless you use --force. Use --repo-name or -r to extract into a directory named after the repository instead:

degit user/repo my-new-project
degit -r user/repo

Clone a subdirectory

Add the subdirectory to the source:

degit user/repo/subdirectory

You can also paste a full GitHub URL:

degit https://github.com/user/repo/tree/main/subdirectory

For GitLab nested groups, degit first tries the two-segment user/repo interpretation, then falls back to treating the path as a nested group.

Clone specific files

To keep only specific files or directories, use --files or -F. Separate paths with commas or repeat the flag:

degit user/repo my-project --files README.md,src/index.ts
degit user/repo my-project -F README.md -F src/index.ts

Missing or out-of-bounds paths are skipped with a warning; if no requested paths resolve, the whole destination is kept.

Options

OptionShortDescription
--help-hShow help text.
--version-VShow the version.
--cache-cOnly use the local cache; do not hit the network.
--force-fAllow cloning into a non-empty destination directory.
--files <paths>-F <paths>Keep only the listed files or directories.
--repo-name-rClone into a directory named after the repository.
--verbose-vPrint extra progress information.
--mode <mode>-mtar (default) or git. --mode=git is accepted for compatibility but prints a deprecation notice.

Run degit --help to see the published help text.

Caching

degit caches downloaded tar snapshots in a platform-appropriate directory:

  • Linux/BSD: $XDG_CACHE_HOME/degit or ~/.cache/degit
  • macOS: ~/Library/Caches/degit
  • Windows: %LOCALAPPDATA%\degit or ~/AppData/Local/degit

By default, degit resolves the latest ref from the network and falls back to the cached version if the network is unreachable. Use --cache to skip the network request and only use a local cached copy.

Private repositories

Private repositories are handled automatically. degit tries the HTTPS tarball path by default and falls back to SSH cloning when it cannot fetch or extract a snapshot. SSH/private repositories still require git on your PATH.

HTTPS proxying

If you set the https_proxy environment variable, degit uses it when fetching tar archives.

Aliases

Save an alias:

degit alias github:user/repo myRepo

Use it:

degit myRepo

Manage aliases:

degit unalias myRepo
degit ls                    # list saved aliases

Aliases are stored in aliases.json inside the degit cache directory.

Interactive mode

Running degit with no arguments starts an interactive picker. It prompts for a source, destination, and whether to use the cache. If the destination is not empty, it asks whether to overwrite.

ESM API

degit can also be used inside a Node script.

Basic example

import degit from 'degit';

const emitter = degit('user/repo', {
	cache: true,
	force: true,
	verbose: true,
});

emitter.on('info', (info) => {
	console.log(info.message);
});

emitter.on('warn', (info) => {
	console.warn(info.message);
});

await emitter.clone('path/to/dest');
console.log('done');

Constructor options

OptionTypeDescription
aliasesRecord<string, string>Alias map used when resolving src.
cachebooleanOnly use local cache; do not hit the network.
fetchFetchFnCustom (url, dest, proxy?) => Promise<void> download function.
filesstring[]Keep only the listed files or directories.
forcebooleanAllow cloning into a non-empty destination.
gitGitClientCustom git client for ref resolution and fallback cloning.
mode'tar' | 'git'Clone mode. tar is the default.
verbosebooleanPrint extra progress information.

Events

The returned emitter exposes two event channels:

  • info — progress and success messages.
  • warn — non-fatal issues, such as skipped paths or fallback notices.

Event objects include at least message. They may also include code, dest, repo, url, ref, and subdir.

degit.json actions

After the initial clone, degit looks for a degit.json file at the top level of the destination and runs the actions it defines. A JSON Schema is available at schemas/degit.schema.json for editor autocompletion and validation.

clone

Clone another repository into the destination, preserving existing files:

[
	{
		"action": "clone",
		"src": "user/another-repo"
	},
	{
		"action": "clone",
		"src": "user/another-repo",
		"files": ["README.md", "src/index.ts"]
	}
]

The cloned repo can define its own degit.json actions.

search_replace

Replace every match of a regular expression in the listed files. The replacement field is the name of an environment variable; its value is used as the replacement string.

[
	{
		"action": "search_replace",
		"files": ["package.json", "README.md"],
		"pattern": "\\{\\{project_name\\}\\}",
		"replacement": "PROJECT_NAME"
	}
]

files can be a single path or an array of paths. Paths are resolved relative to the destination; paths outside the destination are skipped.

remove

Remove one or more files:

[
	{
		"action": "remove",
		"files": ["LICENSE"]
	}
]

files entries support glob patterns, so you can remove a whole class of files without listing each one. Because glob patterns can match more files than intended, they are only processed when allowGlobs is set to true. Matches outside the destination are skipped.

[
	{
		"action": "remove",
		"files": [".github/**/*.md"],
		"allowGlobs": true
	}
]

Why not just git clone --depth 1?

A few salient differences:

  • git clone leaves a .git folder that belongs to the template, not your new project. You can easily forget to re-init the repository.
  • degit caches archives and can work offline after the first download.
  • Less to type (degit user/repo versus git clone --depth 1 ssh://git@github.com/user/repo).
  • Composable post-clone actions through degit.json.
  • Built-in support for subdirectories, file filtering, and aliases.

See also