A fully configurable Go CLI tool for managing copyright headers in source code files.
- Fully configurable: Define any copyright format via templates
- Optional licensing: Enable/disable SPDX license headers
- Path filtering: Include/exclude files using powerful glob patterns with
**support - Multiple file types: Support any file extension with custom comment styles
- Smart detection: Skip generated files, replace specific patterns
- Third-party copyright handling: Configure how to handle existing third-party copyrights
- Git integration: Only processes git-tracked files
- Progress tracking: Visual progress bar for large codebases
- Template-based: Use Go templates for flexible header formats
go install github.com/YakDriver/copyplop@latestCreate .copyplop.yaml in your project root:
copyright:
holder: "Your Company"
start_year: 2020
current_year: 2025
format: "Copyright {{.Holder}} {{.StartYear}}-{{.CurrentYear}}"
license:
enabled: true
identifier: "MIT"
files:
extensions: [".go", ".js", ".py", ".sh"]
comment_styles:
".go": "//"
".js": "//"
".py": "#"
".sh": "#"
detection:
skip_generated: true
generated_patterns: ["Code generated", "DO NOT EDIT"]
replace_patterns: ["Copyright.*OldCompany"]
third_party:
action: "above" # "leave", "above", "below", "replace"
patterns:
- "Copyright.*Oracle"
- "Copyright.*Microsoft"Configure how to handle existing third-party copyrights with precedence logic:
leave: Keep third-party copyrights as-is, add your copyright normallyabove: Add your copyright above third-party copyrightsbelow: Add your copyright below third-party copyrightsreplace: Replace third-party copyrights with your copyright
Replacement patterns take precedence over third-party patterns. This allows you to use general third-party patterns without accidentally treating your own replacement targets as third-party.
detection:
# These get REPLACED (highest precedence)
replace_patterns:
third_party:
action: "above"
# General pattern - but won't match HashiCorp due to precedence
patterns:
- "Copyright.*[a-zA-Z0-9].*"Result: HashiCorp copyrights get replaced, all other copyrights are treated as third-party.
Original file with Oracle copyright:
//Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
package mainWith action: "above":
// Copyright IBM Corp. 2014, 2025
//Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
package mainWith action: "below":
//Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
// Copyright IBM Corp. 2014, 2025
package mainHandle template files that could contain different content types using smart content detection:
files:
# Regular extensions with known comment styles
extensions: [".go", ".py", ".md"]
# Smart extensions detect content type automatically
smart_extensions: [".gtpl", ".tmpl"]
comment_styles:
".go": "//"
".py": "#"
".md": "<!--"Smart extensions analyze file content to determine the actual file type:
.gtpl(Go templates) - Could be Go code, Markdown, HCL, YAML, etc..tmpl(Generic templates) - Detects the underlying content type
| Content Type | Detection Patterns |
|---|---|
| Go | package , func , import (, type ... struct |
| Markdown | # , ## , ```, [text](url) |
| HCL/Terraform | resource ", data ", variable ", output " |
| YAML | ---, key: value patterns |
Binary File Safety: Files with null bytes are automatically skipped to prevent processing binary content.
# For terraform-provider-aws templates
smart_extensions: [".gtpl", ".tmpl"]
# Templates will be processed with appropriate comment style:
# - service.go.gtpl → detected as Go → uses "//" comments
# - README.md.tmpl → detected as Markdown → uses "<!--" comments
# - main.tf.gtpl → detected as HCL → uses "#" commentsFallback: Unknown content defaults to Go (configurable per project needs).
Control which files to process using include/exclude patterns with full doublestar glob support:
files:
# Only process specific paths
include_paths:
- "internal/service/[a-g]*" # Services starting with a-g
- "cmd/**" # All files under cmd/
# Skip specific paths
exclude_paths:
- ".github/**" # Skip all GitHub workflows
- "internal/service/s3*" # Skip S3-related services
- "**/*_test.go" # Skip all test files- No filters: Process all files
- Include only: Process only matching files
- Exclude only: Process all except matching files
- Both: Process files that match includes AND don't match excludes
*- Single-level wildcard**- Recursive directory matching[a-g]- Character ranges{foo,bar}- Alternativesinternal/service/*- Auto-expands to match subdirectories
# Process only EC2 and ECS services
include_paths: ["internal/service/ec[2s]*"]
# Skip generated and test files
exclude_paths: ["**/*generated*", "**/*_test.go"]
# Process infrastructure code only
include_paths: ["internal/**", "cmd/**"]
exclude_paths: [".github/**", "examples/**"]Copyplop supports configurable placement exceptions for cases where copyright headers cannot be the first line in a file.
files:
placement_exceptions:
xml_declaration: true # Allow <?xml version="1.0"?> before copyright
markdown_heading: true # Allow # Heading before copyright
frontmatter: ["md", "html.md"] # YAML frontmatter extensionsAlways Enabled:
- Shebang (
#!/bin/bash) - Always detected and preserved
Configurable Exceptions:
- XML Declaration -
<?xml version="1.0"?>and similar - Markdown Heading -
# Titleas first line - YAML Frontmatter - Between
---markers
Exceptions are processed in this order:
- Shebang (always)
- XML Declaration (if enabled)
- YAML Frontmatter (if configured)
- Markdown Heading (if enabled)
- Copyright header placement
XML File:
<?xml version="1.0"?>
<!-- Copyright 2024 Your Corp -->
<root>content</root>Markdown File:
# My Document
<!-- Copyright 2024 Your Corp -->
Content here...Backward Compatibility: The below_frontmatter configuration is deprecated. Use placement_exceptions.frontmatter instead.
# Check for issues
copyplop check
# Fix copyright headers
copyplop fix
# Process specific path
copyplop check --path ./internal/service/ec2
# Demo progress bar
copyplop demoAvailable in copyright.format:
{{.Holder}}- Copyright holder{{.StartYear}}- Starting year{{.CurrentYear}}- Current year
Available in license.format:
{{.Identifier}}- License identifier
copyright:
format: "Copyright {{.Holder}} {{.StartYear}}, {{.CurrentYear}}"Output: // Copyright IBM Corp. 2014, 2025
copyright:
format: "Copyright (c) {{.Holder}}"copyright:
format: "Copyright {{.CurrentYear}} {{.Holder}}"Output: // Copyright 2025 Acme Corp
See examples/ directory for complete configurations.