Community程式設計與開發github.com

oliverswitzer/lens

建立並維護一份產品透鏡 — 一個以 Git 追蹤的 JSON 圖表,涵蓋產品目的、核心循環、角色人物、受訪者、證據、主張(聽聞/所見、擁有者觀點、未驗證)、具計算信心的重點假設、已上線功能與點子、替代方案與競爭者、市場洞察、內容支柱與決策 — 整合成一份自含式、可註解的 index.html 並附差異檢視。

lens 是什麼?

Lens 技能提供一個結構化、以檔案為基礎的框架,用於捕捉與管理產品知識,其核心是 git 追蹤的 JSON 圖 (model.json),並可建構成一份自含式、可註解的 HTML 檔案 (index.html),讓任何人都能開啟並提供意見。它支援 Claude Code、Cursor 等 AI 代理平台,幫助開發者與產品經理系統化記錄產品目的、核心循環、角色人物、使用者研究證據、主張(區分為觀察、觀點、假設)、已上線功能與點子、競爭對手分析、市場洞察及內容策略。此技能強制資料完整性,若違反規則則建置失敗,確保存放的資料品質。透過 diff 視覺化功能,使用者可以輕鬆檢視模型隨時間的變更,支援新增訪談、更新功能、新增點子、新增競爭對手等常見操作,最終產出結構化的產品知識庫,提升團隊協作效率。

相容平台✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/oliverswitzer/product-lens/tree/main/skills/lens

Installed? Explore more 程式設計與開發 skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

lens 是做什麼的?

透鏡 (Lens) 是一個 JSON 圖表 <lens>/model.json,可建構成一份自含式的 <lens>/index.html,任何人都能開啟並在該頁面上留言。<lens> 是它被建立時所在的資料夾(預設為 docs/lens)。<lens>/README.md 文件記錄了節點類型、關聯、主張形狀與完整性規則。建置流程會拒絕任何違反規則的模型,因此綠色的建置結果是首要檢查項目。

此技能本身的資料夾中包含 template/(會被複製到專案中的內容)、scripts/(競爭者輔助工具)以及 competitors.md。你可以在專案的 .claude/skills/lens/ 找到它,或是在全域安裝時位於 ~/.claude/skills/lens/;下方以 $SKILL 表示該資料夾。

需求:Node 20+ 與 git。不需要 package.json,無任何相依套件。

建立新的透鏡

  1. 選擇資料夾。 詢問使用者透鏡應存放的位置;預設為 docs/lens。拒絕覆蓋已存在的 model.json。

  2. 複製範本(除了已建置好的 index.html 以外的所有內容):

    mkdir -p docs/lens && cp -R "$SKILL/template/." docs/lens/ && rm -f docs/lens/index.html
    echo '[]' > docs/lens/ids.lock.json      # 起始的 ID 並非你的 ID;從空的鎖定檔開始
    
  3. 訪談使用者,然後取代起始模型。 model.json 內含一個虛構的「Acme Notes」範例,展示每一種常見的節點類型。保留其結構,但取代其內容。一次詢問一個主題,並提供具體的草稿供使用者修正,而不是提出空泛的問題:

    • 產品名稱 (title) 與擁有者姓名(owner 人物節點,id 為 p-owner,除非使用者偏好其他名稱;其 title 會在每個觀點主張上顯示為「<姓名> 的觀點」);
    • 一句話描述產品目的 (purpose,一個引用擁有者來源的 view 主張);
    • 核心循環,2–5 個有序的 loop-step;
    • 產品為誰而做(avatars,包含人物誌地圖),以及他們的痛點(problems);
    • 他們已有的訪談或其他證據(source + person 節點;切勿憑空捏造引述或時間戳——如果沒有逐字稿,則記錄為擁有者的報告);
    • 已經上線的內容(surface, shipped: true,附上真實截圖)以及僅是點子的內容(shipped: false);
    • 人們使用的替代方案(alternatives);
    • 最多三個目前要驗證的賭注(hypothesis 節點,focus: 1|2|3)。 使用者所說的一切,若無證據支持,皆視為 view(其觀點)或 hypothesis;除非有來源和 at 時間戳,否則不得標記為 observed。使用占位符名稱(例如「受訪者 A」),除非使用者希望在可能公開的檔案中使用真實姓名。
  4. 清理範例。 一旦沒有任何節點參考 assets/example.png,就將其刪除,並將螢幕截圖指向 assets/surfaces/<surface-id>/<slug>.png。Surface 的 code 和 adrs 路徑相對於專案根目錄,且必須存在(將 adrs 指向專案存放決策記錄的位置,例如 docs/adr/)。

  5. 建置與測試:

    node docs/lens/build.mjs && node --test docs/lens/tests/*.test.mjs
    
  6. 查看結果。 留言是根據瀏覽器的來源 (origin) 儲存的,因此請啟動伺服器來提供服務,而不是直接開啟檔案:

    python3 -m http.server 8767 --bind 127.0.0.1    # 從專案根目錄執行
    open "http://127.0.0.1:8767/docs/lens/index.html"
    
  7. 如果使用者會追蹤競爭對手的廣告,建議在 .gitignore 中加入 docs/lens/assets/ads/**/*.mp4。提交 model.json、ids.lock.json、index.html、assets/ 以及資料夾中的其他內容,並遵循專案本身的提交規則。

奠基工作

在詢問擁有者任何問題之前,請先閱讀相關的節點、其主張及其來源。提供一份具體的綜合摘要供其修正。對於一個 Surface,如果其行為至關重要,請檢查其命名的程式碼 (code) 和決策記錄 (adrs);決策記錄說明的是當時的決定,而非程式碼目前的狀態。

新增證據

每一項陳述都是一個主張,包含 kind、evidence 以及選擇性的 next:

  • observed(聽聞/所見):某人說過的話或做過的事。使用 at(逐字稿的時間戳,或文件的章節)來引用來源。貼近原文引用或改寫;切勿升級含糊的用語(例如「可能有用」)。
  • view(擁有者觀點):擁有者的解讀。它必須引用一個來源,且該來源的 people 必須包含模型的 owner。
  • hypothesis(未驗證):任何未經測試的事物,包括代理程式的建議和實作點子。
  • 假設也是一種節點類型:記錄每一項證據時,需包含 stance(supports 或 contradicts)和 at。切勿設定信心度;focus 假設上的信心度計量器是根據該證據在下一次建置時計算得出的(有不同受訪者支持則提升;有人反駁則降低一級;擁有者的觀點永遠不會提高信心度)。應像記錄支持證據一樣樂於記錄反駁證據。
  • 每個薄弱的證據都應給予一個 next:一個足夠具體、可在通話中提出的問題。它會出現在「下一個對話」區塊中。
  • 釐清誰說了什麼:一個由擁有者提出且其他人同意的主張,並非他們的需求。
  • 一次新的訪談是一個 source,包含 date、people、locator 和簡短的 takeaways,並由其所支持的主張引用。省略與產品無關的個人詳細資訊。僅在儲存庫為私人且受訪者同意的情況下,才將逐字稿歸檔至 <lens>/sources/。

更新 Surface(在變更之後)

當變更改變了 Surface 的外觀或功能時,請在同一個分支中進行以下操作:

  1. 從正在運行的產品中,將變更後的狀態截圖捕捉至 <lens>/assets/surfaces/<surface-id>/<slug>.png(取代舊的截圖,保留 1–4 張)。
  2. 更新 Surface 的 screenshots 項目:caption、capturedAt(今天)、origin: "app"、version。頁面會標記任何比 Surface 的 code 最後一次提交時間更早的截圖。
  3. 如果行為改變,更新 unique / situations;如果檔案移動,更新 code / adrs。

一個全新上線的 Surface 是一個新的 surface 節點,帶有 shipped: true、至少一張截圖、指向其所解決問題的 serves 邊,以及指向其所實作的循環步驟的 implements 邊。

新增點子(來自腦力激盪)

一個曾經討論過但尚未建置的 Surface 是一個 surface,帶有 shipped: false;它會顯示在「點子」區域,視覺上有所區別。為它指定 unique(作為 hypothesis 主張)、situations、heard(人們所說的內容,附帶證據),以及作為 screenshots 的 mockups,並帶有 origin: "design"。當它上線時,將 shipped 設為 true,並用真實截圖取代 mockups。

新增內容支柱或點子

一個行銷主題是一個 pillar;一個具體的文章、影片或活動是位於其下的 content-idea,並帶有 format。將支柱或點子連結到其所針對的角色 (speaks-to),點子連結到其所展示的 Surface (features),以及已經在執行類似策略的競爭對手 (like)。在內容觸及人群之前,點子和支柱皆視為未驗證;記錄發生的情況,作為關於該點子的假設 (hypothesis) 上的證據。

新增市場洞察

來自外部研究的趨勢是一個位於「市場洞察」標籤頁的 insight。將文章記錄為「市場研究」來源(選擇性地在 sources/ 下保存快照),將其事實陳述為觀察到的 findings,並將其對角色的意義保留為觀點或假設,同時包含關於該來源限制的發現。將其連結 (bears-on) 到它所影響的所有事物。

新增或更新競爭對手

遵循 $SKILL/competitors.md 的步驟進行研究(使用真實瀏覽器檢查廣告,絕不繞過付費牆)、使用 scripts/add-product.py 新增產品、分階段捕捉廣告、使用 scripts/apply-staged-ads.py 套用(先檢查所有項目,然後一次性套用)、使用 scripts/smoke-ads.mjs 進行冒煙測試,然後提交(不包含 .mp4 檔案)。根據透鏡中的產品目的和重點假設進行比較,而非其行銷頁面,並將該比較標記為未驗證。

可用性發現不屬於透鏡內容

互動問題(一個沒人找到的按鈕、遺失的焦點狀態)應歸屬於團隊的議題追蹤系統。請在該處記錄它們,並僅在透鏡中記錄其產品意義(如果有的話)。

重新命名或移除

ids.lock.json 記錄了上次建置中每個可留言的 ID。消失的 ID 必須在 model.json 的 renamed 項目中進行映射("old-id": "new-id",或者如果是有意移除則設為 null),否則建置會失敗。這是保持現有留言附加到正確項目的關鍵。

變更透鏡本身

任何在 components/ 下的變更(例如視圖顯示的內容、路由、驗證、差異比對)都應從 <lens>/tests/ 中的一個失敗測試開始(使用 node:test;共用測試夾具位於 tests/fixture.mjs,僅使用虛構名稱)。將邏輯保留在純模組中;只有 components/app.js 會操作 DOM。然後執行測試,接著在瀏覽器中檢查相同的場景。

視覺化差異

當擁有者要求查看、審查或視覺化變更時:

node docs/lens/diff.mjs [rev]          # 預設為 HEAD;輸出變更列表
python3 -m http.server 8767 --bind 127.0.0.1
open "http://127.0.0.1:8767/docs/lens/index.html"

綠色外框表示新增的項目,黃色表示已變更的項目;已移除的項目會以紅色列在橫幅中。每個新增或變更的列都會連結到其項目。變更是根據 ID 進行匹配的,因此單一主張的變化會凸顯出來,而不會影響整個卡片。在提交之前,請務必清除差異並進行檢查:

node docs/lens/build.mjs
grep -c LENS-V2-DIFF docs/lens/index.html   # 必須輸出 0

重新建置與檢查

node docs/lens/build.mjs && node --test docs/lens/tests/*.test.mjs

然後在瀏覽器中查看受影響的視圖。留言是瀏覽器本地端與來源相關聯的;在切換環境前請先匯出它們。最後提供透鏡連結、變更內容、證據以及任何限制。

相關技能