name: copyright-update description: Scan the entire codebase for copyright year notices and update stale years to the current year, preserving the original start year in ranges. Use when user asks to "update copyright", "fix copyright years", "update license year", or "change copyright to 2026". version: 1.0.0 license: MIT compatibility: opencode, claude metadata: workflow: git-branch-and-commit current-year: "2026"
What I do
- Scan every tracked source file for copyright year notices using regex patterns
- If a single year is present, update it to the current single year
- If a year range is present, preserve the original start year and update the trailing year to the current year
- Skip third-party dependencies and vendored code
- Handle all common copyright formats across all file types
- Update
LICENSEfiles separately (they often have their own format) - Create a git branch, apply all updates, and commit
When to use me
Use this skill at the start of a new year, or when auditing a codebase that has stale copyright notices. Common situations:
- Files still showing
Copyright 2023orCopyright 2020-2024 - LICENSE file has an outdated year
- New contributor files with no copyright notice (optionally add one)
- CI checks requiring up-to-date copyright headers
Year update rules
The current year is 2026.
| Found in file | Updated to |
|---|---|
2023 (single year) |
2026 |
2021-2024 (range, end is stale) |
2021-2026 |
2025-2026 (already current) |
no change |
2026 (already current single) |
no change |
2025 (single, one year behind) |
2026 |
Step-by-step workflow
1. Determine the current year
date +%Y
Use this value as CURRENT_YEAR throughout. As of today it is 2026.
2. Find all files with copyright notices
# Search for all copyright patterns across the codebase
grep -rn --include="*.py" --include="*.js" --include="*.ts" \
--include="*.jsx" --include="*.tsx" --include="*.java" \
--include="*.c" --include="*.cpp" --include="*.h" \
--include="*.go" --include="*.rs" --include="*.rb" \
--include="*.sh" --include="*.md" --include="*.rst" \
--include="*.txt" --include="*.toml" --include="*.yaml" \
--include="*.yml" --include="*.json" --include="*.xml" \
--include="*.html" --include="*.css" --include="*.scss" \
-iE "(copyright|©|\(c\))" . \
--exclude-dir=".git" \
--exclude-dir="node_modules" \
--exclude-dir=".venv" \
--exclude-dir="venv" \
--exclude-dir="dist" \
--exclude-dir="build" \
--exclude-dir="__pycache__"
Also check the LICENSE file specifically:
grep -n -iE "(copyright|©|\(c\))" LICENSE LICENSE.md LICENSE.txt 2>/dev/null
3. Identify stale copyright patterns
Common patterns to look for (all case-insensitive):
# Single year (stale if year < CURRENT_YEAR):
Copyright (c) 2023
Copyright © 2022
# Copyright 2021
// Copyright 2020
# Year ranges (stale if end year < CURRENT_YEAR):
Copyright (c) 2018-2023
Copyright © 2020-2024
# Copyright 2019-2025
/* Copyright 2021-2024 */
# Already current (do NOT change):
Copyright (c) 2026
Copyright (c) 2025-2026
Copyright © 2023-2026
4. Create a new git branch
git fetch origin
git checkout master 2>/dev/null || git checkout main
git pull
git checkout -b fix/copyright-$(date +%Y%m%d)
5. Apply updates file by file
For each file containing a stale copyright year, read the file and apply targeted edits.
Pattern: single stale year → update to current single year
Regex to match: (Copyright\s+(?:\(c\)|©)?\s*)(\d{4})(\s)
- If captured year
$2< 2026: replace with 2026 - If captured year
$2== 2026: leave unchanged
Pattern: range with stale end year → update end year only
Regex to match: (Copyright\s+(?:\(c\)|©)?\s*\d{4}-)(\d{4})
- If captured end year
$2< 2026: replace with$12026 - If captured end year
$2== 2026: leave unchanged
Using sed for bulk updates (always review the result):
# Update stale single years and ranges ending in 2026
# Review before committing!
grep -rln --include="*.py" -E "Copyright.*\b(202[0-5]|201[0-9]|200[0-9])\b" . | while read f; do
# Logically skip dependencies, third-party code, or vendor files
if [[ "$f" == *"vendor/"* ]] || [[ "$f" == *"third_party/"* ]] || [[ "$f" == *"node_modules/"* ]]; then
continue
fi
# 1. Update range: "Copyright 2020-2023" -> "Copyright 2020-2026"
sed -i -E 's/(Copyright[^0-9]*[0-9]{4}-)([0-9]{4})([^0-9-]|$)/\12026\3/g' "$f"
# 2. Update single year: "Copyright 2023" -> "Copyright 2026"
sed -i -E 's/(Copyright[^0-9]*)([0-9]{4})([^0-9-]|$)/\12026\3/g' "$f"
echo "Updated: $f"
done
However, prefer using file editing tools instead of sed — read each file, find the specific copyright line, and edit it precisely. This avoids accidentally matching year numbers that are not copyright years (e.g. version numbers, dates in code).
6. Handle LICENSE file
The LICENSE file often has a standalone year line like:
MIT License
Copyright (c) 2021 Author Name
Read the LICENSE file, find the copyright line, and update:
Copyright (c) 2021→Copyright (c) 2026Copyright (c) 2021-2024→Copyright (c) 2021-2026
7. Handle file headers with SPDX or structured copyright
Some projects use SPDX headers:
# SPDX-FileCopyrightText: 2023 Author Name
# SPDX-License-Identifier: MIT
Update the year in SPDX-FileCopyrightText lines using the same rules:
2023→20262021-2024→2021-2026
8. Review all changes
git diff
Verify:
- No version numbers were accidentally changed (e.g.
v2023.1should NOT becomev2026.1) - No data/timestamps in code were changed
- Only copyright year fields were updated
If any incorrect changes were made, revert those specific files:
git checkout -- path/to/file
Then manually edit only the copyright line.
9. Commit the changes
git add -A
git commit -m "chore: update copyright years to 2026"
Rules and guardrails
- Think logically whether a file belongs to this project or is a third-party dependency. If it's a dependency's license or vendored code, SKIP IT. Do not update it.
- When in doubt about whether a year is part of a copyright notice or something else, read the surrounding context carefully before editing
- Do not add copyright headers to files that have none — that is a policy decision for the project maintainers, not an automated task
- Commit only copyright changes in this branch — do not mix with other work