home / skills / gwenwindflower / .charmschool / gitignore

This skill generates advanced .gitignore templates tailored to project type, ensuring precise file exclusion and clean repositories.

npx playbooks add skill gwenwindflower/.charmschool --skill gitignore

Review the files below or copy the command above to add this skill to your agents.

Files (1)
SKILL.md
2.3 KB
---
name: gitignore
description: Generate advanced and comprehensive .gitignore files based on project type, using stringent syntax for selecting and excluding files and directories.
---
# .gitignore Creation and Management

## Templates and Initial Scaffolding

The GitHub CLI (`gh`) has a `gh repo gitignore` command that can be used to fetch templates from GitHub's collection. `gh repo gitignore list` will output the list of templates in GitHub's collection to stdout. When you have the name of the one you want, use `gh repo gitignore view [TEMPLATE]` to have the content output to stdout, which you can redirect to a `.gitignore` file or wherever you need it. This is the easiest way to spike out the boilerplate for a given project type.

The rest of the Skill covers manually adding entries in gitignore syntax for the specific project you're working in.

## `/path` vs `path/` vs `path`

| Pattern | Meaning |
| --------- | --------- |
| `path/` | Matches a **directory** named `path` (and its contents) |
| `path` | Matches both **files AND directories** named `path` |
| `/path` | Matches `path` **relative to the .gitignore file's location** (anchored path) |

**Examples:**

- `build/` ignores the `build` directory and all its contents
- `build` ignores any file or directory named `build` anywhere in the tree
- `/build` ignores only the `build` directory in the same folder as the .gitignore

## Wildcard/Globbing Patterns

Git uses fnmatch-style patterns:

| Pattern | Matches |
| --------- | --------- |
| `*` | Any sequence of characters (except `/`) |
| `**` | Any sequence of directories (including zero) |
| `?` | Any single character |
| `[abc]` | Any one character in the set |
| `[a-z]` | Any one character in the range |

**Examples:**

- `*.log` ignores all `.log` files
- `**/node_modules` ignores `node_modules` at any depth
- `src/*.js` ignores `.js` files directly in `src/`
- `file?.txt` matches `file1.txt`, `file2.txt`, etc.
- `a/**/b` matches `a/b`, `a/x/b`, `a/x/y/b`
- `/**/b` matches `b` anywhere in the tree

## Negation and Special Patterns

| Pattern | Purpose |
| --------- | --------- |
| `!pattern` | **Negates** — re-includes previously ignored files |
| `#` | Comment line |
| `\` | Escape character for literal patterns |

**Example:**

```gitignore
# Ignore all .log files
*.log

# But not this specific one
!important.log
```

Overview

This skill generates advanced and comprehensive .gitignore files tailored to your project type, using precise gitignore syntax and patterns. It produces scaffolding from common templates and refines entries with anchored paths, wildcards, and negations to minimize accidental commits. The output emphasizes clarity and maintainability so teams can rely on a consistent ignore strategy.

How this skill works

The skill can scaffold a starter .gitignore based on project type and then refine rules using anchored paths (/path), directory-only matches (path/), and loose matches (path). It applies fnmatch-style globbing (*, **, ?, [sets], [ranges]) to handle files and directories at any depth, and supports explicit negation (!pattern) to re-include necessary files. Comments (#) and escapes (\) are used to document and preserve literal patterns.

When to use it

  • Initializing a new repository and creating a minimal, correct .gitignore
  • Converting informal ignore lists into strict, anchored rules for clarity
  • Adding exclusions for build artifacts, logs, secrets, or dependency folders
  • Preserving a small set of committed files while ignoring broader patterns
  • Creating cross-project dotfiles for consistent developer environments

Best practices

  • Prefer anchored paths (/path) for repo-root directories to avoid accidental global matches
  • Use directory-only patterns (path/) when you intend to ignore a folder and its contents
  • Use ** to express depth-insensitive ignores (e.g., **/node_modules) for nested dependencies
  • Add negation rules (!pattern) after the broader ignore to re-include necessary tracked files
  • Comment groups of rules to explain why items are ignored and reduce surprise for teammates

Example use cases

  • Generate a Node.js .gitignore that ignores node_modules/, dist/, *.log and re-includes a tracked config file
  • Create a Python .gitignore that excludes venv/ and __pycache__/, while allowing a tracked requirements.txt
  • Scaffold a build-focused .gitignore that ignores build/, *.o, and coverage/ but keeps README.md
  • Convert a flat list of ignored names into precise patterns using /path, path/, and ** for depth

FAQ

When should I use /path vs path/?

/path anchors the match to the .gitignore location (use for repo-root folders). path/ matches any directory named path at any depth and ignores its contents.

How do I keep one file inside an ignored folder?

Ignore the folder first (e.g., logs/), then add a negation for the file path after (e.g., !logs/important.log). Ensure the negation is not shadowed by earlier rules.