快轉到主要內容

我與 Claude Code 協作時怎麼寫 prompt ? (2025 下半)

記錄我在 2025 Q4 使用 Claude Code 開發程式時,下 prompt 的一些心態跟技巧

  • AI 進展太快,所以強調這是 2025 Q4
  • 這裡情境是與 AI 協作,不是 AI 自動化
  • 這邊沒有用任何框架:不如說跟框架無關,例如 spec-kit, Claude Skills 等等

把 Prompt 主要內容寫在檔案 #

對於起始規格與後續 change request,我會把主要內容寫在檔案,而不是全部打在聊天框裡面。實際要讓 AI 做事時只會簡單一句「請照著 @xxxxx.md 檔案做」

原因是我能更容易編輯,逐步改進我的 prompt – 尤其我時常會「重來」:對 AI 寫的結果不滿意,又不是一兩句能解決的話,我會另開新的 session 像是聘一個新的 AI 員工, 把我的指令改善後再叫他做。這些情況特別有用

  • 看了結果後,我知道為什麼 AI 不如預期:例如 AI 不具備我想像中的知識
  • 我希望 AI 一次只專注在一件事的開發,控制 context size
  • 需要回顧以前的 prompt 去寫新的規格時

假設我寫好 “prompt file” 以後我會這樣跟 Claude Code 說

AI 有具備相關知識嗎? #

Proofread @spec/puzzle.md to check whether the spec is
clear enough for you to build the 3D rendering.

優點是知道自己會不會寫得太簡略。缺點是這樣問很容易讓 AI 鑽牛角尖,就算規格已經完善到他有能力可以推理寫出好程式了,他還是會繼續講不足之處

單純說他這次的任務是什麼 #

Read the spec @spec/sq1-puzzle.md carefully.

Your job is to implement the two kinds of movements of the puzzle
described in the spec.

Your predecessor recorded @IMPLEMENTATION_NOTES.md while implementing the previous specs.
The note contains background information, rationales, design decisions,
and caveats that may be helpful.

這邊有個交接清單,但為什麼?怎麼生?

交接清單 #

交接清單是讓目前這個 session 有過去的「經驗傳承」,且不想浪費 context size 的用意

我常只想讓 AI 在一個 session 專心做一件事,藉以控制 context 避免「大海撈針」。但有時候前人 前AI 做了一些會需要傳承下去的重要經驗

如果我不接續著同個 session 繼續工作,當我在一個 session 即將結束時,我會這樣說

Create a concise note in a Markdown file describing what you have done.

**DO NOT** include anything that could be inferred by tracing the code.

The note should only record items that cannot be determined by reading the code,
such as mindset, caveats, or things not mentioned in the previous spec.

會特別強調「能爬程式就知道的不要列進去」是因為,我發現 Claude Code 真的很會 trace code, 只要程式架構好、取名取得好,Claude Code 大概都知道哪個東西放哪、誰用、怎麼找

如果單純叫他做交接清單,他很常把詳細 code structure 甚至實作寫出來,但不見得每次都會用到,或者是就算用到了,Claude Code 還是會再掃一遍 repo 浪費 context

生出來的檔案有時我會直接在之後引入(例如前一段的 IMPLEMENTATION_NOTES.md),或是根據回饋手動改規格 md

Prompt file #

我 prompt file 比較隨性,可能會寫成兩種形式之一

  • 自我流加強版 Given-When-Then 格式
  • 單純描述「目標」、「規矩」、「期望」…

自我流 Gherkin 格式 #

在 Given-When-Then 當中引述「範例」跟「定義」,例如下面的 Definition: “Valid short course video files” 跟 Example: @scenarios/short_course_1.yaml

## Scenarios

API Upload-and-link: Create lessons of a fresh short course from GDrive files
    SUT: `upload(slug, create_sc=True)` in router.py

    Given a short course with:
        - 0 lessons
        - A google drive folder bound to the course
        - Example: @scenarios/short_course_1.yaml
    And valid short course video files in GDrive
        - For example, 4 video files in GDrive
        - Definition: "Valid short course video files"
        - Example: @scenarios/short_course_1_gdrive_videos.yaml

    When upload the course videos

    Then the lessons should be created
        - For example, 4 lesson rows are created in DB
    And video records should be created
        - For example, 4 video rows are created in DB
    And video files should be processed and uploaded
        - For example, 4 video files are processed and uploaded to S3
        - Definition: "Video files should be processed and uploaded"
    And every video is linked to the corresponding lesson
        - Definition: "A video is linked to a lesson"
        - Definition: "Rules for short course video linking"
        - Example: @scenarios/short_course_1_after_upload.yaml

...

## Definitions

### Valid short course video files

- A short course has one Google Drive folder
- All the video files should be in this same Google Drive folder without any subfolders
- The valid file name of a video file should follow the pattern
    - "sc-{course_nickname}-L{number}.mp4" , where {number} is an integer starting from 0

...

類似像英文子句那樣,行為的大方向出來,但有時白話不足以形容詳細規格時, 用專屬段落、甚至是其他檔案來補充

其實這做得最好的之一應該是 Robot Framework,但是我自己總覺得有點卡卡的。 這個自我流形式沒有像 Robot Fraemwork 那樣嚴謹,不過有時還堪用

我覺得關鍵還是在,究竟應該要把白話文寫得多詳細,在程式跟人話中間的取捨,讓人跟 AI 看得都開心

單純描述規格 #

在一些特殊的領域,AI 無法從現成知識推理,尤其是需要「控制」的、「物理」相關的。在 prompt file 除了描述 goal, overview, spec, behavior, … 以外,有時就只能很詳盡地描述,利用範例或 code snippet

# Definition of SQ1 Pieces

A SQ1 piece is a rigid object in an extruded shape, where the base 2D shape is parallel to the XZ plane.

## High Level Definition

...

## Visual Attributes

...

const sq1BoundaryVertices = [
    { x: 0, z: 0 },  // origin
    { x: cos75, z: -sin75 },
    { x: sin75, z: -sin75 },
    { x: sin75, z: -cos75 },
    { x: sin75, z: cos75 },
    { x: sin75, z: sin75 },
    { x: cos75, z: sin75 },
    { x: -cos75, z: sin75 },
    { x: -sin75, z: sin75 },
    { x: -sin75, z: cos75 },
    { x: -sin75, z: -cos75 },
    { x: -sin75, z: -sin75 },
    { x: -cos75, z: -sin75 },
];

An extruded shape is created from the base 2D shape and "grow upward" with a thickness.

### Vertices of Pieces

The top layer pieces are the following 2D shapes with baseY = 0.33, thickness = 0.67:
1. Edge: sq1BoundaryVertices[0, 12, 1]
2. Corner: sq1BoundaryVertices[0, 1, 2, 3]
...

The bottom layer pieces are the following 2D shapes with baseY = -1.0, thickness = 0.67:
1. Edge: sq1BoundaryVertices[0, 6, 7]
2. Corner: sq1BoundaryVertices[0, 7, 8, 9]
...

The middle layer pieces are the following 2D shapes with baseY = -0.33, thickness = 0.66:
- Left-center: sq1BoundaryVertices[1, 7, 8, 11]
- Right-center: sq1BoundaryVertices[1, 2, 5, 7]

那 CLAUDE.md 呢? #

以前用 /init 都會生出一大串的 CLAUDE.md ,但現在越來越不這樣做了。盡量讓 CLAUDE.md 簡潔,大概只會放

  • 專案工具大方向(例如用 uv, poetry, …)跟規矩(例如 static website, vanilla js, 用 Three.js, …)
  • 為了要做哪些步驟,指令要怎麼下(測試、DB migration 等等)

剩下都是個別檔案,下 prompt 時手動引入 – 某種角度就是 Skills 的手動版


最後,上述這些其實都是偽科學:沒有控制變因,沒有嚴謹實驗,只有 heuristic 與自我良好 – 跟市面上 70% 以上的所謂 prompt “engineering” 教學一樣 :p

參考就好


若您覺得有趣, 請 追蹤我的Facebook 或  Linkedin, 讓你獲得更多資訊!