optbrew 0.0.0-stage → 0.1.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/.claude-plugin/marketplace.json +6 -0
- package/.claude-plugin/plugin.json +6 -0
- package/.codex-plugin/plugin.json +13 -0
- package/CHANGELOG.md +20 -0
- package/LICENSE +21 -0
- package/README.ko.md +73 -0
- package/README.md +72 -2
- package/THIRD_PARTY_NOTICES.md +10 -0
- package/bin/optbrew.mjs +4 -0
- package/docs/platforms.md +31 -0
- package/docs/release.md +14 -0
- package/lib/cli.mjs +103 -0
- package/lib/doctor.mjs +44 -0
- package/lib/install.mjs +158 -0
- package/lib/paths.mjs +30 -0
- package/lib/records.mjs +44 -0
- package/lib/transaction.mjs +205 -0
- package/lib/update.mjs +181 -0
- package/package.json +39 -4
- package/plugin.json +13 -0
- package/skills/optbrew/LICENSE +21 -0
- package/skills/optbrew/SKILL.md +17 -0
- package/skills/optbrew/THIRD_PARTY_NOTICES.md +10 -0
- package/skills/optbrew/agents/openai.yaml +4 -0
- package/skills/optbrew/bundle-manifest.json +663 -0
- package/skills/optbrew/licenses/firecrawl-seo-audit.txt +15 -0
- package/skills/optbrew/licenses/magnus-seo.txt +21 -0
- package/skills/optbrew/licenses/marketing-search.txt +21 -0
- package/skills/optbrew/licenses/mblode-seo.txt +21 -0
- package/skills/optbrew/licenses/naver-searchadvisor.txt +29 -0
- package/skills/optbrew/licenses/seranking-seo.txt +21 -0
- package/skills/optbrew/modules/firecrawl-seo-audit/GUIDE.md +64 -0
- package/skills/optbrew/modules/magnus-seo/GUIDE.md +79 -0
- package/skills/optbrew/modules/magnus-seo/README.md +45 -0
- package/skills/optbrew/modules/magnus-seo/assets/audit-report-template.md +76 -0
- package/skills/optbrew/modules/magnus-seo/references/aeo-methodology.md +105 -0
- package/skills/optbrew/modules/magnus-seo/references/agent-readable-content.md +28 -0
- package/skills/optbrew/modules/magnus-seo/references/content-and-entity-architecture.md +100 -0
- package/skills/optbrew/modules/magnus-seo/references/content-strategy-seo.md +142 -0
- package/skills/optbrew/modules/magnus-seo/references/discovery-and-freshness.md +47 -0
- package/skills/optbrew/modules/magnus-seo/references/evidence-boundaries.md +75 -0
- package/skills/optbrew/modules/magnus-seo/references/ghost-metadata.md +204 -0
- package/skills/optbrew/modules/magnus-seo/references/implementation-playbook.md +114 -0
- package/skills/optbrew/modules/magnus-seo/references/measurement-and-experimentation.md +47 -0
- package/skills/optbrew/modules/magnus-seo/references/onpage-seo.md +154 -0
- package/skills/optbrew/modules/magnus-seo/references/platform-guidance.md +30 -0
- package/skills/optbrew/modules/magnus-seo/references/schema-markup.md +244 -0
- package/skills/optbrew/modules/magnus-seo/references/source-index.md +36 -0
- package/skills/optbrew/modules/magnus-seo/references/structured-data.md +56 -0
- package/skills/optbrew/modules/magnus-seo/references/technical-seo.md +99 -0
- package/skills/optbrew/modules/magnus-seo/scripts/aeo_audit.py +158 -0
- package/skills/optbrew/modules/magnus-seo/scripts/build_prompt_matrix.py +52 -0
- package/skills/optbrew/modules/magnus-seo/templates/aeo-implementation-plan.md +53 -0
- package/skills/optbrew/modules/magnus-seo/templates/citation-observation-log.md +16 -0
- package/skills/optbrew/modules/magnus-seo/templates/llms.txt.template +15 -0
- package/skills/optbrew/modules/magnus-seo/templates/question-cluster.md +27 -0
- package/skills/optbrew/modules/magnus-seo/templates/robots-ai-crawlers.txt +23 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/GUIDE.md +483 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/agent-readiness.md +57 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/citations-vs-recommendations.md +85 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/content-patterns.md +287 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/content-types.md +71 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/format-volatility.md +98 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/okf.md +104 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/platform-ranking-factors.md +154 -0
- package/skills/optbrew/modules/marketing-search/skills/ai-seo/references/youtube-ai-citations.md +60 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/GUIDE.md +303 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/references/event-library.md +260 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/references/ga4-implementation.md +300 -0
- package/skills/optbrew/modules/marketing-search/skills/analytics/references/gtm-implementation.md +390 -0
- package/skills/optbrew/modules/marketing-search/skills/content-strategy/GUIDE.md +432 -0
- package/skills/optbrew/modules/marketing-search/skills/content-strategy/references/content-distribution.md +83 -0
- package/skills/optbrew/modules/marketing-search/skills/content-strategy/references/headless-cms.md +194 -0
- package/skills/optbrew/modules/marketing-search/skills/programmatic-seo/GUIDE.md +231 -0
- package/skills/optbrew/modules/marketing-search/skills/programmatic-seo/references/playbooks.md +308 -0
- package/skills/optbrew/modules/marketing-search/skills/schema/GUIDE.md +172 -0
- package/skills/optbrew/modules/marketing-search/skills/schema/references/schema-examples.md +398 -0
- package/skills/optbrew/modules/marketing-search/skills/seo-audit/GUIDE.md +492 -0
- package/skills/optbrew/modules/marketing-search/skills/seo-audit/references/ai-writing-detection.md +200 -0
- package/skills/optbrew/modules/marketing-search/skills/seo-audit/references/international-seo.md +230 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/GUIDE.md +350 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/references/mermaid-templates.md +216 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/references/navigation-patterns.md +305 -0
- package/skills/optbrew/modules/marketing-search/skills/site-architecture/references/site-type-templates.md +293 -0
- package/skills/optbrew/modules/mblode-seo/GUIDE.md +74 -0
- package/skills/optbrew/modules/mblode-seo/references/answer-engines.md +58 -0
- package/skills/optbrew/modules/mblode-seo/references/audit.md +78 -0
- package/skills/optbrew/modules/mblode-seo/references/brief-template.md +47 -0
- package/skills/optbrew/modules/mblode-seo/references/monitoring.md +56 -0
- package/skills/optbrew/modules/mblode-seo/references/nextjs-implementation.md +65 -0
- package/skills/optbrew/modules/mblode-seo/references/research-protocol.md +37 -0
- package/skills/optbrew/modules/mblode-seo/references/sources.md +47 -0
- package/skills/optbrew/modules/mblode-seo/references/validation-evidence.md +21 -0
- package/skills/optbrew/modules/naver-searchadvisor/GUIDE.md +75 -0
- package/skills/optbrew/modules/naver-searchadvisor/NOTICE.md +59 -0
- package/skills/optbrew/modules/naver-searchadvisor/references/INDEX.md +97 -0
- package/skills/optbrew/modules/naver-searchadvisor/scripts/audit.mjs +714 -0
- package/skills/optbrew/modules/naver-searchadvisor/scripts/robots.mjs +77 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-ai-search-share-of-voice/GUIDE.md +94 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/GUIDE.md +186 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/api-surface-map.md +207 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/auth-and-keys.md +182 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/integration-patterns.md +283 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-api/references/rate-limits-and-credits.md +235 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-competitor-gap-analysis/GUIDE.md +117 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/GUIDE.md +155 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/references/cite.md +84 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/references/core-eeat.md +147 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-content-audit/templates/verdict.md +63 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-firecrawl/GUIDE.md +141 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-firecrawl/references/preflight.md +73 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-geo/GUIDE.md +159 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/GUIDE.md +393 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/assets/templates/cwv-audit-report.md +48 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/assets/templates/gsc-performance-report.md +44 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/assets/templates/indexation-status-report.md +43 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/auth-setup.md +160 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/cross-skill-integration.md +187 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/ga4-data-api.md +184 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/indexing-api.md +109 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/keyword-planner-api.md +66 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/nlp-api.md +55 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/pagespeed-crux-api.md +204 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/rate-limits-quotas.md +75 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/search-console-api.md +156 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/supplementary-apis.md +99 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-google/references/youtube-api.md +49 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-keyword-niche/GUIDE.md +174 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-page/GUIDE.md +174 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-plan/GUIDE.md +220 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/GUIDE.md +135 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/references/google-rich-results.md +89 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/article.json +23 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/breadcrumb-list.json +18 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/faq-page.json +22 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/local-business.json +32 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-schema/templates/product.json +25 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-sitemap/GUIDE.md +128 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-technical-audit/GUIDE.md +235 -0
- package/skills/optbrew/modules/seranking-seo/skills/seo-technical-audit/references/severity-mapping.md +133 -0
- package/skills/optbrew/references/api.md +45 -0
- package/skills/optbrew/references/check-registry.json +28 -0
- package/skills/optbrew/references/evidence.md +9 -0
- package/skills/optbrew/references/intake.md +9 -0
- package/skills/optbrew/references/measurement.md +29 -0
- package/skills/optbrew/references/policies.md +7 -0
- package/skills/optbrew/references/profiles.json +13 -0
- package/skills/optbrew/references/remediations.json +12 -0
- package/skills/optbrew/references/report.md +25 -0
- package/skills/optbrew/references/routing.md +15 -0
- package/skills/optbrew/references/schemas/contract.schema.json +51 -0
- package/skills/optbrew/references/scoring.md +62 -0
- package/skills/optbrew/scripts/adapters/anthropic.mjs +116 -0
- package/skills/optbrew/scripts/adapters/imports.mjs +81 -0
- package/skills/optbrew/scripts/audit.mjs +145 -0
- package/skills/optbrew/scripts/cli.mjs +41 -0
- package/skills/optbrew/scripts/core/bootstrap.mjs +31 -0
- package/skills/optbrew/scripts/core/bundle.mjs +73 -0
- package/skills/optbrew/scripts/core/capabilities.mjs +19 -0
- package/skills/optbrew/scripts/core/collector.mjs +236 -0
- package/skills/optbrew/scripts/core/compare.mjs +47 -0
- package/skills/optbrew/scripts/core/contracts.mjs +144 -0
- package/skills/optbrew/scripts/core/cost-ledger.mjs +95 -0
- package/skills/optbrew/scripts/core/findings.mjs +54 -0
- package/skills/optbrew/scripts/core/metrics.mjs +97 -0
- package/skills/optbrew/scripts/core/protocol.mjs +125 -0
- package/skills/optbrew/scripts/core/report.mjs +652 -0
- package/skills/optbrew/scripts/core/scope.mjs +52 -0
- package/skills/optbrew/scripts/core/score.mjs +71 -0
- package/skills/optbrew/scripts/core/weights.mjs +139 -0
- package/skills/optbrew/source-lock.json +2686 -0
- package/source-lock.json +2686 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
|
+
"name": "optbrew",
|
|
4
|
+
"version": "0.1.1",
|
|
5
|
+
"description": "Pinned search audit and improvement skill bundle",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"extensions": {
|
|
8
|
+
"com.openai": {
|
|
9
|
+
"skills": ["./skills/optbrew"],
|
|
10
|
+
"release_version": "0.1.1"
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
}
|
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.1 — local release candidate
|
|
4
|
+
|
|
5
|
+
- Verified a real localhost noindex/title baseline, backed-up local edit, same-condition rescan and evidence-bound JSON/Markdown report. The collector emits pass or fail observations for completed index checks, a fail for a missing title and unknown for a present one (uniqueness and descriptiveness need separate evidence), and the report replays title, index and crawl-policy verdicts from the preserved raw bytes.
|
|
6
|
+
- Audit evidence produced before the hashed response records existed must be re-collected; the audit evidence format changed during 0.1.1 development, and report replay now rejects older audit output. Report replay also rejects a selected page that is neither collected nor skipped, and a packet that drops its audit snapshot while collector evidence is indexed. A production resolution now names the evaluator type and source of its resolving observation.
|
|
7
|
+
- Final review round 2: the collector keeps each X-Robots-Tag header line separate and hashes a response record (final URL, redirect chain, header lines) beside every raw body; report replay binds the final URL and headers to that record, requires every planned collector observation, and accepts `verified_local` only through the production-style observation binding of a collector-produced after observation. Native export paths refuse protocol-relative or other-host URLs, a semicolon separates robots meta directives, and the ZIP verifier refuses Windows case-insensitive and trailing dot or space name collisions.
|
|
8
|
+
- Final review fixes: index directives ignore commented or script text and follow the target engine's meta and X-Robots-Tag scope; report replay accepts permitted redirects and header-only noindex findings and re-derives robots verdicts; a byte-hash receipt alone no longer marks a fix verified locally; redirect hops count against the 50-request budget; native path mappings match whole path segments; the release verifier rejects unextractable ZIP layouts.
|
|
9
|
+
- Bound runtime scoring to the installed evaluation/protocol source hashes and versions. The evaluation and observation protocol versions remain 0.1.0. Root notice links resolve to the packaged skill licenses.
|
|
10
|
+
- Fixed direct audit and calculation entrypoints invoked through managed Windows junctions or Unix symlinks. Ordinary imports remain inert.
|
|
11
|
+
- The report separates baseline and after blocker counts. Locally verified fixes now lead to production deployment/reobservation work instead of repeating the original edit instruction.
|
|
12
|
+
- One fresh Codex bare invocation completed on the local 0.1.0 install. Broader native behavior and Claude Code invocation remain unverified for this corrected release.
|
|
13
|
+
|
|
14
|
+
## 0.1.0 — local prepublication install
|
|
15
|
+
|
|
16
|
+
- Added one pinned optbrew skill source with five selected source bundles and seven marketing guides. Retained notices and modification records; excluded 55 Naver original guide articles while keeping official index links.
|
|
17
|
+
- Added local collection boundaries, evidence-based readiness scoring, before/after comparison, and report generation. Scores distinguish unknown checks, blockers, and actual outcomes.
|
|
18
|
+
- Added managed install, doctor, update, and rollback paths for Codex, Claude Code, Cursor, OpenCode, and Pi; added host plugin and Pi package metadata.
|
|
19
|
+
- Added a text-only direct Anthropic adapter with exact model and token-bound checks. API use remains optional and requires an approved cost decision.
|
|
20
|
+
- Added English and Korean usage, API, platform, and release instructions. This initial local install did not establish public npm/GitHub publication or native host invocation.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 optbrew contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.ko.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# optbrew
|
|
2
|
+
|
|
3
|
+
[English](README.md)
|
|
4
|
+
|
|
5
|
+
Optbrew는 웹사이트의 검색 준비도를 확인하고, 승인된 로컬 파일을 고친 뒤, 전후 근거를 비교하는 스킬과 CLI입니다. 고정된 원본 묶음 5개(mblode SEO, Naver Search Advisor, Firecrawl SEO Audit, Magnus SEO, SE Ranking SEO)와 선택한 마케팅 가이드 7개를 포함합니다. 최상위 `SKILL.md` 한 파일이 내부 가이드를 안내합니다. 실행 중에 바뀌는 upstream 파일을 가져오지 않습니다.
|
|
6
|
+
|
|
7
|
+
저장된 JSON으로 점수를 계산하고 보고서를 만드는 데 API 계정은 필요하지 않습니다. 사이트 감사에는 대상과 허용 범위가 필요합니다. 공개 게시, 검색엔진 제출, 원격 사이트 수정, 유료 호출은 각각 별도 권한이 필요합니다. 설치 파일이 놓인 상태와 호스트가 실제로 스킬을 호출한 상태는 [플랫폼 안내](docs/platforms.md)에서 구분합니다.
|
|
8
|
+
|
|
9
|
+
## 설치
|
|
10
|
+
|
|
11
|
+
Node.js 22 이상이 필요합니다. 내부 Python 감사 도구는 Python 3.10 이상이 필요합니다. Python이 없으면 그 도구는 미실행으로 남깁니다. 이 checkout에서 `site`라는 별도 프로젝트 폴더를 만든 뒤 실행합니다.
|
|
12
|
+
|
|
13
|
+
Bash와 PowerShell에서 같은 명령을 사용합니다.
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
node bin/optbrew.mjs install --agents codex,claude-code,cursor,opencode,pi --scope project --project ./site --strategy copy --dry-run --json
|
|
17
|
+
node bin/optbrew.mjs install --agents codex,claude-code,cursor,opencode,pi --scope project --project ./site --strategy copy --json
|
|
18
|
+
node bin/optbrew.mjs doctor --agents codex,claude-code,cursor,opencode,pi --scope project --project ./site --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
저장소 루트에서 실행하십시오. 기본 전략은 `--strategy link`입니다. 링크를 쓸 수 없으면 `copy`를 선택할 수 있습니다. 관리 기록은 프로젝트의 `.optbrew/install`에 둡니다. 한 호스트만 설치하려면 목록 대신 `codex`, `claude-code`, `cursor`, `opencode`, `pi` 중 한 ID를 적습니다. 사용자 전체 범위에 설치할 때만 `--scope user`를 씁니다. 설치 명령은 번들 manifest를 확인하며 관리 대상이 아닌 기존 폴더를 덮어쓰지 않습니다.
|
|
22
|
+
|
|
23
|
+
checkout은 `https://github.com/nowwcastle-sudo/optbrew`를 clone해서 받고, 위 명령은 그 저장소 최상위에서 실행합니다. `npm install -g optbrew`로 설치하면 같은 CLI를 `optbrew` 명령으로 쓸 수 있습니다. 이때는 위 명령의 `node bin/optbrew.mjs`를 `optbrew`로 바꿉니다. 호스트 고유 설치와 ZIP은 [플랫폼 안내](docs/platforms.md)를 보십시오.
|
|
24
|
+
|
|
25
|
+
## 첫 실행
|
|
26
|
+
|
|
27
|
+
호스트에 optbrew를 사용하라고 요청할 때 대상 URL, 목표, 사이트 소유 또는 접근 권한, 허용할 로컬 변경, 보유한 근거를 전달합니다. 로컬 감사 전에 URL 범위를 선언합니다. 기본 수집 상한은 URL 50개, 깊이 3, 동시성 2입니다. 사설 주소는 명시한 로컬 대상에서만 허용합니다. 작업은 원시 근거, 준비도 관찰, 로컬 변경, 후속 확인을 기록합니다. 로컬 검증 통과를 운영 성과로 해석하지 않습니다.
|
|
28
|
+
|
|
29
|
+
다음 명령은 포함된 합성 fixture를 재생하며 제공자 호출을 하지 않습니다. 저장소 루트에서 새 출력 경로를 골라 실행합니다.
|
|
30
|
+
|
|
31
|
+
Bash와 PowerShell에서 같은 명령을 사용합니다.
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
node bin/optbrew.mjs score --input ./before.json --output ./score.json
|
|
35
|
+
node bin/optbrew.mjs compare --before ./before.json --after ./after.json --output ./comparison.json
|
|
36
|
+
node bin/optbrew.mjs report --input ./remote-only.json --output-dir ./report-output
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
명령을 그대로 실행하려면 `tests/fixtures/scoring/before.json`, `after.json`을 현재 폴더로 복사합니다. `tests/fixtures/reports/remote-only.json`과 같은 폴더의 근거 파일도 함께 복사합니다. 실제 작업에서는 자신의 검증된 `ScoreInput` 또는 `ReportPacket` 경로를 넘깁니다. 계약은 [채점](skills/optbrew/references/scoring.md), [측정](skills/optbrew/references/measurement.md), [보고 근거](skills/optbrew/references/report.md)에 있습니다.
|
|
40
|
+
|
|
41
|
+
## 점수와 보고서
|
|
42
|
+
|
|
43
|
+
자체 준비도 프로필은 SEO, 네이버가 대상일 때 NEO, AEO, GEO, LLMO입니다. 고유 검사군 22개는 여러 가이드가 같은 문제를 찾아도 한 번만 셉니다. 확인하지 못한 적용 검사는 분모에 남기고, 근거 있는 `not_applicable` 검사만 제외합니다. 결과에는 점수, 측정 범위, 미측정 구간의 상·하한, 차단 요소, 미확인 핵심 검사가 들어갑니다. 측정 범위 80% 기준은 optbrew 자체 규칙이며 검색엔진 기준이 아닙니다. 높은 준비도 점수는 색인, 유입, 인용, 사실 정확성, 전환, 매출을 증명하지 않습니다.
|
|
44
|
+
|
|
45
|
+
보고서는 준비도, 해결 방안, 실제 성과, 남은 일을 별도 표로 보여 줍니다. 실제 성과에는 소유자 내보내기 자료 또는 고정된 AI 질문 패널이 필요합니다. 일반 성과 비교에는 정의와 필터가 같은 인접한 완결 28일 기간 두 개를 사용합니다. 로컬 수정은 배포와 운영 관찰의 근거가 생기기 전까지 로컬 수정입니다.
|
|
46
|
+
|
|
47
|
+
## API와 비용
|
|
48
|
+
|
|
49
|
+
API 사용은 선택 사항입니다. Claude 또는 Claude Code 구독에 Anthropic API 과금이 포함되는 것은 아닙니다. 직접 API 키는 [공식 발급 안내](https://platform.claude.com/docs/en/get-api-key)의 Console → Settings → API keys에서 만듭니다. 키는 자신의 셸 또는 비밀 관리 도구에서 `ANTHROPIC_API_KEY`로 설정합니다. 보고서에 실값을 넣지 마십시오. v0.1.0에서 도입한 직접 어댑터는 여러 Anthropic workspace에 걸친 키에 필요할 수 있는 `anthropic-workspace-id` 헤더를 여전히 설정하지 않습니다. 호환 키나 별도로 승인된 호스트 기능을 사용합니다.
|
|
50
|
+
|
|
51
|
+
직접 어댑터는 텍스트 `{model,max_tokens,messages}` 요청과 정확한 모델 ID `claude-fable-5-1`, `claude-opus-5-5`, `claude-sonnet-5-5`, `claude-haiku-5-5`만 받습니다. `max_tokens` 상한은 128,000입니다. 매 시도에는 `1,000,000 + max_tokens` 이상의 토큰 예약 한 개, 맞는 장부 예산, 승인 참조가 필요합니다. 이 예약은 최악 경우의 용량 상한이며 예상 청구액이 아닙니다. 첫 유료 호출 전에 현재 단가의 출처와 날짜, 예상 지출, 승인된 중단 조건을 기록합니다. 추가 필드, 도구, 검색, 비텍스트 입력, 다른 모델, 통화만으로 설정한 상한은 직접 호출 전에 거부됩니다. 자세한 경계는 [API 안내](skills/optbrew/references/api.md)에 있습니다.
|
|
52
|
+
|
|
53
|
+
SE Ranking은 별도의 [API](https://seranking.com/api.html), [MCP 안내](https://seranking.com/api/integrations/mcp), 계정 상품, 크레딧을 사용합니다. [HTTP MCP 주소](https://api.seranking.com/mcp)는 문서에 따른 OAuth 또는 직접 토큰 경로를 씁니다. `ANTHROPIC_API_KEY`와는 별개입니다. 사용 가능한 도구는 구독에 따라 달라집니다. 오프라인 채점에는 어느 연결도 필요하지 않습니다. 유료 기능을 결정할 때 실제 계정의 단가와 크레딧을 확인합니다.
|
|
54
|
+
|
|
55
|
+
## 업데이트와 복원
|
|
56
|
+
|
|
57
|
+
관리 설치를 갱신하려면 먼저 검증된 새 optbrew 번들을 빌드하거나 받습니다. 저장소 루트에서 다음 명령을 실행합니다.
|
|
58
|
+
|
|
59
|
+
Bash와 PowerShell에서 같은 명령을 사용합니다.
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
node bin/optbrew.mjs check-updates --json
|
|
63
|
+
node bin/optbrew.mjs update --scope project --project ./site --json
|
|
64
|
+
node bin/optbrew.mjs rollback --scope project --project ./site --release-version 0.1.0 --json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
확인된 registry 패키지가 없으면 `check-updates`는 `local_only`를 반환합니다. `update`는 현재 CLI 번들을 검증한 뒤 관리 기록의 모든 대상에 적용합니다. 로컬 편집은 자동으로 덮어쓰지 않습니다. `rollback`은 관리 기록에 해당 이전 버전이 남아 있어야 합니다. 새 0.1.1 설치에서는 위 복원 예시가 실패하며, 로컬 0.1.0을 보존한 관리 설치에 적용됩니다. 출시 후 `npm update -g optbrew`는 npm 패키지를 갱신하지만 이전에 agent 스킬 폴더로 복사한 파일까지 바꾸지는 않습니다. CLI를 갱신한 다음 관리 `update`를 다시 실행합니다. 호스트 고유 갱신은 [플랫폼 안내](docs/platforms.md)를 보십시오.
|
|
68
|
+
|
|
69
|
+
## 지원 범위와 라이선스
|
|
70
|
+
|
|
71
|
+
관리 설치·검사·갱신·복원은 문서화된 기본 경로의 Codex, Claude Code, Cursor, OpenCode, Pi를 대상으로 합니다. 호스트의 사용자 지정 경로, 프로젝트 신뢰 설정, 세션 재시작 조건은 탐색 결과를 바꿀 수 있습니다. 일반 ChatGPT 채팅에서는 파일을 첨부해 안내형으로 사용합니다. 이는 Codex나 Work/desktop 플러그인 설치와 다릅니다. Claude 웹에서는 ZIP을 직접 올리고 갱신 때 다시 올립니다. 호스트 탐색과 실제 호출 성공은 따로 확인해야 합니다.
|
|
72
|
+
|
|
73
|
+
네이버 묶음은 [Search Advisor 공식 안내](https://searchadvisor.naver.com/guide)의 색인을 포함합니다. 네이버 원문 55개는 제외했으므로 전문을 오프라인에서 읽을 수 없습니다. 온라인에서 공식 링크를 여십시오. 포함한 원본의 라이선스와 변경 내역은 [제삼자 고지](skills/optbrew/THIRD_PARTY_NOTICES.md)에 있습니다. optbrew 자체 코드는 [MIT 라이선스](LICENSE)입니다. 서비스 접근권과 API 자료 이용권은 코드 라이선스와 별개입니다. 묶음 생성·검증 절차는 [릴리스 안내](docs/release.md)에 있습니다.
|
package/README.md
CHANGED
|
@@ -1,3 +1,73 @@
|
|
|
1
|
-
#
|
|
1
|
+
# optbrew
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[한국어](README.ko.md)
|
|
4
|
+
|
|
5
|
+
Optbrew is a local skill and CLI for checking a site's search readiness, making approved local changes, and comparing evidence before and after. It combines five pinned source bundles—mblode SEO, Naver Search Advisor, Firecrawl SEO Audit, Magnus SEO, and SE Ranking SEO—with seven selected marketing guides. One top-level `SKILL.md` routes to the included guides. The bundle works from its pinned files; it does not fetch a moving upstream revision during a run.
|
|
6
|
+
|
|
7
|
+
The CLI can calculate a score and write a report from stored JSON without an API account. A site audit needs a declared target and scope. Publication, search engine submission, remote site changes, and paid calls require separate authority. Read [platform support](docs/platforms.md) for the difference between installing a file and confirming that a host invoked it.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
Requires Node.js 22 or later. The internal Python audit utilities need Python 3.10 or later; missing Python leaves those utilities unrun. From this checkout, first inspect the targets in an isolated project directory named `site`:
|
|
12
|
+
|
|
13
|
+
Bash and PowerShell use the same commands:
|
|
14
|
+
|
|
15
|
+
```text
|
|
16
|
+
node bin/optbrew.mjs install --agents codex,claude-code,cursor,opencode,pi --scope project --project ./site --strategy copy --dry-run --json
|
|
17
|
+
node bin/optbrew.mjs install --agents codex,claude-code,cursor,opencode,pi --scope project --project ./site --strategy copy --json
|
|
18
|
+
node bin/optbrew.mjs doctor --agents codex,claude-code,cursor,opencode,pi --scope project --project ./site --json
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Create `site` first and run these commands from the repository root. `--strategy link` is the default; `copy` also works when links are unavailable. The managed record lives under that project's `.optbrew/install`. For one host, replace the comma-separated list with its exact ID: `codex`, `claude-code`, `cursor`, `opencode`, or `pi`. Use `--scope user` only when you intend to install into user-level host directories. The install command checks the bundle manifest and refuses to replace an unmanaged target.
|
|
22
|
+
|
|
23
|
+
To get the checkout, clone `https://github.com/nowwcastle-sudo/optbrew` and run the commands above from its root. `npm install -g optbrew` installs the same CLI as an `optbrew` command; replace `node bin/optbrew.mjs` with `optbrew` in the commands above. Native host distribution and the ZIP path are described in [platform support](docs/platforms.md).
|
|
24
|
+
|
|
25
|
+
## First use
|
|
26
|
+
|
|
27
|
+
Ask the host to use optbrew with the target URL, goal, site ownership or access, allowed local changes, and available evidence. For a local audit, declare the URL scope before collection. The default collection ceilings are 50 URLs, depth 3, and concurrency 2; private addresses need an explicit local target. The workflow records raw evidence, readiness observations, local changes, and follow-up checks. It does not infer a site's production result from a passing local test.
|
|
28
|
+
|
|
29
|
+
The examples below replay bundled synthetic fixtures. They make no provider call. Run them from the checkout root and choose fresh output paths:
|
|
30
|
+
|
|
31
|
+
Bash and PowerShell use the same commands:
|
|
32
|
+
|
|
33
|
+
```text
|
|
34
|
+
node bin/optbrew.mjs score --input ./before.json --output ./score.json
|
|
35
|
+
node bin/optbrew.mjs compare --before ./before.json --after ./after.json --output ./comparison.json
|
|
36
|
+
node bin/optbrew.mjs report --input ./remote-only.json --output-dir ./report-output
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
For those literal commands, copy `tests/fixtures/scoring/before.json` and `after.json` into the current directory, and copy `tests/fixtures/reports/remote-only.json` plus its sibling evidence files into the current directory. For real work, pass your own validated `ScoreInput` or `ReportPacket` paths. See [scoring](skills/optbrew/references/scoring.md), [measurement](skills/optbrew/references/measurement.md), and [report evidence](skills/optbrew/references/report.md) for the contracts.
|
|
40
|
+
|
|
41
|
+
## Score and report
|
|
42
|
+
|
|
43
|
+
The five optbrew readiness profiles are SEO, NEO when Naver is a target, AEO, GEO, and LLMO. The 22 unique check families are counted once even when several guides find the same issue. An unknown applicable check remains in the denominator; an evidenced `not_applicable` check is excluded. The result includes score, measured coverage, missing-data bounds, blockers, and unresolved core checks. The 80% coverage threshold is an optbrew rule, not a search engine standard. A high readiness score does not prove indexing, traffic, citations, accuracy, conversions, or revenue.
|
|
44
|
+
|
|
45
|
+
The report keeps readiness, remedies, actual outcomes, and remaining work in separate tables. Actual outcomes need owner exports or a fixed AI question panel. A normal outcome comparison uses two complete, adjacent 28-day windows with matching definitions and filters. A local edit remains local until deployment and a production observation have their own evidence.
|
|
46
|
+
|
|
47
|
+
## APIs and cost
|
|
48
|
+
|
|
49
|
+
API access is optional. A Claude or Claude Code subscription does not supply Anthropic API billing. To use a direct API key, follow the [official key guide](https://platform.claude.com/docs/en/get-api-key): Console → Settings → API keys. Put the key in the `ANTHROPIC_API_KEY` environment variable in your own shell or secret manager; never put a real value in a report. A key spanning multiple Anthropic workspaces may require an `anthropic-workspace-id` header. The direct adapter introduced in v0.1.0 still does not set that header, so use a compatible key or a separately approved host capability.
|
|
50
|
+
|
|
51
|
+
The direct adapter accepts only text `{model,max_tokens,messages}` requests for the exact model IDs `claude-fable-5-1`, `claude-opus-5-5`, `claude-sonnet-5-5`, and `claude-haiku-5-5`. `max_tokens` cannot exceed 128,000. Each attempt needs one token reservation of at least `1,000,000 + max_tokens`, a matching ledger budget, and an approval reference. This is a worst-case capacity bound, not a bill estimate. Record the current price source, estimated spend, and approved stop condition before the first paid call. Extra fields, tools, search, non-text input, unknown models, or currency-only bounds make zero direct calls. See [API boundaries](skills/optbrew/references/api.md).
|
|
52
|
+
|
|
53
|
+
SE Ranking has its own [API](https://seranking.com/api.html), [MCP instructions](https://seranking.com/api/integrations/mcp), account plan, and credits. Its [HTTP MCP endpoint](https://api.seranking.com/mcp) uses its documented OAuth or direct-token path, independently of `ANTHROPIC_API_KEY`. Available tools depend on the subscription. Neither connection is required for offline scoring. Use actual account prices and credits when deciding whether to run a paid capability; no price is built into this README.
|
|
54
|
+
|
|
55
|
+
## Update and rollback
|
|
56
|
+
|
|
57
|
+
For a managed project installation, rebuild or obtain a verified newer optbrew bundle before updating. From the checkout root:
|
|
58
|
+
|
|
59
|
+
Bash and PowerShell use the same commands:
|
|
60
|
+
|
|
61
|
+
```text
|
|
62
|
+
node bin/optbrew.mjs check-updates --json
|
|
63
|
+
node bin/optbrew.mjs update --scope project --project ./site --json
|
|
64
|
+
node bin/optbrew.mjs rollback --scope project --project ./site --release-version 0.1.0 --json
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Without a confirmed registry package, `check-updates` reports `local_only`. `update` uses the current CLI bundle, verifies it, and updates all targets in that install record; it does not silently replace local edits. `rollback` needs that version in the record's retained prior releases. The shown rollback will therefore fail on a fresh 0.1.1 install and applies to a managed installation that retains local 0.1.0. `npm update -g optbrew` updates npm's package files after release; it does not rewrite a copy already placed in an agent skills directory. Run the managed `update` command again after updating the CLI. Native plugin and Pi package update paths are in [platform support](docs/platforms.md).
|
|
68
|
+
|
|
69
|
+
## Support and license
|
|
70
|
+
|
|
71
|
+
Managed install, doctor, update, and rollback cover Codex, Claude Code, Cursor, OpenCode, and Pi at the documented default paths. Custom host directories, project trust, and session reload rules can change discovery. Ordinary ChatGPT chat uses attached files and instructions; it is not the same installation path as Codex or a Work/desktop plugin. Claude web requires manual ZIP upload and re-upload for updates. Host discovery and a successful real invocation require separate checks.
|
|
72
|
+
|
|
73
|
+
The Naver bundle retains an index of official [Search Advisor guides](https://searchadvisor.naver.com/guide). It excludes the 55 original Naver article bodies, so full offline article lookup is unavailable. Follow the official links while online. Included source licenses and changes are listed in [third-party notices](skills/optbrew/THIRD_PARTY_NOTICES.md); optbrew's own code is [MIT licensed](LICENSE). Service access and API data rights are separate from those code licenses. Release packaging and verification are in [release instructions](docs/release.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
The files below retain their upstream copyright and permission notices. Service accounts, API data and Naver guide article bodies are outside these code licenses.
|
|
4
|
+
|
|
5
|
+
- **mblode-seo** — mblode/agent-skills at 872bc83bdb6dd54a9ff456fbf1181beea6db7875; MIT; Git license blob c5a1d56c6d623c72d077f8aab56b31d7dc371cbb; exact notice: [licenses/mblode-seo.txt](skills/optbrew/licenses/mblode-seo.txt). Exclusions: Unselected agent skills in the upstream repository.
|
|
6
|
+
- **naver-searchadvisor** — JaceProgramming/naver-searchadvisor-expert at cd95f6281090416b3dfbf15fb0f66f0ffa67a19c; MIT (limited scope); Git license blob 4434edf30edce0a41c07fbc776b0d5cebd044547; exact notice: [licenses/naver-searchadvisor.txt](skills/optbrew/licenses/naver-searchadvisor.txt). Exclusions: references/guide/*.md: 55 Naver copyrighted article bodies outside MIT scope; official URLs retained in INDEX; README.md: documents upstream offline corpus and is not a runtime guide; tools/fetch-guide.mjs: would retrieve excluded articles; tools/fix-index.mjs and tools/package.json: authoring tools, not runtime.
|
|
7
|
+
- **firecrawl-seo-audit** — firecrawl/firecrawl-workflows at 94cc91229d6cedc0613f140d3d013b150bc8e1b0; ISC; Git license blob ee221a2151d63ddc1db9857f9c5d346a3de9d816; exact notice: [licenses/firecrawl-seo-audit.txt](skills/optbrew/licenses/firecrawl-seo-audit.txt). Exclusions: Unselected Firecrawl workflows.
|
|
8
|
+
- **magnus-seo** — magnus919/agent-skills at 2e8fb962819b2b01b270620f92f0cc7213d77ef1; MIT; Git license blob 9745e19f4b20d77c134964ae1bf0af0ace5c4db7; exact notice: [licenses/magnus-seo.txt](skills/optbrew/licenses/magnus-seo.txt). Exclusions: Unselected agent skills.
|
|
9
|
+
- **seranking-seo** — seranking/seo-skills at fd6d1408f2e6a06454d81c07c29e0f04342eb9ba; MIT; Git license blob ca6b9a33c8234bf47cdcfb2dc157b308195845c5; exact notice: [licenses/seranking-seo.txt](skills/optbrew/licenses/seranking-seo.txt). Exclusions: extensions/google/install.sh and extensions/firecrawl/install.sh: upstream installers disabled; scripts/google_auth.py and root scripts: upstream authentication and provider execution disabled; optbrew capability adapters replace active commands; Unselected campaign, ad, social and other upstream skills.
|
|
10
|
+
- **marketing-search** — coreyhaines31/marketingskills at 5b2c0007766c6a1cf1d53fd8fc73e979e0821022; MIT; Git license blob 7c48dd638a9ebed49a8ef0c0c4eea90105381cdf; exact notice: [licenses/marketing-search.txt](skills/optbrew/licenses/marketing-search.txt). Exclusions: Unselected marketing skills, installers and authoring utilities.
|
package/bin/optbrew.mjs
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Platform installation and update paths
|
|
2
|
+
|
|
3
|
+
Optbrew v0.1.1 contains one skill source at `skills/optbrew`. The managed CLI can place it at five hosts' documented default paths. A file in a host path proves placement, not that the host discovered, loaded, or invoked the skill. Confirm those three steps in a fresh host session before reporting host support as exercised.
|
|
4
|
+
|
|
5
|
+
| Host | Managed project target | Managed user target | Discovery and invocation boundary |
|
|
6
|
+
|---|---|---|---|
|
|
7
|
+
| Codex | `.agents/skills/optbrew` | `~/.agents/skills/optbrew` | [Codex skills](https://learn.chatgpt.com/docs/build-skills) scans repository and user skills and follows links. Test invocation in a fresh task. |
|
|
8
|
+
| Claude Code | `.claude/skills/optbrew` | `~/.claude/skills/optbrew` | [Claude Code skills](https://code.claude.com/docs/en/skills) scans those roots. This is separate from the Claude web upload. |
|
|
9
|
+
| Cursor | `.cursor/skills/optbrew` | `~/.cursor/skills/optbrew` | [Cursor skills](https://cursor.com/docs/skills) also accepts `.agents/skills`; local user skills are not automatically copied to cloud agents. |
|
|
10
|
+
| OpenCode | `.opencode/skills/optbrew` | `~/.config/opencode/skills/optbrew` | [OpenCode skills](https://opencode.ai/docs/skills/) also discovers compatible `.agents` and `.claude` roots. |
|
|
11
|
+
| Pi | `.pi/skills/optbrew` | `<agent-dir>/skills/optbrew`, normally `~/.pi/agent/skills/optbrew` | [Pi configuration](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/configuration.md) permits `PI_CODING_AGENT_DIR` overrides and requires project trust for project configuration. |
|
|
12
|
+
|
|
13
|
+
The CLI maps only these default targets. Custom roots, host policies, remote agents, and session reload behavior need host-specific checks. `--scope project --project ./site` keeps a managed installation inside an isolated project. `--scope user` addresses the user's default host paths and should be chosen deliberately.
|
|
14
|
+
|
|
15
|
+
## Managed checkout and npm paths
|
|
16
|
+
|
|
17
|
+
The [README](../README.md) shows parser-checked checkout commands for install, doctor, update, and rollback. The CLI validates bundle hashes before an install or update. `update` replaces every target in one managed record as a unit. An edited target makes the default update stop; the explicit `--local-changes backup-and-replace` policy retains a readable backup. `rollback --release-version VERSION` works only when that version is in the record's retained prior releases. A fresh installation has no older release.
|
|
18
|
+
|
|
19
|
+
After a public npm release, `npm install -g optbrew` and `npm update -g optbrew` manage the package in npm. Neither command rewrites an old copied skill target. Run the installed CLI's managed `update` after the package update, then `doctor` and a new-session invocation check. `check-updates --json` is read-only; without a confirmed registry name it returns `local_only`. The package is not public merely because `package.json` names it.
|
|
20
|
+
|
|
21
|
+
## Native host routes
|
|
22
|
+
|
|
23
|
+
These are alternatives to the managed CLI. Do not mix their ownership records for the same target path.
|
|
24
|
+
|
|
25
|
+
- **Agent Skills tool:** Current [Vercel Skills CLI](https://github.com/vercel-labs/skills) documents `npx skills add ./` for a local source and `npx skills update optbrew` for an installation it owns. Run from a checkout containing the skill. Confirm its host selection and destination before writing. The public repository is `https://github.com/nowwcastle-sudo/optbrew`.
|
|
26
|
+
- **Claude Code plugin:** The local `.claude-plugin/marketplace.json` and `plugin.json` name `optbrew@optbrew-local` at version 0.1.1. The installed Claude CLI help accepts `claude plugin marketplace add --scope project .`, then `claude plugin install --scope project optbrew@optbrew-local` from this checkout. Later, `claude plugin update --scope project optbrew@optbrew-local` applies the marketplace's newer version and requires a restart. These commands change Claude settings, so documentation checks inspect `--help` without registering a marketplace. [Claude Code plugin instructions](https://code.claude.com/docs/en/plugins) also describe the interactive `/plugin` path. Marketplace auto-update is a user setting; the marketplace file does not enable it. Verify the selected release version and a fresh-session invocation after a native update.
|
|
27
|
+
- **Pi package:** Current [Pi package instructions](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/packages.md) document `pi install ./local-package`, `pi install npm:package-name@version`, `pi list`, and `pi update --extensions`. `pi install ./` installs from a local checkout when Pi is installed; `pi install npm:optbrew@0.1.1` installs the published npm package. The package's `pi.skills` entry points to `./skills/optbrew`. A project-local package declaration uses Pi's `--local` option and is subject to project trust. Check the installed Pi version's help and package list before updating.
|
|
28
|
+
- **Claude web:** Upload the built skill ZIP manually in the supported web interface. Upload a new ZIP again for each update. There is no verified automatic update of that upload.
|
|
29
|
+
- **Ordinary ChatGPT chat:** Attach the relevant skill files or ZIP and give the assistant the target and scope. This is attachment-guided use. It is not the Codex installation path and does not establish Work/desktop plugin discovery.
|
|
30
|
+
|
|
31
|
+
The native syntax above comes from host documentation checked on 2026-10-14. It is documentation evidence, not proof that an installed host accepted the package or called the skill. No host registration, OAuth, account setting, or user-level install is performed by the documentation checks.
|
package/docs/release.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Release procedure
|
|
2
|
+
|
|
3
|
+
This checkout is version 0.1.1. A package name, local manifest, or generated ZIP does not establish a public release. Publication, a Git tag, a push, and account changes require their own authorization. This page describes the reviewable local release artifacts and the checks to run before that decision.
|
|
4
|
+
|
|
5
|
+
1. Confirm the source commit and clean intended diff. Match `package.json`, the portable plugin, Codex plugin, Claude plugin, marketplace entry, and ZIP name to one release version. Keep `evaluation_version` and `protocol_version` separate from the release version.
|
|
6
|
+
2. Run `npm test` and `python -m unittest discover -s tests/python` on Python 3.10 or later. Run the focused `node --test tests/docs-commands.test.mjs` check when changing examples. The command check runs optbrew against isolated local fixtures; it makes no provider call.
|
|
7
|
+
3. Run `npm run build-bundle`, `node scripts/build-release.mjs --version 0.1.1 --output-dir dist`, `npm pack --pack-destination dist`, `node scripts/verify-release.mjs --dist dist`, and `npm pack --dry-run --json` from the repository root. Rebuild after changing the README or packaged files. Do not treat an older tarball as containing a later documentation edit.
|
|
8
|
+
4. Inspect the npm file list, the ZIP file list, `bundle-manifest.json`, `source-lock.json`, licenses, and secret scan output. The same skill bytes and version must be traceable across the npm package and ZIP. Source notices belong in both. User run evidence, account configuration, keys, private cards, and authoring materials must stay outside both.
|
|
9
|
+
5. Test a fresh isolated managed install, `doctor`, update from a retained earlier release, rollback, and fresh host discovery or invocation where a host is available. A dry run or manifest check does not prove invocation. Record the untested hosts and capabilities.
|
|
10
|
+
6. Only after a reviewed release decision, publish or upload the approved artifacts and verify the public npm and repository readback. Do not infer publication from successful local builds.
|
|
11
|
+
|
|
12
|
+
The bundle includes five pinned source bundles plus seven selected marketing guides. The Naver source articles under `references/guide/` (55 original bodies) remain excluded; the index links to official pages and full offline article lookup is unavailable. The published notice must retain upstream MIT/ISC permission texts and modifications. Optbrew's own code uses MIT. These code licenses do not grant service subscriptions or API data rights.
|
|
13
|
+
|
|
14
|
+
The direct Anthropic adapter retains its v0.1.0 text-only scope and four model IDs in [API boundaries](../skills/optbrew/references/api.md). No live paid result, search indexing, traffic change, or customer adoption is established by a passing package check. See [platform paths](platforms.md) for update mechanisms after release.
|
package/lib/cli.mjs
ADDED
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { install } from './install.mjs';
|
|
5
|
+
import { doctor } from './doctor.mjs';
|
|
6
|
+
import { supportedAgents, scopePaths } from './paths.mjs';
|
|
7
|
+
import { checkUpdates, update, rollback } from './update.mjs';
|
|
8
|
+
import { readFile } from 'node:fs/promises';
|
|
9
|
+
import { readInstallRecord } from './records.mjs';
|
|
10
|
+
import { runCli } from '../skills/optbrew/scripts/cli.mjs';
|
|
11
|
+
|
|
12
|
+
const defaultBundle = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../skills/optbrew');
|
|
13
|
+
class UsageError extends Error {}
|
|
14
|
+
const usage = 'usage: optbrew <install|doctor|check-updates|update|rollback|score|compare|report> [options]';
|
|
15
|
+
|
|
16
|
+
function parseOptions(argv, allowed) {
|
|
17
|
+
const options = {};
|
|
18
|
+
for (let i = 0; i < argv.length; i++) {
|
|
19
|
+
const key = argv[i];
|
|
20
|
+
if (!allowed.includes(key) || key in options) throw new UsageError(`unknown or repeated option: ${key}`);
|
|
21
|
+
if (key === '--json' || key === '--dry-run') options[key] = true;
|
|
22
|
+
else {
|
|
23
|
+
if (!argv[i + 1] || argv[i + 1].startsWith('--')) throw new UsageError(`missing value for ${key}`);
|
|
24
|
+
options[key] = argv[++i];
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return options;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function installOptions(argv, command, { cwd, env }) {
|
|
31
|
+
const allowed = ['--agents', '--scope', '--project', '--home', '--json'];
|
|
32
|
+
if (command === 'install') allowed.push('--dry-run', '--strategy');
|
|
33
|
+
const parsed = parseOptions(argv, allowed);
|
|
34
|
+
if (!parsed['--agents']) throw new UsageError('--agents is required');
|
|
35
|
+
const agents = parsed['--agents'].split(',');
|
|
36
|
+
if (agents.some(agent => !supportedAgents.includes(agent)) || new Set(agents).size !== agents.length) throw new UsageError('invalid or duplicate agent');
|
|
37
|
+
const scope = parsed['--scope'] ?? 'user';
|
|
38
|
+
if (!['user', 'project'].includes(scope)) throw new UsageError('--scope must be user or project');
|
|
39
|
+
if (scope === 'project' && !parsed['--project']) throw new UsageError('project scope requires --project');
|
|
40
|
+
if (scope === 'user' && parsed['--project']) throw new UsageError('--project requires project scope');
|
|
41
|
+
const strategy = parsed['--strategy'] ?? 'link';
|
|
42
|
+
if (!['link', 'copy'].includes(strategy)) throw new UsageError('--strategy must be link or copy');
|
|
43
|
+
return { agents, scope, home: parsed['--home'] ? path.resolve(cwd, parsed['--home']) : env?.HOME ?? os.homedir(),
|
|
44
|
+
projectRoot: parsed['--project'] ? path.resolve(cwd, parsed['--project']) : undefined,
|
|
45
|
+
dryRun: Boolean(parsed['--dry-run']), strategy, json: Boolean(parsed['--json']) };
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function computeArgs(argv, command, cwd) {
|
|
49
|
+
const keys = command === 'score' ? ['--input', '--output'] : command === 'compare' ? ['--before', '--after', '--output'] : ['--input', '--output-dir'];
|
|
50
|
+
const opts = parseOptions(argv, keys);
|
|
51
|
+
if (keys.some(k => !opts[k])) throw new UsageError(`missing ${keys.filter(k => !opts[k]).join(', ')}`);
|
|
52
|
+
return [command, ...keys.flatMap(k => [k, path.resolve(cwd, opts[k])])];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/** Return CLI process code: 0 success, 2 argument error, 1 environment or file failure. */
|
|
56
|
+
export async function main(argv, { stdout = process.stdout, stderr = process.stderr, env = process.env, cwd = process.cwd(), bundleRoot = defaultBundle, registryTransport } = {}) {
|
|
57
|
+
try {
|
|
58
|
+
const [command, ...rest] = argv;
|
|
59
|
+
if (['score', 'compare', 'report'].includes(command)) {
|
|
60
|
+
await runCli(computeArgs(rest, command, cwd));
|
|
61
|
+
stdout.write(`${command} complete\n`);
|
|
62
|
+
return 0;
|
|
63
|
+
}
|
|
64
|
+
if (!['install', 'doctor', 'check-updates', 'update', 'rollback'].includes(command)) throw new UsageError(usage);
|
|
65
|
+
if (command === 'check-updates') {
|
|
66
|
+
const parsed = parseOptions(rest, ['--package', '--json']);
|
|
67
|
+
const manifest = JSON.parse(await readFile(path.join(bundleRoot, 'bundle-manifest.json'), 'utf8'));
|
|
68
|
+
const result = await checkUpdates({ packageName: parsed['--package'], currentVersion: manifest.release_version, registryTransport });
|
|
69
|
+
stdout.write(`${JSON.stringify(result, null, parsed['--json'] ? 2 : 0)}\n`);
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
if (command === 'update' || command === 'rollback') {
|
|
73
|
+
const allowed = ['--record-root', '--scope', '--home', '--project', '--agents', '--json'];
|
|
74
|
+
allowed.push(command === 'update' ? '--local-changes' : '--release-version');
|
|
75
|
+
const parsed = parseOptions(rest, allowed);
|
|
76
|
+
if (parsed['--record-root'] && ['--scope', '--home', '--project'].some(k => parsed[k])) throw new UsageError('--record-root cannot be combined with scope options');
|
|
77
|
+
const scope = parsed['--scope'] ?? 'user';
|
|
78
|
+
if (scope === 'user' && parsed['--project']) throw new UsageError('--project requires project scope');
|
|
79
|
+
const recordRoot = parsed['--record-root'] ? path.resolve(cwd, parsed['--record-root']) : scopePaths({ scope,
|
|
80
|
+
home: parsed['--home'] ? path.resolve(cwd, parsed['--home']) : env?.HOME ?? os.homedir(),
|
|
81
|
+
projectRoot: parsed['--project'] ? path.resolve(cwd, parsed['--project']) : undefined }).managedRoot;
|
|
82
|
+
if (parsed['--agents']) {
|
|
83
|
+
const selected = parsed['--agents'].split(',');
|
|
84
|
+
if (selected.some(agent => !supportedAgents.includes(agent)) || new Set(selected).size !== selected.length) throw new UsageError('invalid or duplicate agent');
|
|
85
|
+
const record = await readInstallRecord(recordRoot);
|
|
86
|
+
if (!record) throw new Error('install record missing');
|
|
87
|
+
if (JSON.stringify(selected.sort()) !== JSON.stringify(record.targets.map(t => t.agent).sort())) throw new UsageError('update/rollback requires all recorded targets; partial updates are unavailable');
|
|
88
|
+
}
|
|
89
|
+
if (command === 'rollback' && !parsed['--release-version']) throw new UsageError('--release-version is required');
|
|
90
|
+
const result = command === 'update' ? await update({ bundleRoot, recordRoot, localChanges: parsed['--local-changes'] ?? 'abort' }) :
|
|
91
|
+
await rollback({ recordRoot, releaseVersion: parsed['--release-version'] });
|
|
92
|
+
stdout.write(`${JSON.stringify(result, null, parsed['--json'] ? 2 : 0)}\n`);
|
|
93
|
+
return ['updated', 'rolled_back', 'unchanged'].includes(result.status) ? 0 : 1;
|
|
94
|
+
}
|
|
95
|
+
const options = installOptions(rest, command, { cwd, env });
|
|
96
|
+
const result = command === 'install' ? await install({ ...options, bundleRoot }) : await doctor(options);
|
|
97
|
+
stdout.write(options.json ? `${JSON.stringify(result, null, 2)}\n` : `${JSON.stringify(result)}\n`);
|
|
98
|
+
return 0;
|
|
99
|
+
} catch (error) {
|
|
100
|
+
stderr.write(`${error.message}\n`);
|
|
101
|
+
return error instanceof UsageError || error instanceof TypeError ? 2 : 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
package/lib/doctor.mjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { lstat, readFile, realpath } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { verifyBundle } from '../skills/optbrew/scripts/core/bundle.mjs';
|
|
4
|
+
import { readInstallRecord } from './records.mjs';
|
|
5
|
+
import { resolveTargets, scopePaths } from './paths.mjs';
|
|
6
|
+
import { validateScope } from './transaction.mjs';
|
|
7
|
+
|
|
8
|
+
async function exists(name) {
|
|
9
|
+
try { await lstat(name); return true; } catch (error) { if (error.code === 'ENOENT') return false; throw error; }
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function doctor({ agents, scope, home, projectRoot }) {
|
|
13
|
+
const { scopeRoot, managedRoot } = scopePaths({ scope, home, projectRoot });
|
|
14
|
+
const selected = resolveTargets({ agents, scope, home, projectRoot });
|
|
15
|
+
const warnings = [];
|
|
16
|
+
let record;
|
|
17
|
+
try { record = await readInstallRecord(managedRoot); if (record) await validateScope(managedRoot, record); }
|
|
18
|
+
catch (error) { warnings.push(`install record unreadable: ${error.message}`); record = null; }
|
|
19
|
+
const recoveryPending = await exists(path.join(managedRoot, 'transaction.json'));
|
|
20
|
+
if (recoveryPending) warnings.push('recovery_required: interrupted transaction; rerun update/rollback to recover before use');
|
|
21
|
+
if (record?.transaction?.state === 'pending') warnings.push('initial install pending: finish optbrew install before updating');
|
|
22
|
+
const results = [];
|
|
23
|
+
for (const target of selected) {
|
|
24
|
+
const saved = record?.targets.find(t => t.agent === target.agent && t.path === target.path);
|
|
25
|
+
const filePresent = await exists(path.join(target.path, 'SKILL.md'));
|
|
26
|
+
let hashOk = false;
|
|
27
|
+
if (filePresent && saved && record) {
|
|
28
|
+
try {
|
|
29
|
+
if (saved.strategy === 'link' && await realpath(target.path) !== await realpath(path.join(managedRoot, 'bundle'))) throw new Error('link target changed');
|
|
30
|
+
if (saved.strategy === 'copy' && (await lstat(target.path)).isSymbolicLink()) throw new Error('copy replaced by link');
|
|
31
|
+
const manifest = JSON.parse(await readFile(path.join(target.path, 'bundle-manifest.json'), 'utf8'));
|
|
32
|
+
const check = await verifyBundle({ bundleRoot: target.path, manifest });
|
|
33
|
+
hashOk = !recoveryPending && record.transaction.state === 'committed' && check.status === 'valid' && check.bundle_hash === record.bundle_hash && manifest.release_version === record.release_version;
|
|
34
|
+
} catch (error) { warnings.push(`${target.agent}: ${error.message}`); }
|
|
35
|
+
}
|
|
36
|
+
results.push({ agent: target.agent, path: target.path, file_present: filePresent, hash_ok: hashOk,
|
|
37
|
+
registered: Boolean(saved), session_discovery: 'not_verified', invocation_verified: 'not_verified' });
|
|
38
|
+
}
|
|
39
|
+
if (agents.includes('codex') || agents.includes('cursor') || agents.includes('opencode') || agents.includes('pi')) {
|
|
40
|
+
warnings.push('Shared .agents skill paths may also be discovered by other hosts; only selected targets are registered here.');
|
|
41
|
+
}
|
|
42
|
+
if (agents.includes('pi')) warnings.push('Pi custom PI_CODING_AGENT_DIR and project trust settings are not inspected.');
|
|
43
|
+
return { scope_id: `${scope}:${scopeRoot}`, release_version: record?.release_version ?? null, targets: results, warnings };
|
|
44
|
+
}
|