This document covers advanced configuration options and features in pks.
Packs first mode can be used if your entire team is using packs. Currently, the only thing this does is change the copy in package_todo.yml files to reference pks instead of packwerk.
There are two ways to enable this:
- Rename
packwerk.ymltopacks.ymland packs first mode will be automatically enabled. - Set
packs_first_mode: truein yourpackwerk.yml
By default, pks automatically respects .gitignore files when analyzing your codebase. This means any files or directories listed in your .gitignore will be excluded from pack analysis.
This feature:
- ✅ Reduces noise by excluding generated files, temporary files, and vendor code
- ✅ Improves performance by skipping ignored directories during traversal
- ✅ Works automatically without any configuration
- ✅ Can be disabled if you need behavior identical to
packwerk
pks checks multiple gitignore sources in this order:
- Local
.gitignore- The.gitignorefile in your repository root - Global gitignore - Your user-level gitignore file from
git config --global core.excludesFile - Git exclude file - The
.git/info/excludefile in your repository
All standard gitignore features are supported:
- Pattern matching (e.g.,
*.log,tmp/) - Directory exclusion (e.g.,
node_modules/) - Negation patterns (e.g.,
!important.log) - Comments (lines starting with
#)
If you need to disable automatic gitignore support, add this to your packwerk.yml or packs.yml:
# Disable automatic gitignore support
respect_gitignore: falseYou might want to disable gitignore support if:
- You have files in
.gitignorethat should still be analyzed bypks - You're migrating from
packwerkand want identical behavior - You have custom
exclude:patterns that you prefer to manage manually - You need to analyze generated code that's normally gitignored
If not specified, respect_gitignore defaults to true (enabled).
When determining whether to process a file, pks applies rules in this order (highest priority first):
- Include patterns - Files matching
include:patterns in configuration - Gitignore patterns - Files/directories in
.gitignore(ifrespect_gitignore: true) - Exclude patterns - Files matching
exclude:patterns in configuration - Default exclusions - Hardcoded exclusions (e.g.,
{bin,node_modules,script,tmp,vendor}/**/*)
This precedence allows you to:
- Override gitignore by explicitly including files via
include:patterns - Add additional exclusions beyond what's in
.gitignoreviaexclude:patterns - Layer multiple levels of filtering for fine-grained control
# packwerk.yml
# Enable gitignore support (this is the default)
respect_gitignore: true
# Include patterns (highest priority - override gitignore)
include:
- "**/*.rb"
- "**/*.rake"
- "**/*.erb"
# Exclude patterns (lower priority than gitignore)
exclude:
- "{bin,node_modules,script,tmp,vendor}/**/*"
- "test/fixtures/**/*"Example scenario:
Given this configuration and a .gitignore containing debug.log:
app/models/user.rb→ ✅ Analyzed (matches include pattern)tmp/cache/foo.rb→ ❌ Skipped (matches default exclusion)debug.log→ ❌ Skipped (matches gitignore)test/fixtures/data.rb→ ❌ Skipped (matches exclude pattern)
When respect_gitignore: true (default):
- ✅ Files in
.gitignoreare automatically skipped during directory walking - ✅ Directories in
.gitignoreare not traversed (improves performance) - ✅ Global gitignore patterns are applied
- ✅ Gitignore negation patterns (e.g.,
!important.log) are respected - ✅
.git/info/excludepatterns are applied
When respect_gitignore: false:
- ❌
.gitignorefiles are completely ignored - ✅ Only
include:andexclude:patterns from configuration are used - ✅ Behavior matches
packwerkexactly
Enabling gitignore support typically has neutral to positive performance impact:
- ✅ Ignored directories are skipped entirely (faster directory walking)
- ✅ Fewer files need to be processed
- ✅ Pattern matching is highly optimized (uses the same engine as
ripgrep) - ✅ Gitignore matcher is built once and reused throughout the walk
In practice, this means:
- Large ignored directories like
node_modules/,tmp/, orvendor/are skipped immediately - No time wasted parsing or analyzing files that would be ignored anyway
- Memory usage is lower due to fewer files being tracked
If files are being ignored that shouldn't be:
-
Check your
.gitignore- Rungit check-ignore -v path/to/file.rbto see which pattern is matchinggit check-ignore -v app/models/user.rb # Output: .gitignore:10:*.rb app/models/user.rb -
Check global gitignore - See where your global gitignore is configured:
# Check if core.excludesFile is set git config --global core.excludesFile # Output: /Users/you/.config/git/ignore (or your custom path) # View its contents if set cat $(git config --global core.excludesFile)
-
Disable temporarily - Set
respect_gitignore: falseto confirm it's a gitignore issue# packwerk.yml respect_gitignore: false
-
Use negation patterns - Add
!path/to/file.rbto your.gitignoreto explicitly include it# .gitignore *.log !important.log # This file should NOT be ignored
-
Override with include patterns - Add explicit include patterns in your
packwerk.yml:include: - "path/to/important/file.rb"
If gitignored files are still being analyzed:
-
Check configuration - Ensure
respect_gitignore: true(or not set, since it defaults totrue)# packwerk.yml should have either: respect_gitignore: true # or nothing (defaults to true)
-
Check include patterns - Include patterns override gitignore; files matching
include:will be processed even if gitignoredinclude: - "**/*.rb" # This will include ALL .rb files, even if gitignored
-
Check file location - Only files within the project root can be affected by gitignore
- Files must be relative to the repository root
- Symlinked files outside the repo may not respect gitignore
-
Verify .gitignore syntax - Ensure your patterns are valid
# Test if git itself recognizes the pattern git status # Should not show the file if properly ignored git check-ignore path/to/file.rb # Should output the path if ignored
Useful commands for debugging gitignore behavior:
# List all files that pks will analyze
pks list-included-files
# Check if a specific file would be ignored by git
git check-ignore -v path/to/file.rb
# See your global gitignore location
git config --global core.excludesFile
# View your global gitignore contents (if core.excludesFile is set)
cat $(git config --global core.excludesFile)
# View repository-specific exclusions
cat .git/info/exclude
# Test gitignore patterns
echo "path/to/file.rb" | git check-ignore --stdin -vThis feature is a new addition in pks and does not exist in packwerk.
If you're migrating from packwerk to pks:
- Default behavior change:
pkswill automatically respect.gitignorefiles, whilepackwerkdoes not - Files that may be affected: Any files in your
.gitignorethat were previously analyzed bypackwerkwill now be skipped - To get identical behavior: Set
respect_gitignore: falsein your configuration - Recommended approach: Try the default behavior first; it usually works better and is faster
# packwerk.yml - for packwerk-identical behavior
respect_gitignore: false
# Or accept the new default (recommended)
# respect_gitignore: true # This is the default, no need to specifyThe error messages resulting from running pks check can be customized with mustache-style interpolation. The available variables are:
violation_namereferencing_pack_namedefining_pack_nameconstant_namereference_locationreferencing_pack_relative_yml
Layer violations also have:
defining_layerreferencing_layer
Example:
# packwerk.yml
checker_overrides:
privacy_error_template: "{{reference_location}}Privacy violation: `{{constant_name}}` is private to `{{defining_pack_name}}`. See https://go/pks-privacy"
dependency_error_template: "{{reference_location}}Dependency violation: `{{constant_name}}` belongs to `{{defining_pack_name}}`. See https://go/pks-dependency"See the main README.md for more details.