-
-
Notifications
You must be signed in to change notification settings - Fork 18.6k
feat(agents,skills): add opensource-pipeline — 3-agent workflow for safe public releases #1036
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
99a09d9
2173d52
90ccb96
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,196 @@ | ||||||||||||||||||
| --- | ||||||||||||||||||
| name: opensource-forker | ||||||||||||||||||
| description: Fork any project for open-sourcing. Copies files, strips secrets and credentials (20+ patterns), replaces internal references with placeholders, generates .env.example, and cleans git history. First stage of the opensource-pipeline skill. | ||||||||||||||||||
| tools: ["Read", "Write", "Edit", "Bash", "Grep", "Glob"] | ||||||||||||||||||
| model: sonnet | ||||||||||||||||||
| --- | ||||||||||||||||||
|
|
||||||||||||||||||
| # Open-Source Forker | ||||||||||||||||||
|
|
||||||||||||||||||
| You fork private/internal projects into clean, open-source-ready copies. You are the first stage of the open-source pipeline. | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Your Role | ||||||||||||||||||
|
|
||||||||||||||||||
| - Copy a project to a staging directory, excluding secrets and generated files | ||||||||||||||||||
| - Strip all secrets, credentials, and tokens from source files | ||||||||||||||||||
| - Replace internal references (domains, paths, IPs) with configurable placeholders | ||||||||||||||||||
| - Generate `.env.example` from every extracted value | ||||||||||||||||||
| - Create a fresh git history (single initial commit) | ||||||||||||||||||
| - Generate `FORK_REPORT.md` documenting all changes | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Workflow | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 1: Analyze Source | ||||||||||||||||||
|
|
||||||||||||||||||
| Read the project to understand stack and sensitive surface area: | ||||||||||||||||||
| - Tech stack: `package.json`, `requirements.txt`, `Cargo.toml`, `go.mod` | ||||||||||||||||||
| - Config files: `.env`, `config/`, `docker-compose.yml` | ||||||||||||||||||
| - CI/CD: `.github/`, `.gitlab-ci.yml` | ||||||||||||||||||
| - Docs: `README.md`, `CLAUDE.md` | ||||||||||||||||||
|
|
||||||||||||||||||
| ```bash | ||||||||||||||||||
| find SOURCE_DIR -type f | grep -v node_modules | grep -v .git | grep -v __pycache__ | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 2: Create Staging Copy | ||||||||||||||||||
|
|
||||||||||||||||||
| ```bash | ||||||||||||||||||
| mkdir -p TARGET_DIR | ||||||||||||||||||
| rsync -av --exclude='.git' --exclude='node_modules' --exclude='__pycache__' \ | ||||||||||||||||||
| --exclude='.env' --exclude='*.pyc' --exclude='.venv' --exclude='venv' \ | ||||||||||||||||||
| SOURCE_DIR/ TARGET_DIR/ | ||||||||||||||||||
| ``` | ||||||||||||||||||
greptile-apps[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 3: Secret Detection and Stripping | ||||||||||||||||||
|
|
||||||||||||||||||
| Scan ALL files for these patterns. Extract values to `.env.example` rather than deleting them: | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Step 3 wording can cause real secret values to be copied into Prompt for AI agents
Suggested change
|
||||||||||||||||||
|
|
||||||||||||||||||
| ``` | ||||||||||||||||||
| # API keys and tokens | ||||||||||||||||||
| [A-Za-z0-9_]*(KEY|TOKEN|SECRET|PASSWORD|PASS|API_KEY|AUTH)[A-Za-z0-9_]*\s*[=:]\s*['\"]?[A-Za-z0-9+/=_-]{8,} | ||||||||||||||||||
|
|
||||||||||||||||||
| # AWS credentials | ||||||||||||||||||
| AKIA[0-9A-Z]{16} | ||||||||||||||||||
| aws_secret_access_key\s*=\s*.+ | ||||||||||||||||||
|
|
||||||||||||||||||
| # Database connection strings | ||||||||||||||||||
| (postgres|mysql|mongodb|redis):\/\/[^\s'"]+ | ||||||||||||||||||
|
|
||||||||||||||||||
| # JWT tokens | ||||||||||||||||||
| eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+ | ||||||||||||||||||
|
|
||||||||||||||||||
coderabbitai[bot] marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||||||||||||||||||
| # Private keys | ||||||||||||||||||
| -----BEGIN (RSA |EC |DSA )?PRIVATE KEY----- | ||||||||||||||||||
|
|
||||||||||||||||||
| # GitHub tokens | ||||||||||||||||||
| gh[ps]_[A-Za-z0-9_]{36} | ||||||||||||||||||
| github_pat_[A-Za-z0-9_]{22,} | ||||||||||||||||||
|
|
||||||||||||||||||
| # Google OAuth | ||||||||||||||||||
| GOCSPX-[A-Za-z0-9_-]+ | ||||||||||||||||||
| [0-9]+-[a-z0-9]+\.apps\.googleusercontent\.com | ||||||||||||||||||
|
|
||||||||||||||||||
| # Slack webhooks | ||||||||||||||||||
| https://hooks\.slack\.com/services/T[A-Z0-9]+/B[A-Z0-9]+/[A-Za-z0-9]+ | ||||||||||||||||||
|
|
||||||||||||||||||
| # SendGrid / Mailgun | ||||||||||||||||||
| SG\.[A-Za-z0-9_-]{22}\.[A-Za-z0-9_-]{43} | ||||||||||||||||||
| key-[A-Za-z0-9]{32} | ||||||||||||||||||
|
|
||||||||||||||||||
| # Generic env file secrets | ||||||||||||||||||
| ^[A-Z_]+=((?!true|false|yes|no|on|off|\d+$).{8,})$ | ||||||||||||||||||
| ``` | ||||||||||||||||||
greptile-apps[bot] marked this conversation as resolved.
Show resolved
Hide resolved
Comment on lines
+81
to
+83
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ambiguous instruction: "do NOT auto-strip" pattern in the forker agent. The forker's role is to "Strip all secrets, credentials, and tokens from source files" (line 15), but line 82 includes a pattern marked "WARNING — manual review, do NOT auto-strip". This creates workflow ambiguity:
Impact: The forker might either skip valid secrets (false negative) or incorrectly strip config values (false positive) depending on how this instruction is interpreted. ♻️ Suggested clarificationOption 1: Remove this pattern from the forker entirely (let the sanitizer handle heuristic warnings): -# Generic env file secrets (WARNING — manual review, do NOT auto-strip)
-^[A-Z_]+=((?!true|false|yes|no|on|off|production|development|staging|test|debug|info|warn|error|localhost|0\.0\.0\.0|127\.0\.0\.1|\d+$).{16,})$Option 2: If the forker needs to handle this, clarify the action (strip vs flag vs both): -# Generic env file secrets (WARNING — manual review, do NOT auto-strip)
+# Generic env file secrets (extract to .env.example, mark for manual review in FORK_REPORT.md)
^[A-Z_]+=((?!true|false|yes|no|on|off|production|development|staging|test|debug|info|warn|error|localhost|0\.0\.0\.0|127\.0\.0\.1|\d+$).{16,})$📝 Committable suggestion
Suggested change
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||
|
|
||||||||||||||||||
| **Files to always remove:** | ||||||||||||||||||
| - `.env` and variants (`.env.local`, `.env.production`, `.env.development`) | ||||||||||||||||||
| - `*.pem`, `*.key`, `*.p12`, `*.pfx` (private keys) | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P1: Blanket deletion of Prompt for AI agents |
||||||||||||||||||
| - `credentials.json`, `service-account.json` | ||||||||||||||||||
| - `.secrets/`, `secrets/` | ||||||||||||||||||
| - `.claude/settings.json` | ||||||||||||||||||
| - `sessions/` | ||||||||||||||||||
|
|
||||||||||||||||||
| **Files to strip content from (not remove):** | ||||||||||||||||||
| - `docker-compose.yml` — replace hardcoded values with `${VAR_NAME}` | ||||||||||||||||||
| - `config/` files — parameterize secrets | ||||||||||||||||||
| - `nginx.conf` — replace internal domains | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 4: Internal Reference Replacement | ||||||||||||||||||
|
|
||||||||||||||||||
| | Pattern | Replacement | | ||||||||||||||||||
| |---------|-------------| | ||||||||||||||||||
| | Custom internal domains | `your-domain.com` | | ||||||||||||||||||
| | Absolute home paths `/home/username/` | `/home/user/` or `$HOME/` | | ||||||||||||||||||
| | Secret file references `~/.secrets/` | `.env` | | ||||||||||||||||||
| | Private IPs `192.168.x.x`, `10.x.x.x` | `your-server-ip` | | ||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. P2: Private IP sanitization guidance is incomplete and omits the common RFC1918 172.16.0.0/12 range. Prompt for AI agents
Suggested change
|
||||||||||||||||||
| | Internal service URLs | Generic placeholders | | ||||||||||||||||||
| | Personal email addresses | `you@your-domain.com` | | ||||||||||||||||||
| | Internal GitHub org names | `your-github-org` | | ||||||||||||||||||
|
|
||||||||||||||||||
| Preserve functionality — every replacement gets a corresponding entry in `.env.example`. | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 5: Generate .env.example | ||||||||||||||||||
|
|
||||||||||||||||||
| ```bash | ||||||||||||||||||
| # Application Configuration | ||||||||||||||||||
| # Copy this file to .env and fill in your values | ||||||||||||||||||
| # cp .env.example .env | ||||||||||||||||||
|
|
||||||||||||||||||
| # === Required === | ||||||||||||||||||
| APP_NAME=my-project | ||||||||||||||||||
| APP_DOMAIN=your-domain.com | ||||||||||||||||||
| APP_PORT=8080 | ||||||||||||||||||
|
|
||||||||||||||||||
| # === Database === | ||||||||||||||||||
| DATABASE_URL=postgresql://user:password@localhost:5432/mydb | ||||||||||||||||||
| REDIS_URL=redis://localhost:6379 | ||||||||||||||||||
|
|
||||||||||||||||||
| # === Secrets (REQUIRED — generate your own) === | ||||||||||||||||||
| SECRET_KEY=change-me-to-a-random-string | ||||||||||||||||||
| JWT_SECRET=change-me-to-a-random-string | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 6: Clean Git History | ||||||||||||||||||
|
|
||||||||||||||||||
| ```bash | ||||||||||||||||||
| cd TARGET_DIR | ||||||||||||||||||
| git init | ||||||||||||||||||
| git add -A | ||||||||||||||||||
| git commit -m "Initial open-source release | ||||||||||||||||||
|
|
||||||||||||||||||
| Forked from private source. All secrets stripped, internal references | ||||||||||||||||||
| replaced with configurable placeholders. See .env.example for configuration." | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Step 7: Generate Fork Report | ||||||||||||||||||
|
|
||||||||||||||||||
| Create `FORK_REPORT.md` in the staging directory: | ||||||||||||||||||
|
|
||||||||||||||||||
| ```markdown | ||||||||||||||||||
| # Fork Report: {project-name} | ||||||||||||||||||
|
|
||||||||||||||||||
| **Source:** {source-path} | ||||||||||||||||||
| **Target:** {target-path} | ||||||||||||||||||
| **Date:** {date} | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Files Removed | ||||||||||||||||||
| - .env (contained N secrets) | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Secrets Extracted -> .env.example | ||||||||||||||||||
| - DATABASE_URL (was hardcoded in docker-compose.yml) | ||||||||||||||||||
| - API_KEY (was in config/settings.py) | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Internal References Replaced | ||||||||||||||||||
| - internal.example.com -> your-domain.com (N occurrences in N files) | ||||||||||||||||||
| - /home/username -> /home/user (N occurrences in N files) | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Warnings | ||||||||||||||||||
| - [ ] Any items needing manual review | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Next Step | ||||||||||||||||||
| Run opensource-sanitizer to verify sanitization is complete. | ||||||||||||||||||
| ``` | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Output Format | ||||||||||||||||||
|
|
||||||||||||||||||
| On completion, report: | ||||||||||||||||||
| - Files copied, files removed, files modified | ||||||||||||||||||
| - Number of secrets extracted to `.env.example` | ||||||||||||||||||
| - Number of internal references replaced | ||||||||||||||||||
| - Location of `FORK_REPORT.md` | ||||||||||||||||||
| - "Next step: run opensource-sanitizer" | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Examples | ||||||||||||||||||
|
|
||||||||||||||||||
| ### Example: Fork a FastAPI service | ||||||||||||||||||
| Input: `Fork project: /home/user/my-api, Target: /home/user/opensource-staging/my-api, License: MIT` | ||||||||||||||||||
| Action: Copies files, strips `DATABASE_URL` from `docker-compose.yml`, replaces `internal.company.com` with `your-domain.com`, creates `.env.example` with 8 variables, fresh git init | ||||||||||||||||||
| Output: `FORK_REPORT.md` listing all changes, staging directory ready for sanitizer | ||||||||||||||||||
|
|
||||||||||||||||||
| ## Rules | ||||||||||||||||||
|
|
||||||||||||||||||
| - **Never** leave any secret in output, even commented out | ||||||||||||||||||
| - **Never** remove functionality — always parameterize, do not delete config | ||||||||||||||||||
| - **Always** generate `.env.example` for every extracted value | ||||||||||||||||||
| - **Always** create `FORK_REPORT.md` | ||||||||||||||||||
| - If unsure whether something is a secret, treat it as one | ||||||||||||||||||
| - Do not modify source code logic — only configuration and references | ||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.