bmad-plus 0.8.0 → 0.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +45 -1
- package/LICENSE +21 -21
- package/README.md +107 -85
- package/osint-agent-package/README.md +88 -88
- package/osint-agent-package/SETUP_KEYS.md +108 -108
- package/osint-agent-package/agents/osint-investigator.md +80 -80
- package/osint-agent-package/install.ps1 +87 -87
- package/osint-agent-package/install.sh +76 -76
- package/osint-agent-package/skills/bmad-osint-investigate/SKILL.md +147 -147
- package/osint-agent-package/skills/bmad-osint-investigate/osint/references/enrichment-databases-fr.md +148 -148
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/_http.py +101 -101
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/apify.py +266 -266
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/brightdata.py +101 -101
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/diagnose.py +141 -141
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/exa.py +79 -79
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/jina.py +71 -71
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/parallel.py +85 -85
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/perplexity.py +102 -102
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/tavily.py +72 -72
- package/osint-agent-package/skills/bmad-osint-investigate/osint/scripts/volley.py +208 -208
- package/osint-agent-package/skills/bmad-osint-investigator/SKILL.md +15 -15
- package/package.json +30 -3
- package/readme-international/README.de.md +18 -5
- package/readme-international/README.es.md +40 -12
- package/readme-international/README.fr.md +36 -8
- package/src/bmad-plus/agents/agent-architect-dev/SKILL.md +96 -96
- package/src/bmad-plus/agents/agent-architect-dev/bmad-skill-manifest.yaml +13 -13
- package/src/bmad-plus/agents/agent-maker/SKILL.md +201 -201
- package/src/bmad-plus/agents/agent-maker/bmad-skill-manifest.yaml +13 -13
- package/src/bmad-plus/agents/agent-orchestrator/SKILL.md +137 -137
- package/src/bmad-plus/agents/agent-orchestrator/bmad-skill-manifest.yaml +13 -13
- package/src/bmad-plus/agents/agent-quality/SKILL.md +83 -83
- package/src/bmad-plus/agents/agent-quality/bmad-skill-manifest.yaml +13 -13
- package/src/bmad-plus/agents/agent-shadow/SKILL.md +71 -71
- package/src/bmad-plus/agents/agent-shadow/bmad-skill-manifest.yaml +13 -13
- package/src/bmad-plus/agents/agent-strategist/SKILL.md +80 -80
- package/src/bmad-plus/agents/agent-strategist/bmad-skill-manifest.yaml +13 -13
- package/src/bmad-plus/data/role-triggers.yaml +209 -209
- package/src/bmad-plus/module-help.csv +10 -10
- package/src/bmad-plus/packs/pack-memory/README.md +106 -106
- package/src/bmad-plus/packs/pack-memory/memory-orchestrator.md +79 -79
- package/src/bmad-plus/packs/pack-memory/shared/karpathy-guardrails.md +86 -86
- package/src/bmad-plus/packs/pack-memory/shared/memory-protocol.md +143 -143
- package/src/bmad-plus/packs/pack-memory/templates/context.md +39 -39
- package/src/bmad-plus/packs/pack-memory/templates/decisions.md +25 -25
- package/src/bmad-plus/packs/pack-memory/templates/identity.yaml +39 -39
- package/src/bmad-plus/packs/pack-memory/templates/lessons.md +31 -31
- package/src/bmad-plus/packs/pack-memory/templates/patterns.md +24 -24
- package/src/bmad-plus/packs/pack-memory/templates/session-handoff.md +25 -25
- package/src/bmad-plus/packs/pack-memory/zecher-agent.md +157 -157
- package/src/bmad-plus/packs/pack-seo/bmad-skill-manifest.yaml +13 -0
- package/src/bmad-plus/packs/pack-shield/README.md +110 -110
- package/src/bmad-plus/packs/pack-shield/SKILL.md +82 -0
- package/src/bmad-plus/packs/pack-shield/categories/accessibility-esg/csrd-agent.md +251 -251
- package/src/bmad-plus/packs/pack-shield/categories/accessibility-esg/section508-agent.md +168 -168
- package/src/bmad-plus/packs/pack-shield/categories/accessibility-esg/wcag-agent.md +190 -190
- package/src/bmad-plus/packs/pack-shield/categories/ai-governance/eu-ai-act-agent.md +86 -86
- package/src/bmad-plus/packs/pack-shield/categories/ai-governance/iso42001-agent.md +240 -240
- package/src/bmad-plus/packs/pack-shield/categories/ai-governance/nist-ai-rmf-agent.md +122 -122
- package/src/bmad-plus/packs/pack-shield/categories/cybersecurity/cis-controls-agent.md +210 -210
- package/src/bmad-plus/packs/pack-shield/categories/cybersecurity/ism-agent.md +139 -139
- package/src/bmad-plus/packs/pack-shield/categories/cybersecurity/iso27001-agent.md +156 -156
- package/src/bmad-plus/packs/pack-shield/categories/cybersecurity/nis2-agent.md +72 -72
- package/src/bmad-plus/packs/pack-shield/categories/cybersecurity/nist-800-53-agent.md +239 -239
- package/src/bmad-plus/packs/pack-shield/categories/cybersecurity/nist-csf-agent.md +207 -207
- package/src/bmad-plus/packs/pack-shield/categories/data-privacy/ccpa-agent.md +94 -94
- package/src/bmad-plus/packs/pack-shield/categories/data-privacy/dpdpa-agent.md +136 -136
- package/src/bmad-plus/packs/pack-shield/categories/data-privacy/gdpr-agent.md +296 -296
- package/src/bmad-plus/packs/pack-shield/categories/data-privacy/iso27701-agent.md +134 -134
- package/src/bmad-plus/packs/pack-shield/categories/data-privacy/lgpd-agent.md +129 -129
- package/src/bmad-plus/packs/pack-shield/categories/defense-export/cmmc-agent.md +116 -116
- package/src/bmad-plus/packs/pack-shield/categories/defense-export/ear-agent.md +261 -261
- package/src/bmad-plus/packs/pack-shield/categories/defense-export/itar-agent.md +191 -191
- package/src/bmad-plus/packs/pack-shield/categories/defense-export/tsa-agent.md +356 -356
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/dora-agent.md +499 -499
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/fedramp-agent.md +236 -236
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/hipaa-agent.md +162 -162
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/pci-dss-agent.md +228 -228
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/soc2-agent.md +255 -255
- package/src/bmad-plus/packs/pack-shield/categories/industry-compliance/swift-csp-agent.md +153 -153
- package/src/bmad-plus/packs/pack-shield/categories/workflows/ai-act-classifier.md +131 -131
- package/src/bmad-plus/packs/pack-shield/categories/workflows/ai-act-fria.md +155 -155
- package/src/bmad-plus/packs/pack-shield/categories/workflows/ai-act-incidents.md +187 -187
- package/src/bmad-plus/packs/pack-shield/categories/workflows/ai-act-roles.md +113 -113
- package/src/bmad-plus/packs/pack-shield/categories/workflows/breach-sentinel.md +197 -197
- package/src/bmad-plus/packs/pack-shield/categories/workflows/cookie-policy-gen.md +180 -180
- package/src/bmad-plus/packs/pack-shield/categories/workflows/dpia-sentinel.md +235 -235
- package/src/bmad-plus/packs/pack-shield/categories/workflows/legitimate-interest.md +159 -159
- package/src/bmad-plus/packs/pack-shield/categories/workflows/privacy-advisor.md +133 -133
- package/src/bmad-plus/packs/pack-shield/categories/workflows/privacy-notice-gen.md +160 -160
- package/src/bmad-plus/packs/pack-shield/categories/workflows/privacy-policy-gen.md +135 -135
- package/src/bmad-plus/packs/pack-shield/references/ccpa/ccpa-gdpr-comparison.md +117 -117
- package/src/bmad-plus/packs/pack-shield/references/ccpa/consumer-rights-workflows.md +177 -177
- package/src/bmad-plus/packs/pack-shield/references/cis-controls/framework-mappings.md +162 -162
- package/src/bmad-plus/packs/pack-shield/references/cis-controls/implementation-guidance.md +235 -235
- package/src/bmad-plus/packs/pack-shield/references/cis-controls/safeguards-detail.md +252 -252
- package/src/bmad-plus/packs/pack-shield/references/cmmc/cmmc-assessment.md +170 -170
- package/src/bmad-plus/packs/pack-shield/references/cmmc/cmmc-levels.md +113 -113
- package/src/bmad-plus/packs/pack-shield/references/cmmc/cmmc-practices.md +211 -211
- package/src/bmad-plus/packs/pack-shield/references/csrd/compliance-program.md +281 -281
- package/src/bmad-plus/packs/pack-shield/references/csrd/double-materiality.md +253 -253
- package/src/bmad-plus/packs/pack-shield/references/csrd/esrs-standards.md +401 -401
- package/src/bmad-plus/packs/pack-shield/references/dora/article-reference.md +441 -441
- package/src/bmad-plus/packs/pack-shield/references/dora/incident-classification.md +297 -297
- package/src/bmad-plus/packs/pack-shield/references/dora/rts-its-guide.md +306 -306
- package/src/bmad-plus/packs/pack-shield/references/dora/third-party-risk.md +349 -349
- package/src/bmad-plus/packs/pack-shield/references/dpdpa/gdpr-comparison.md +173 -173
- package/src/bmad-plus/packs/pack-shield/references/dpdpa/rights-and-obligations.md +426 -426
- package/src/bmad-plus/packs/pack-shield/references/dpdpa/rules-2025.md +599 -599
- package/src/bmad-plus/packs/pack-shield/references/dpdpa/sections-reference.md +319 -319
- package/src/bmad-plus/packs/pack-shield/references/ear/ccl-eccn-guide.md +250 -250
- package/src/bmad-plus/packs/pack-shield/references/ear/compliance-program.md +280 -280
- package/src/bmad-plus/packs/pack-shield/references/ear/license-exceptions.md +207 -207
- package/src/bmad-plus/packs/pack-shield/references/eu-ai-act/gpai-governance.md +267 -267
- package/src/bmad-plus/packs/pack-shield/references/eu-ai-act/obligations-high-risk.md +287 -287
- package/src/bmad-plus/packs/pack-shield/references/eu-ai-act/risk-classification.md +182 -182
- package/src/bmad-plus/packs/pack-shield/references/fedramp/appendices-guide.md +209 -209
- package/src/bmad-plus/packs/pack-shield/references/fedramp/control-families.md +281 -281
- package/src/bmad-plus/packs/pack-shield/references/fedramp/poam-guide.md +93 -93
- package/src/bmad-plus/packs/pack-shield/references/fedramp/readiness-checklist.md +134 -134
- package/src/bmad-plus/packs/pack-shield/references/fedramp/sap-sar-guide.md +86 -86
- package/src/bmad-plus/packs/pack-shield/references/fedramp/ssp-guide.md +129 -129
- package/src/bmad-plus/packs/pack-shield/references/gdpr-compliance/documents.md +192 -192
- package/src/bmad-plus/packs/pack-shield/references/gdpr-compliance/dpa-template.md +121 -121
- package/src/bmad-plus/packs/pack-shield/references/gdpr-compliance/privacy-notice.md +87 -87
- package/src/bmad-plus/packs/pack-shield/references/hipaa-compliance/breach-notification.md +293 -293
- package/src/bmad-plus/packs/pack-shield/references/hipaa-compliance/privacy-rule.md +276 -276
- package/src/bmad-plus/packs/pack-shield/references/hipaa-compliance/security-rule.md +299 -299
- package/src/bmad-plus/packs/pack-shield/references/hipaa-compliance/templates.md +568 -568
- package/src/bmad-plus/packs/pack-shield/references/ism/control-applicability.md +181 -181
- package/src/bmad-plus/packs/pack-shield/references/ism/guidelines-overview.md +183 -183
- package/src/bmad-plus/packs/pack-shield/references/iso27001/annex-a-2013.md +203 -203
- package/src/bmad-plus/packs/pack-shield/references/iso27001/annex-a-2022.md +132 -132
- package/src/bmad-plus/packs/pack-shield/references/iso27001/control-mapping.md +153 -153
- package/src/bmad-plus/packs/pack-shield/references/iso27701/annex-a-controls.md +195 -195
- package/src/bmad-plus/packs/pack-shield/references/iso27701/regulatory-mapping.md +229 -229
- package/src/bmad-plus/packs/pack-shield/references/iso27701/transition-guide.md +219 -219
- package/src/bmad-plus/packs/pack-shield/references/iso42001/iso42001-ai-risk-assessment.md +258 -258
- package/src/bmad-plus/packs/pack-shield/references/iso42001/iso42001-clauses-requirements.md +279 -279
- package/src/bmad-plus/packs/pack-shield/references/iso42001/iso42001-controls-annex-a.md +155 -155
- package/src/bmad-plus/packs/pack-shield/references/itar/compliance-program.md +174 -174
- package/src/bmad-plus/packs/pack-shield/references/itar/licensing-guide.md +146 -146
- package/src/bmad-plus/packs/pack-shield/references/itar/usml-categories.md +93 -93
- package/src/bmad-plus/packs/pack-shield/references/lgpd/anpd-enforcement.md +147 -147
- package/src/bmad-plus/packs/pack-shield/references/lgpd/compliance-program.md +272 -272
- package/src/bmad-plus/packs/pack-shield/references/lgpd/lgpd-articles.md +271 -271
- package/src/bmad-plus/packs/pack-shield/references/nis2/article-21-measures.md +153 -153
- package/src/bmad-plus/packs/pack-shield/references/nis2/iso27001-nis2-mapping.md +68 -68
- package/src/bmad-plus/packs/pack-shield/references/nist-800-53/assessment-rmf.md +349 -349
- package/src/bmad-plus/packs/pack-shield/references/nist-800-53/baselines-tailoring.md +277 -277
- package/src/bmad-plus/packs/pack-shield/references/nist-800-53/control-families.md +450 -450
- package/src/bmad-plus/packs/pack-shield/references/nist-ai-rmf/rmf-core.md +361 -361
- package/src/bmad-plus/packs/pack-shield/references/nist-ai-rmf/rmf-profiles.md +192 -192
- package/src/bmad-plus/packs/pack-shield/references/nist-csf/csf-10-to-20-mapping.md +143 -143
- package/src/bmad-plus/packs/pack-shield/references/nist-csf/csf-20-functions-categories.md +278 -278
- package/src/bmad-plus/packs/pack-shield/references/nist-csf/csf-implementation-tiers.md +135 -135
- package/src/bmad-plus/packs/pack-shield/references/pci-compliance/pci-dss-requirements.md +366 -366
- package/src/bmad-plus/packs/pack-shield/references/pci-compliance/pci-dss-saq-guide.md +217 -217
- package/src/bmad-plus/packs/pack-shield/references/pci-compliance/pci-dss-v4-changes.md +190 -190
- package/src/bmad-plus/packs/pack-shield/references/section-508/wcag-mapping.md +160 -160
- package/src/bmad-plus/packs/pack-shield/references/soc2/controls.md +241 -241
- package/src/bmad-plus/packs/pack-shield/references/soc2/evidence.md +236 -236
- package/src/bmad-plus/packs/pack-shield/references/soc2/policies.md +254 -254
- package/src/bmad-plus/packs/pack-shield/references/soc2/vendor.md +276 -276
- package/src/bmad-plus/packs/pack-shield/references/swift-csp/swift-assessment.md +202 -202
- package/src/bmad-plus/packs/pack-shield/references/swift-csp/swift-controls.md +545 -545
- package/src/bmad-plus/packs/pack-shield/references/tsa-compliance/tsa-crmp-requirements.md +359 -359
- package/src/bmad-plus/packs/pack-shield/references/tsa-compliance/tsa-directives-overview.md +187 -187
- package/src/bmad-plus/packs/pack-shield/references/tsa-compliance/tsa-incident-reporting.md +187 -187
- package/src/bmad-plus/packs/pack-shield/references/wcag/criteria-detail.md +510 -510
- package/src/bmad-plus/packs/pack-shield/shared/audit-report-template.md +103 -103
- package/src/bmad-plus/packs/pack-shield/shared/cross-framework-mapper.md +103 -103
- package/src/bmad-plus/packs/pack-shield/shared/gap-analysis-template.md +83 -83
- package/src/bmad-plus/packs/pack-shield/shield-orchestrator.md +229 -229
- package/src/bmad-plus/packs/pack-shield/upstream-sync.yaml +68 -68
- package/src/bmad-plus/skills/bmad-plus-autopilot/SKILL.md +99 -99
- package/src/bmad-plus/skills/bmad-plus-parallel/SKILL.md +93 -93
- package/src/bmad-plus/skills/bmad-plus-sync/SKILL.md +69 -69
- package/tools/bmad-plus-npx.js +3 -5
- package/tools/cli/bmad-plus-cli.js +5 -3
- package/tools/cli/commands/autoconfig.js +18 -61
- package/tools/cli/commands/doctor.js +30 -31
- package/tools/cli/commands/install.js +33 -343
- package/tools/cli/commands/memory.js +1 -0
- package/tools/cli/commands/scan.js +61 -74
- package/tools/cli/commands/uninstall.js +7 -4
- package/tools/cli/commands/update.js +15 -72
- package/tools/cli/i18n.js +92 -10
- package/tools/cli/lib/ide-config.js +259 -0
- package/tools/cli/lib/memory-init.js +113 -0
- package/tools/cli/lib/pack-copy.js +84 -0
- package/tools/cli/lib/packs.js +114 -0
- package/tools/cli/lib/stack-detect.js +102 -0
- package/tools/cli/lib/validate.js +45 -0
- package/src/bmad-plus/agents/pack-animated/animated-website-agent.md +0 -325
- package/src/bmad-plus/agents/pack-animated/templates/animated-website-workflow.md +0 -55
- package/src/bmad-plus/agents/pack-backup/backup-agent.md +0 -71
- package/src/bmad-plus/agents/pack-backup/templates/backup-workflow.md +0 -51
- package/src/bmad-plus/agents/pack-seo/SKILL.md +0 -171
- package/src/bmad-plus/agents/pack-seo/checklist.md +0 -140
- package/src/bmad-plus/agents/pack-seo/pagespeed-playbook.md +0 -320
- package/src/bmad-plus/agents/pack-seo/ref/audit-schema.json +0 -187
- package/src/bmad-plus/agents/pack-seo/ref/cwv-thresholds.md +0 -87
- package/src/bmad-plus/agents/pack-seo/ref/eeat-criteria.md +0 -123
- package/src/bmad-plus/agents/pack-seo/ref/geo-signals.md +0 -167
- package/src/bmad-plus/agents/pack-seo/ref/hreflang-rules.md +0 -153
- package/src/bmad-plus/agents/pack-seo/ref/quality-gates.md +0 -133
- package/src/bmad-plus/agents/pack-seo/ref/schema-catalog.md +0 -91
- package/src/bmad-plus/agents/pack-seo/ref/schema-templates.json +0 -356
- package/src/bmad-plus/agents/pack-seo/seo-chief.md +0 -294
- package/src/bmad-plus/agents/pack-seo/seo-judge.md +0 -241
- package/src/bmad-plus/agents/pack-seo/seo-scout.md +0 -171
- package/src/bmad-plus/agents/pack-seo/templates/seo-audit-workflow.md +0 -241
|
@@ -1,148 +1,148 @@
|
|
|
1
|
-
# Bases de données et outils d'enrichissement OSINT — France
|
|
2
|
-
|
|
3
|
-
## 🇫🇷 Registres d'entreprises (données publiques, gratuites)
|
|
4
|
-
|
|
5
|
-
### Pappers.fr ⭐ Priorité 1
|
|
6
|
-
- **URL** : https://www.pappers.fr
|
|
7
|
-
- **Données** : SIREN/SIRET, dirigeants (noms + adresses perso dans les statuts), bilans, statuts (PDF), actes, annonces BODACC
|
|
8
|
-
- **Gratuit** : Oui (accès complet aux fiches, PDFs des statuts et actes)
|
|
9
|
-
- **Astuce OSINT** : Les statuts de société contiennent souvent l'adresse personnelle du fondateur
|
|
10
|
-
- **Google dork** : `"Nom Prénom" site:pappers.fr` ou `"Nom" filetype:pdf site:pappers.fr`
|
|
11
|
-
|
|
12
|
-
### Societe.com
|
|
13
|
-
- **URL** : https://www.societe.com
|
|
14
|
-
- **Données** : Fiches entreprises, dirigeants, établissements, chiffre d'affaires
|
|
15
|
-
- **Gratuit** : Données de base gratuites, détails payants
|
|
16
|
-
- **Google dork** : `"Nom Prénom" site:societe.com dirigeant`
|
|
17
|
-
|
|
18
|
-
### Infogreffe.fr
|
|
19
|
-
- **URL** : https://www.infogreffe.fr
|
|
20
|
-
- **Données** : Kbis, comptes annuels, actes officiels
|
|
21
|
-
- **Gratuit** : Recherche gratuite, documents payants
|
|
22
|
-
|
|
23
|
-
### Verif.com
|
|
24
|
-
- **URL** : https://www.verif.com
|
|
25
|
-
- **Données** : Fiches entreprises, dirigeants, données financières
|
|
26
|
-
- **Gratuit** : Oui pour les infos de base
|
|
27
|
-
|
|
28
|
-
### BODACC (Bulletin Officiel des Annonces Civiles et Commerciales)
|
|
29
|
-
- **URL** : https://www.bodacc.fr
|
|
30
|
-
- **Données** : Créations, modifications, radiations, ventes de fonds de commerce
|
|
31
|
-
- **Gratuit** : Oui, source officielle
|
|
32
|
-
|
|
33
|
-
### INPI (Institut National de la Propriété Industrielle)
|
|
34
|
-
- **URL** : https://data.inpi.fr
|
|
35
|
-
- **Données** : Marques déposées, brevets (contient le nom du déposant)
|
|
36
|
-
- **Gratuit** : Oui
|
|
37
|
-
|
|
38
|
-
### Datalegal.fr
|
|
39
|
-
- **URL** : https://www.datalegal.fr
|
|
40
|
-
- **Données** : Mandats sociaux d'un dirigeant (toutes ses sociétés)
|
|
41
|
-
- **Gratuit** : Oui
|
|
42
|
-
- **Astuce** : Tapez un nom pour voir TOUTES les sociétés où la personne est dirigeante
|
|
43
|
-
|
|
44
|
-
---
|
|
45
|
-
|
|
46
|
-
## 📞 Outils d'enrichissement de contacts
|
|
47
|
-
|
|
48
|
-
### RocketReach ⭐ Priorité 1
|
|
49
|
-
- **URL** : https://rocketreach.co
|
|
50
|
-
- **Gratuit** : 5 lookups/mois
|
|
51
|
-
- **Données** : Emails professionnels/perso, numéros de téléphone (portables !), profils sociaux
|
|
52
|
-
- **Méthode** : Chercher le nom → voir les données partielles → utiliser un crédit gratuit pour révéler
|
|
53
|
-
|
|
54
|
-
### ContactOut
|
|
55
|
-
- **URL** : https://contactout.com
|
|
56
|
-
- **Gratuit** : Extension Chrome, quelques crédits gratuits
|
|
57
|
-
- **Données** : Emails et téléphones depuis les profils LinkedIn
|
|
58
|
-
- **Méthode** : Installer l'extension → aller sur le profil LinkedIn → ContactOut affiche les données
|
|
59
|
-
|
|
60
|
-
### Kaspr ⭐ Pour les portables FR
|
|
61
|
-
- **URL** : https://www.kaspr.io
|
|
62
|
-
- **Gratuit** : Extension Chrome + crédits gratuits à l'inscription
|
|
63
|
-
- **Données** : Numéros de portable français directs, emails
|
|
64
|
-
- **Méthode** : Extension Chrome sur LinkedIn → révèle le portable
|
|
65
|
-
- **Avantage** : Spécialisé sur les données françaises
|
|
66
|
-
|
|
67
|
-
### Lusha
|
|
68
|
-
- **URL** : https://www.lusha.com
|
|
69
|
-
- **Gratuit** : 5 crédits/mois
|
|
70
|
-
- **Données** : Téléphones directs, emails
|
|
71
|
-
|
|
72
|
-
### Apollo.io
|
|
73
|
-
- **URL** : https://www.apollo.io
|
|
74
|
-
- **Gratuit** : 50 crédits/mois
|
|
75
|
-
- **Données** : Emails, téléphones, firmographics
|
|
76
|
-
- **Avantage** : Filtrage avancé par industrie, taille d'entreprise, fonction
|
|
77
|
-
|
|
78
|
-
### Hunter.io
|
|
79
|
-
- **URL** : https://hunter.io
|
|
80
|
-
- **Gratuit** : 25 recherches/mois
|
|
81
|
-
- **Données** : Emails professionnels (pattern d'email de l'entreprise)
|
|
82
|
-
|
|
83
|
-
---
|
|
84
|
-
|
|
85
|
-
## 🔍 Google Dorks pour l'OSINT
|
|
86
|
-
|
|
87
|
-
### Recherche de documents
|
|
88
|
-
```
|
|
89
|
-
"Nom Prénom" filetype:pdf # CV, rapports, statuts, bilans
|
|
90
|
-
"Nom Prénom" filetype:pptx OR filetype:ppt # Présentations
|
|
91
|
-
"Nom Prénom" filetype:doc OR filetype:docx # Documents Word
|
|
92
|
-
"Nom Prénom" filetype:xls OR filetype:xlsx # Tableurs
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
### Recherche de numéros de téléphone
|
|
96
|
-
```
|
|
97
|
-
"Nom Prénom" ("06" OR "07" OR "+33 6" OR "+33 7") # Portables FR
|
|
98
|
-
"Nom Prénom" (telephone OR mobile OR portable) # Mentions de tel
|
|
99
|
-
"Nom Prénom" (CV OR resume OR curriculum) # CV avec coordonnées
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
### Recherche sur des sites spécifiques
|
|
103
|
-
```
|
|
104
|
-
"Nom" site:pappers.fr # Registre entreprises
|
|
105
|
-
"Nom" site:societe.com # Registre entreprises
|
|
106
|
-
"Nom" site:linkedin.com/in/ # Profil LinkedIn
|
|
107
|
-
"Nom" site:rocketreach.co # Enrichissement
|
|
108
|
-
"Nom" site:contactout.com # Enrichissement
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
### Recherche de données perso dans des statuts/actes
|
|
112
|
-
```
|
|
113
|
-
"Nom Prénom" "demeurant" site:pappers.fr # Adresse perso dans statuts
|
|
114
|
-
"Nom Prénom" inurl:statuts filetype:pdf # Statuts de société
|
|
115
|
-
"Nom Prénom" "né(e) le" # Date de naissance
|
|
116
|
-
```
|
|
117
|
-
|
|
118
|
-
---
|
|
119
|
-
|
|
120
|
-
## 📱 Réseaux sociaux et profils publics
|
|
121
|
-
|
|
122
|
-
### LinkedIn
|
|
123
|
-
- Profils professionnels, parcours, connexions
|
|
124
|
-
- Avec Kaspr/ContactOut/Lusha → révèle les portables
|
|
125
|
-
|
|
126
|
-
### Instagram
|
|
127
|
-
- DM pour contact direct (surtout influenceurs)
|
|
128
|
-
- Le bouton "Contact" affiche souvent l'email pro
|
|
129
|
-
|
|
130
|
-
### Pages Jaunes / 118712
|
|
131
|
-
- **URL** : https://www.pagesjaunes.fr / https://www.118712.fr
|
|
132
|
-
- Pour les numéros de téléphone fixes et professionnels
|
|
133
|
-
|
|
134
|
-
### YouTube
|
|
135
|
-
- Les descriptions de vidéos contiennent parfois des emails de contact
|
|
136
|
-
- Les chaînes business ont un onglet "À propos" avec contact
|
|
137
|
-
|
|
138
|
-
---
|
|
139
|
-
|
|
140
|
-
## Escalation recommandée (coût croissant)
|
|
141
|
-
|
|
142
|
-
| Niveau | Sources | Coût |
|
|
143
|
-
|--------|---------|------|
|
|
144
|
-
| 1. Gratuit | Google dorks, Pappers, Societe.com, BODACC, INPI | 0€ |
|
|
145
|
-
| 2. Freemium | RocketReach (5/mois), Kaspr (gratuit), Apollo (50/mois) | 0€ |
|
|
146
|
-
| 3. Cheap | Jina search, Tavily search | ~$0.01 |
|
|
147
|
-
| 4. Medium | Apify scrapers, ContactOut | ~$0.10 |
|
|
148
|
-
| 5. Premium | Perplexity Deep, Exa Deep | ~$0.50 |
|
|
1
|
+
# Bases de données et outils d'enrichissement OSINT — France
|
|
2
|
+
|
|
3
|
+
## 🇫🇷 Registres d'entreprises (données publiques, gratuites)
|
|
4
|
+
|
|
5
|
+
### Pappers.fr ⭐ Priorité 1
|
|
6
|
+
- **URL** : https://www.pappers.fr
|
|
7
|
+
- **Données** : SIREN/SIRET, dirigeants (noms + adresses perso dans les statuts), bilans, statuts (PDF), actes, annonces BODACC
|
|
8
|
+
- **Gratuit** : Oui (accès complet aux fiches, PDFs des statuts et actes)
|
|
9
|
+
- **Astuce OSINT** : Les statuts de société contiennent souvent l'adresse personnelle du fondateur
|
|
10
|
+
- **Google dork** : `"Nom Prénom" site:pappers.fr` ou `"Nom" filetype:pdf site:pappers.fr`
|
|
11
|
+
|
|
12
|
+
### Societe.com
|
|
13
|
+
- **URL** : https://www.societe.com
|
|
14
|
+
- **Données** : Fiches entreprises, dirigeants, établissements, chiffre d'affaires
|
|
15
|
+
- **Gratuit** : Données de base gratuites, détails payants
|
|
16
|
+
- **Google dork** : `"Nom Prénom" site:societe.com dirigeant`
|
|
17
|
+
|
|
18
|
+
### Infogreffe.fr
|
|
19
|
+
- **URL** : https://www.infogreffe.fr
|
|
20
|
+
- **Données** : Kbis, comptes annuels, actes officiels
|
|
21
|
+
- **Gratuit** : Recherche gratuite, documents payants
|
|
22
|
+
|
|
23
|
+
### Verif.com
|
|
24
|
+
- **URL** : https://www.verif.com
|
|
25
|
+
- **Données** : Fiches entreprises, dirigeants, données financières
|
|
26
|
+
- **Gratuit** : Oui pour les infos de base
|
|
27
|
+
|
|
28
|
+
### BODACC (Bulletin Officiel des Annonces Civiles et Commerciales)
|
|
29
|
+
- **URL** : https://www.bodacc.fr
|
|
30
|
+
- **Données** : Créations, modifications, radiations, ventes de fonds de commerce
|
|
31
|
+
- **Gratuit** : Oui, source officielle
|
|
32
|
+
|
|
33
|
+
### INPI (Institut National de la Propriété Industrielle)
|
|
34
|
+
- **URL** : https://data.inpi.fr
|
|
35
|
+
- **Données** : Marques déposées, brevets (contient le nom du déposant)
|
|
36
|
+
- **Gratuit** : Oui
|
|
37
|
+
|
|
38
|
+
### Datalegal.fr
|
|
39
|
+
- **URL** : https://www.datalegal.fr
|
|
40
|
+
- **Données** : Mandats sociaux d'un dirigeant (toutes ses sociétés)
|
|
41
|
+
- **Gratuit** : Oui
|
|
42
|
+
- **Astuce** : Tapez un nom pour voir TOUTES les sociétés où la personne est dirigeante
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## 📞 Outils d'enrichissement de contacts
|
|
47
|
+
|
|
48
|
+
### RocketReach ⭐ Priorité 1
|
|
49
|
+
- **URL** : https://rocketreach.co
|
|
50
|
+
- **Gratuit** : 5 lookups/mois
|
|
51
|
+
- **Données** : Emails professionnels/perso, numéros de téléphone (portables !), profils sociaux
|
|
52
|
+
- **Méthode** : Chercher le nom → voir les données partielles → utiliser un crédit gratuit pour révéler
|
|
53
|
+
|
|
54
|
+
### ContactOut
|
|
55
|
+
- **URL** : https://contactout.com
|
|
56
|
+
- **Gratuit** : Extension Chrome, quelques crédits gratuits
|
|
57
|
+
- **Données** : Emails et téléphones depuis les profils LinkedIn
|
|
58
|
+
- **Méthode** : Installer l'extension → aller sur le profil LinkedIn → ContactOut affiche les données
|
|
59
|
+
|
|
60
|
+
### Kaspr ⭐ Pour les portables FR
|
|
61
|
+
- **URL** : https://www.kaspr.io
|
|
62
|
+
- **Gratuit** : Extension Chrome + crédits gratuits à l'inscription
|
|
63
|
+
- **Données** : Numéros de portable français directs, emails
|
|
64
|
+
- **Méthode** : Extension Chrome sur LinkedIn → révèle le portable
|
|
65
|
+
- **Avantage** : Spécialisé sur les données françaises
|
|
66
|
+
|
|
67
|
+
### Lusha
|
|
68
|
+
- **URL** : https://www.lusha.com
|
|
69
|
+
- **Gratuit** : 5 crédits/mois
|
|
70
|
+
- **Données** : Téléphones directs, emails
|
|
71
|
+
|
|
72
|
+
### Apollo.io
|
|
73
|
+
- **URL** : https://www.apollo.io
|
|
74
|
+
- **Gratuit** : 50 crédits/mois
|
|
75
|
+
- **Données** : Emails, téléphones, firmographics
|
|
76
|
+
- **Avantage** : Filtrage avancé par industrie, taille d'entreprise, fonction
|
|
77
|
+
|
|
78
|
+
### Hunter.io
|
|
79
|
+
- **URL** : https://hunter.io
|
|
80
|
+
- **Gratuit** : 25 recherches/mois
|
|
81
|
+
- **Données** : Emails professionnels (pattern d'email de l'entreprise)
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## 🔍 Google Dorks pour l'OSINT
|
|
86
|
+
|
|
87
|
+
### Recherche de documents
|
|
88
|
+
```
|
|
89
|
+
"Nom Prénom" filetype:pdf # CV, rapports, statuts, bilans
|
|
90
|
+
"Nom Prénom" filetype:pptx OR filetype:ppt # Présentations
|
|
91
|
+
"Nom Prénom" filetype:doc OR filetype:docx # Documents Word
|
|
92
|
+
"Nom Prénom" filetype:xls OR filetype:xlsx # Tableurs
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Recherche de numéros de téléphone
|
|
96
|
+
```
|
|
97
|
+
"Nom Prénom" ("06" OR "07" OR "+33 6" OR "+33 7") # Portables FR
|
|
98
|
+
"Nom Prénom" (telephone OR mobile OR portable) # Mentions de tel
|
|
99
|
+
"Nom Prénom" (CV OR resume OR curriculum) # CV avec coordonnées
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Recherche sur des sites spécifiques
|
|
103
|
+
```
|
|
104
|
+
"Nom" site:pappers.fr # Registre entreprises
|
|
105
|
+
"Nom" site:societe.com # Registre entreprises
|
|
106
|
+
"Nom" site:linkedin.com/in/ # Profil LinkedIn
|
|
107
|
+
"Nom" site:rocketreach.co # Enrichissement
|
|
108
|
+
"Nom" site:contactout.com # Enrichissement
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Recherche de données perso dans des statuts/actes
|
|
112
|
+
```
|
|
113
|
+
"Nom Prénom" "demeurant" site:pappers.fr # Adresse perso dans statuts
|
|
114
|
+
"Nom Prénom" inurl:statuts filetype:pdf # Statuts de société
|
|
115
|
+
"Nom Prénom" "né(e) le" # Date de naissance
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
---
|
|
119
|
+
|
|
120
|
+
## 📱 Réseaux sociaux et profils publics
|
|
121
|
+
|
|
122
|
+
### LinkedIn
|
|
123
|
+
- Profils professionnels, parcours, connexions
|
|
124
|
+
- Avec Kaspr/ContactOut/Lusha → révèle les portables
|
|
125
|
+
|
|
126
|
+
### Instagram
|
|
127
|
+
- DM pour contact direct (surtout influenceurs)
|
|
128
|
+
- Le bouton "Contact" affiche souvent l'email pro
|
|
129
|
+
|
|
130
|
+
### Pages Jaunes / 118712
|
|
131
|
+
- **URL** : https://www.pagesjaunes.fr / https://www.118712.fr
|
|
132
|
+
- Pour les numéros de téléphone fixes et professionnels
|
|
133
|
+
|
|
134
|
+
### YouTube
|
|
135
|
+
- Les descriptions de vidéos contiennent parfois des emails de contact
|
|
136
|
+
- Les chaînes business ont un onglet "À propos" avec contact
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Escalation recommandée (coût croissant)
|
|
141
|
+
|
|
142
|
+
| Niveau | Sources | Coût |
|
|
143
|
+
|--------|---------|------|
|
|
144
|
+
| 1. Gratuit | Google dorks, Pappers, Societe.com, BODACC, INPI | 0€ |
|
|
145
|
+
| 2. Freemium | RocketReach (5/mois), Kaspr (gratuit), Apollo (50/mois) | 0€ |
|
|
146
|
+
| 3. Cheap | Jina search, Tavily search | ~$0.01 |
|
|
147
|
+
| 4. Medium | Apify scrapers, ContactOut | ~$0.10 |
|
|
148
|
+
| 5. Premium | Perplexity Deep, Exa Deep | ~$0.50 |
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
"""Shared HTTP utilities for OSINT scripts — stdlib only, zero dependencies."""
|
|
2
|
-
|
|
3
|
-
import http.client
|
|
4
|
-
import json
|
|
5
|
-
import os
|
|
6
|
-
import ssl
|
|
7
|
-
import sys
|
|
8
|
-
from urllib.parse import urlparse, urlencode, quote
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
def https_request(method, url, headers=None, body=None, timeout=120):
|
|
12
|
-
"""Make an HTTPS request and return (status, headers, body_str).
|
|
13
|
-
|
|
14
|
-
Handles both http and https URLs.
|
|
15
|
-
"""
|
|
16
|
-
parsed = urlparse(url)
|
|
17
|
-
scheme = parsed.scheme or "https"
|
|
18
|
-
host = parsed.hostname
|
|
19
|
-
port = parsed.port or (443 if scheme == "https" else 80)
|
|
20
|
-
path = parsed.path or "/"
|
|
21
|
-
if parsed.query:
|
|
22
|
-
path += "?" + parsed.query
|
|
23
|
-
|
|
24
|
-
if scheme == "https":
|
|
25
|
-
ctx = ssl.create_default_context()
|
|
26
|
-
conn = http.client.HTTPSConnection(host, port, timeout=timeout, context=ctx)
|
|
27
|
-
else:
|
|
28
|
-
conn = http.client.HTTPConnection(host, port, timeout=timeout)
|
|
29
|
-
|
|
30
|
-
hdrs = {"User-Agent": "osint-skill/3.2-python"}
|
|
31
|
-
if headers:
|
|
32
|
-
hdrs.update(headers)
|
|
33
|
-
|
|
34
|
-
conn.request(method, path, body=body, headers=hdrs)
|
|
35
|
-
resp = conn.getresponse()
|
|
36
|
-
data = resp.read().decode("utf-8", errors="replace")
|
|
37
|
-
status = resp.status
|
|
38
|
-
resp_headers = dict(resp.getheaders())
|
|
39
|
-
conn.close()
|
|
40
|
-
return status, resp_headers, data
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
def api_post(url, payload, headers=None, timeout=120):
|
|
44
|
-
"""POST JSON payload and return parsed JSON response."""
|
|
45
|
-
hdrs = {"Content-Type": "application/json"}
|
|
46
|
-
if headers:
|
|
47
|
-
hdrs.update(headers)
|
|
48
|
-
body = json.dumps(payload) if isinstance(payload, dict) else payload
|
|
49
|
-
status, _, data = https_request("POST", url, headers=hdrs, body=body, timeout=timeout)
|
|
50
|
-
if status >= 400:
|
|
51
|
-
print(f"ERROR: HTTP {status}: {data[:300]}", file=sys.stderr)
|
|
52
|
-
return None
|
|
53
|
-
try:
|
|
54
|
-
return json.loads(data)
|
|
55
|
-
except json.JSONDecodeError:
|
|
56
|
-
print(f"ERROR: Invalid JSON response: {data[:300]}", file=sys.stderr)
|
|
57
|
-
return None
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
def api_get(url, headers=None, timeout=120):
|
|
61
|
-
"""GET request and return parsed JSON response."""
|
|
62
|
-
status, _, data = https_request("GET", url, headers=headers, timeout=timeout)
|
|
63
|
-
if status >= 400:
|
|
64
|
-
print(f"ERROR: HTTP {status}: {data[:300]}", file=sys.stderr)
|
|
65
|
-
return None
|
|
66
|
-
try:
|
|
67
|
-
return json.loads(data)
|
|
68
|
-
except json.JSONDecodeError:
|
|
69
|
-
# Return raw text if not JSON
|
|
70
|
-
return {"raw": data[:5000]}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
def get_key(env_var, file_fallback=None, required=True, help_url=""):
|
|
74
|
-
"""Load API key from environment or fallback file."""
|
|
75
|
-
val = os.environ.get(env_var, "")
|
|
76
|
-
if val:
|
|
77
|
-
return val
|
|
78
|
-
if file_fallback and os.path.isfile(file_fallback):
|
|
79
|
-
with open(file_fallback, "r") as f:
|
|
80
|
-
return f.readline().strip()
|
|
81
|
-
if required:
|
|
82
|
-
print(f"ERROR: {env_var} not set.", file=sys.stderr)
|
|
83
|
-
if help_url:
|
|
84
|
-
print(f"Get one at: {help_url}", file=sys.stderr)
|
|
85
|
-
sys.exit(1)
|
|
86
|
-
return ""
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
def get_workspace():
|
|
90
|
-
"""Get workspace root (2 levels up from scripts dir)."""
|
|
91
|
-
scripts_dir = os.path.dirname(os.path.abspath(__file__))
|
|
92
|
-
skill_dir = os.path.dirname(scripts_dir)
|
|
93
|
-
workspace = os.path.dirname(os.path.dirname(skill_dir))
|
|
94
|
-
return workspace, skill_dir, scripts_dir
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def truncate(text, max_len=200):
|
|
98
|
-
"""Truncate text with ellipsis."""
|
|
99
|
-
if not text:
|
|
100
|
-
return ""
|
|
101
|
-
return text[:max_len] + "..." if len(text) > max_len else text
|
|
1
|
+
"""Shared HTTP utilities for OSINT scripts — stdlib only, zero dependencies."""
|
|
2
|
+
|
|
3
|
+
import http.client
|
|
4
|
+
import json
|
|
5
|
+
import os
|
|
6
|
+
import ssl
|
|
7
|
+
import sys
|
|
8
|
+
from urllib.parse import urlparse, urlencode, quote
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def https_request(method, url, headers=None, body=None, timeout=120):
|
|
12
|
+
"""Make an HTTPS request and return (status, headers, body_str).
|
|
13
|
+
|
|
14
|
+
Handles both http and https URLs.
|
|
15
|
+
"""
|
|
16
|
+
parsed = urlparse(url)
|
|
17
|
+
scheme = parsed.scheme or "https"
|
|
18
|
+
host = parsed.hostname
|
|
19
|
+
port = parsed.port or (443 if scheme == "https" else 80)
|
|
20
|
+
path = parsed.path or "/"
|
|
21
|
+
if parsed.query:
|
|
22
|
+
path += "?" + parsed.query
|
|
23
|
+
|
|
24
|
+
if scheme == "https":
|
|
25
|
+
ctx = ssl.create_default_context()
|
|
26
|
+
conn = http.client.HTTPSConnection(host, port, timeout=timeout, context=ctx)
|
|
27
|
+
else:
|
|
28
|
+
conn = http.client.HTTPConnection(host, port, timeout=timeout)
|
|
29
|
+
|
|
30
|
+
hdrs = {"User-Agent": "osint-skill/3.2-python"}
|
|
31
|
+
if headers:
|
|
32
|
+
hdrs.update(headers)
|
|
33
|
+
|
|
34
|
+
conn.request(method, path, body=body, headers=hdrs)
|
|
35
|
+
resp = conn.getresponse()
|
|
36
|
+
data = resp.read().decode("utf-8", errors="replace")
|
|
37
|
+
status = resp.status
|
|
38
|
+
resp_headers = dict(resp.getheaders())
|
|
39
|
+
conn.close()
|
|
40
|
+
return status, resp_headers, data
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def api_post(url, payload, headers=None, timeout=120):
|
|
44
|
+
"""POST JSON payload and return parsed JSON response."""
|
|
45
|
+
hdrs = {"Content-Type": "application/json"}
|
|
46
|
+
if headers:
|
|
47
|
+
hdrs.update(headers)
|
|
48
|
+
body = json.dumps(payload) if isinstance(payload, dict) else payload
|
|
49
|
+
status, _, data = https_request("POST", url, headers=hdrs, body=body, timeout=timeout)
|
|
50
|
+
if status >= 400:
|
|
51
|
+
print(f"ERROR: HTTP {status}: {data[:300]}", file=sys.stderr)
|
|
52
|
+
return None
|
|
53
|
+
try:
|
|
54
|
+
return json.loads(data)
|
|
55
|
+
except json.JSONDecodeError:
|
|
56
|
+
print(f"ERROR: Invalid JSON response: {data[:300]}", file=sys.stderr)
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def api_get(url, headers=None, timeout=120):
|
|
61
|
+
"""GET request and return parsed JSON response."""
|
|
62
|
+
status, _, data = https_request("GET", url, headers=headers, timeout=timeout)
|
|
63
|
+
if status >= 400:
|
|
64
|
+
print(f"ERROR: HTTP {status}: {data[:300]}", file=sys.stderr)
|
|
65
|
+
return None
|
|
66
|
+
try:
|
|
67
|
+
return json.loads(data)
|
|
68
|
+
except json.JSONDecodeError:
|
|
69
|
+
# Return raw text if not JSON
|
|
70
|
+
return {"raw": data[:5000]}
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def get_key(env_var, file_fallback=None, required=True, help_url=""):
|
|
74
|
+
"""Load API key from environment or fallback file."""
|
|
75
|
+
val = os.environ.get(env_var, "")
|
|
76
|
+
if val:
|
|
77
|
+
return val
|
|
78
|
+
if file_fallback and os.path.isfile(file_fallback):
|
|
79
|
+
with open(file_fallback, "r") as f:
|
|
80
|
+
return f.readline().strip()
|
|
81
|
+
if required:
|
|
82
|
+
print(f"ERROR: {env_var} not set.", file=sys.stderr)
|
|
83
|
+
if help_url:
|
|
84
|
+
print(f"Get one at: {help_url}", file=sys.stderr)
|
|
85
|
+
sys.exit(1)
|
|
86
|
+
return ""
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def get_workspace():
|
|
90
|
+
"""Get workspace root (2 levels up from scripts dir)."""
|
|
91
|
+
scripts_dir = os.path.dirname(os.path.abspath(__file__))
|
|
92
|
+
skill_dir = os.path.dirname(scripts_dir)
|
|
93
|
+
workspace = os.path.dirname(os.path.dirname(skill_dir))
|
|
94
|
+
return workspace, skill_dir, scripts_dir
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def truncate(text, max_len=200):
|
|
98
|
+
"""Truncate text with ellipsis."""
|
|
99
|
+
if not text:
|
|
100
|
+
return ""
|
|
101
|
+
return text[:max_len] + "..." if len(text) > max_len else text
|