Skip to main content
Glob patterns let you include or exclude sets of paths with compact wildcard expressions, similar to regular expressions or .gitignore patterns.
Glob-matching implementations can vary between libraries, so be sure to test your patterns in our environment. Contact us if you have any questions or run into issues.
TokenMeaning
*any run of characters except /
**zero or more path segments
{a,b}brace expansion – either a or b
!patternnegation – exclude matches
?exactly one character except /
[...]one character from the set / range

Examples of Common Patterns

Some everyday use cases for globs:
Use‑casePattern
All files at any depth**
All markdown files at any depth**/*.md
All files in src/src/**
All TypeScript & TSX in src/src/**/*.{ts,tsx}
Only test files (Jest style)**/*.{test,spec}.{ts,tsx}
Everything except node_modules**
!**/node_modules/**

Basic Patterns

Wildcard *

* matches any string within a path segment, but not across directory boundaries.
It’s a common mistake to use * when you meant to use the globstar ** - see below.
pattern: src/*
✅ src/README.md
✅ src/index.ts
❌ src/utils/index.ts  // '*' does not cross directory boundaries

pattern: src/*.ts
✅ src/index.ts
❌ src/README.md       // does not have a .ts extension
❌ src/utils/index.ts  // '*' does not cross directory boundaries

pattern: *
✅ README.md
❌ src/index.ts        // '*' does not cross directory boundaries

Globstar **

** matches any string (including empty) across directory boundaries. Using ** is the most common way to match all files in a directory.
pattern: **
// matches all files everywhere

pattern: src/**
✅ src/main.py
✅ src/utils/func.py
✅ src/utils/foo/bar/baz/func.py
❌ test/test_main.py      // does not match 'src/' prefix

pattern: assets/**/*.png
✅ assets/logo.png
✅ assets/icons/flag/us.png
❌ assets/logo.svg        // does not match '.png' extension

pattern: **/src/**/util/**
✅ src/util/README.md
✅ src/foo/util/bar/README.md
✅ foo/src/bar/util/baz/README.md
❌ src/README.md
❌ util/src/README.md
❌ util/util/README.md
❌ srcutil/README.md

Brace expansion {a,b}

Expands into multiple literal alternatives before matching. So, src/**/*.{ts,tsx} expands into two patterns: src/**/*.ts and src/**/*.tsx
pattern: {src,tests}/**/*.py
✅ src/main/app.py
✅ tests/unit/test_app.py
❌ docs/app.py   // directory not in `src` or `tests`

pattern: src/**/*.{ts,tsx}
✅ src/index.ts
✅ src/index.tsx
✅ src/utils/index.ts
✅ src/utils/index.tsx
❌ src/README.md   // does not match '.ts' or '.tsx' extension
❌ test/index.ts   // does not match 'src/' prefix

Negation !pattern

Prefix a pattern with ! to exclude it. Negation is usually used in conjunction with multiple patterns.Patterns are evaluated in the order they are listed. So, you typically want your first pattern to be the most inclusive, followed by a series of negations.
patterns:
  src/utils/**
  !src/utils/deprecated/**

✅ src/utils/users/main.py
✅ src/utils/analytics/overview.py
❌ src/utils/deprecated/main.py  // negated
❌ test/test_index.py            // did not match any patterns
Make sure to include a negation pattern after the relevant include pattern; otherwise, because patterns are evaluated in order, the negation will have no effect. For example, the list of patterns ["!src/utils/**", "**"] will not exclude anything, and will instead match all files.
patterns:
  src/**
  !src/{deprecated,archived}/**

✅ src/main.py
✅ src/analytics/overview.py
❌ src/deprecated/main.py      // negated
❌ src/archived/overview.py    // negated

Extras

These are less commonly used, but useful to know about.
Match exactly one character from a set or range.
pattern: log[0-9].txt
✅ log1.txt
✅ log7.txt
❌ log10.txt   // two digits
❌ logx.txt    // x not in 0‑9

? matches exactly one character (except /).
pattern: ?.md
✅ a.md
✅ Z.md
❌ README.md   // more than one character before the dot
Extglobs are parenthesized patterns preceded by a single symbol that changes how many times the sub‑pattern(s) may appear.
Think of them as “mini‑regular‑expressions” you can drop directly inside a glob.
SyntaxMeaningHandy mnemonic
@(p1|p2)Exactly one of the alternatives“At” least one – exactly one
?(p)Zero or one occurrence of the patternThe ? you already know means “maybe”
+(p)One or more occurrences+ in regex = “one or more”
*(p)Zero or more occurrences* in regex = “zero or more”
!(p)Anything except the alternatives! = “not”
Inside the parentheses separate alternatives with pipes (|): @(foo|bar|baz).

Quick examples

Using @ with extglobs:
pattern: @(Makefile|*.mk)
✅ Makefile
✅ build.mk
❌ build.mks          // extension differs
Using ! with extglobs:
pattern: src/!(deprecated)/**
✅ src/foo/README.md
✅ src/bar/README.md
❌ src/deprecated/README.md  // negated
❌ src/README.md             // needs to be in a sub-folder of src, not in src directly

pattern: src/**/!(*.test|*.spec).js
# ⟶ JS files that are NOT test or spec files
✅ src/index.js
✅ src/app.js
✅ src/foo/index.js
❌ src/README.md        // no .js extension
❌ src/math.test.js     // negated '.test'
❌ src/calc.spec.js     // negated '.spec'
❌ app.js               // not in src folder
Inline negation is generally not recommended because it can be confusing to read. We recommend splitting into multiple patterns to make it clear which are including and which are excluding. For example, src/**/!(*.test|*.spec).js is equivalent to ["src/**/*.js", "!src/**/*.{test,spec}.js"].
Using * with extglobs:
pattern: src/**/+(components|widgets)/**
# ⟶ Any path containing at least one 'components' or 'widgets' segment
✅ src/components/Button.tsx
✅ src/foo/widgets/Card/index.ts
❌ src/utils/helpers.ts
Using ? with extglobs:
pattern: lib/**/?(index|min).mjs
# ⟶ Either 'index.mjs' or 'min.mjs', but file may be absent
✅ lib/index.mjs
✅ lib/foo/min.mjs
❌ lib/foo/utils.mjs
Using + with extglobs:
pattern: **/backup/*(202[0-3]|old)/**
# ⟶ Folders named 'old' **or** any 2020–2023 year, 0 + times deep
✅ backup/old/data.sql
✅ backup/2021/db.dump
✅ company/backup/2023/archive.tgz

Ellipsis custom handling

To cover some edge cases we commonly see in production, we have some custom handling of glob patterns to reduce footguns.

Forgetting to append /**

It’s common for developers to reach for .gitignore-style patterns, which don’t require using the globstar **. So, we expand patterns that don’t end in /** to include all files in the directory. src => src/** src/ => src/**
pattern: src/
✅ src/index.ts
✅ src/utils/index.ts
❌ srces

Dot‑files

Although dotfiles are commonly excluded by default in many globbing tools, Ellipsis enables them by default.
pattern: **
✅ .foo
✅ dir/.foo

Negation without matching patterns

It’s a common mistake to include a negation pattern without any matching patterns before it. So, if all patterns in a list are negated, Ellipsis will automatically insert a ** pattern to run first in the list to ensure some files are included.
patterns: 
  !src/utils/**  // expanded into ["**", "!src/utils/**"]

✅ README.md
✅ src/index.ts
✅ src/worker/main.py
✅ test/test_index.py
❌ src/utils/users/index.ts
❌ src/utils/analytics/overview.tsx
❌ src/utils/deprecated/index.tsx

Triple stars (***)

Using *** is usually a typo where the user meant to write **. So, we rewrite them to **. *** => ** src/***/foo => src/**/foo