
Automates the nerve-wracking process of taking a private project public by running it through a three-stage pipeline: fork and strip secrets, verify nothing leaked, then generate all the open-source boilerplate (CLAUDE.md, setup.sh, README, license, contribution guidelines). The sanitizer agent is the real safety net here, running six scan categories and blocking publication on critical findings like exposed credentials or PII. Everything stages to a review directory before you push anything to GitHub. Honestly most useful if you've got internal tooling you want to share but dread the manual scrubbing. The full pipeline probably saves an hour of paranoid grepping and template copying.
$ npx -y skills add affaan-m/everything-claude-code --skill opensource-pipeline --agent claude-codeInstalls into .claude/skills of the current project.
Safely open-source any project through a 3-stage pipeline: Fork (strip secrets) → Sanitize (verify clean) → Package (CLAUDE.md + setup.sh + README).
/opensource fork, /opensource verify, or /opensource package| Command | Action |
|---|---|
/opensource fork PROJECT | Full pipeline: fork + sanitize + package |
/opensource verify PROJECT | Run sanitizer on existing repo |
/opensource package PROJECT | Generate CLAUDE.md + setup.sh + README |
/opensource list | Show all staged projects |
/opensource status PROJECT | Show reports for a staged project |
Full pipeline — the main workflow.
Resolve the project path. If PROJECT contains /, treat as a path (absolute or relative). Otherwise check: current working directory, $HOME/PROJECT, then ask the user.
SOURCE_PATH="<resolved absolute path>"
STAGING_PATH="$HOME/opensource-staging/${PROJECT_NAME}"
Ask the user:
gh api user -q .login)mkdir -p $HOME/opensource-staging/
Spawn the opensource-forker agent:
Agent(
description="Fork {PROJECT} for open-source",
subagent_type="opensource-forker",
prompt="""
Fork project for open-source release.
Source: {SOURCE_PATH}
Target: {STAGING_PATH}
License: {chosen_license}
Follow the full forking protocol:
1. Copy files (exclude .git, node_modules, __pycache__, .venv)
2. Strip all secrets and credentials
3. Replace internal references with placeholders
4. Generate .env.example
5. Clean git history
6. Generate FORK_REPORT.md in {STAGING_PATH}/FORK_REPORT.md
"""
)
Wait for completion. Read {STAGING_PATH}/FORK_REPORT.md.
The forker's single commit is only the starting point: gh repo create --push (Step 7)
publishes commits, not the working tree. Every later change (sanitizer fixes, packager output)
must be folded into that commit, so the public history is one commit that matches the tree the
sanitizer passed. The reports stay out of it. Fold changes in with:
cd "{STAGING_PATH}"
grep -qxF SANITIZATION_REPORT.md .git/info/exclude || printf '%s\n' FORK_REPORT.md SANITIZATION_REPORT.md >> .git/info/exclude
git add -A
git rm -q --cached --ignore-unmatch FORK_REPORT.md SANITIZATION_REPORT.md
git commit --amend --no-edit
git status --porcelain -uno # must print nothing
git rev-list --count HEAD # must print 1
An amend leaves a secret that was removed from a file out of the new commit. A new commit on top would publish it in history.
Spawn the opensource-sanitizer agent:
Agent(
description="Verify {PROJECT} sanitization",
subagent_type="opensource-sanitizer",
prompt="""
Verify sanitization of open-source fork.
Project: {STAGING_PATH}
Source (for reference): {SOURCE_PATH}
Run ALL scan categories:
1. Secrets scan (CRITICAL)
2. PII scan (CRITICAL)
3. Internal references scan (CRITICAL)
4. Dangerous files check (CRITICAL)
5. Configuration completeness (WARNING)
6. Git history audit
7. Unreadable files (WARNING)
Generate SANITIZATION_REPORT.md inside {STAGING_PATH}/ with PASS/FAIL verdict.
"""
)
Wait for completion. Read {STAGING_PATH}/SANITIZATION_REPORT.md.
If FAIL: Show findings to user. Ask: "Fix these and re-scan, or abort?"
Unreadable files. After the fix/rescan loop settles, read the report's ## Unreadable Files
section, not stdout:
unknown, or the section or the count is missing, the scan did not finish. Stop
before Step 5, as for a FAIL: show any Scan problem lines and ask the user to fix the cause and
re-scan, or abort. A missing section is never an empty one, and an unknown count cannot be
confirmed away.{STAGING_PATH}.UNREADABLE_FILES.txt, which sits beside the staging directory,
not inside it. Ask: "These were never read. Confirm you've opened them, or abort?" Ask once,
against the final report, not on each retry.wc -l on it must equal the count, and it must
not exist when the count is zero. Treat a mismatch as unknown.Most repos trip this on a logo or a font, so expect to be asked.
Continue to Step 5 only when the verdict is PASS or PASS WITH WARNINGS and the unreadable count is zero or the user has confirmed the files. A FAIL (including after the 3 retries), an unknown or missing count, or an unconfirmed list stops the pipeline here.
Spawn the opensource-packager agent:
Agent(
description="Package {PROJECT} for open-source",
subagent_type="opensource-packager",
prompt="""
Generate open-source packaging for project.
Project: {STAGING_PATH}
License: {chosen_license}
Project name: {PROJECT_NAME}
Description: {description}
GitHub repo: {github_repo}
Generate:
1. CLAUDE.md (commands, architecture, key files)
2. setup.sh (one-command bootstrap, make executable)
3. README.md (or enhance existing)
4. LICENSE
5. CONTRIBUTING.md
6. .github/ISSUE_TEMPLATE/ (bug_report.md, feature_request.md)
"""
)
The packager's files are not committed yet. Fold them into the commit (see Step 3), then run the sanitizer again exactly as in Step 4, against what will be published. Apply the same gate as Step 4, including the fix loop and the unreadable-files check. A FAIL here stops the pipeline: packaging can add a personal email, a home path or a key in an example.
When the gate passes, record the commit the sanitizer scanned as {SCANNED_COMMIT}:
git -C "{STAGING_PATH}" rev-parse HEAD
Present to user:
Open-Source Fork Ready: {PROJECT_NAME}
Location: {STAGING_PATH}
License: {license}
Files generated:
- CLAUDE.md
- setup.sh (executable)
- README.md
- LICENSE
- CONTRIBUTING.md
- .env.example ({N} variables)
Sanitization: {sanitization_verdict} (scanned after packaging, on the commit that will be pushed)
Next steps:
1. Review: cd {STAGING_PATH}
2. Create repo: gh repo create {github_org}/{github_repo} --public
3. Push: git remote add origin ... && git push -u origin main
Proceed with GitHub creation? (yes/no/review first)
Push only the commit the sanitizer passed. If the tree or the commit changed since Step 5b (for
example the user edited files after "review first" and amended), go back to Step 5b instead of
pushing. The two generated reports may remain untracked even when a source .gitignore negates
their names. Allow only those two untracked files; a report in the index or scanned commit, or any
other worktree change, still stops publication.
cd "{STAGING_PATH}"
test -z "$(git ls-files -- FORK_REPORT.md SANITIZATION_REPORT.md)" \
&& test -z "$(git ls-tree -r --name-only HEAD -- FORK_REPORT.md SANITIZATION_REPORT.md)" \
&& test -z "$(git status --porcelain --untracked-files=all -- . ':(exclude)FORK_REPORT.md' ':(exclude)SANITIZATION_REPORT.md')" \
&& test "$(git rev-list --count HEAD)" = 1 \
&& test "$(git rev-parse HEAD)" = "{SCANNED_COMMIT}" \
|| { echo "Uncommitted changes, extra commits, or HEAD is not the scanned commit: return to Step 5b" >&2; exit 1; }
gh repo create "{github_org}/{github_repo}" --public --source=. --push --description "{description}"
Run sanitizer independently. Resolve path: if PROJECT contains /, treat as a path. Otherwise check $HOME/opensource-staging/PROJECT, then $HOME/PROJECT, then current directory.
Agent(
subagent_type="opensource-sanitizer",
prompt="Verify sanitization of: {resolved_path}. Run all 7 scan categories and generate SANITIZATION_REPORT.md."
)
There is no confirmation gate here. Show the user the report, including the ## Unreadable Files
count and tally. When the count is above zero, point them at {resolved_path}.UNREADABLE_FILES.txt
and do not read or print it.
Run packager independently. Ask for "License?" and "Description?", then:
Agent(
subagent_type="opensource-packager",
prompt="Package: {resolved_path} ..."
)
ls -d $HOME/opensource-staging/*/
Show each project with pipeline progress (FORK_REPORT.md, SANITIZATION_REPORT.md, CLAUDE.md presence).
cat $HOME/opensource-staging/${PROJECT}/SANITIZATION_REPORT.md
cat $HOME/opensource-staging/${PROJECT}/FORK_REPORT.md
$HOME/opensource-staging/
my-project/
FORK_REPORT.md # From forker agent
SANITIZATION_REPORT.md # From sanitizer agent
CLAUDE.md # From packager agent
setup.sh # From packager agent
README.md # From packager agent
.env.example # From forker agent
... # Sanitized project files
my-project.UNREADABLE_FILES.txt # From sanitizer agent, only when files could not be read
.env, *.pem, or credentials.json in the staging directorySee security-review for secret detection patterns used by the sanitizer.
Sponsors