Get Bananas

一份適用於 iPhone、iPad、Mac 與 Apple Watch 的手寫式購物清單——當你雙手忙著時,Claude 也能幫你編輯。

2026 年 4 月推出。每台裝置都用 SwiftUI 打造。Mac 應用程式內附 Claude Desktop 擴充功能。二十九種語言,每一種都搭配親手挑選的種子購物資料,讓使用者第一眼看到的清單感覺像在地原生,而非翻譯而來。沒有伺服器、沒有帳號、沒有 API 金鑰。整個後端就是你 iCloud 容器裡的一個 JSON 檔。

Get Bananas 在 iPhone 上顯示一份手寫風格的購物清單,列著蛋白質與碳水化合物
Claude Desktop
把香蕉加到我的購物清單
add_item({"name": "bananas"})
完成——已將香蕉加到「蔬果」分類。還需要其他項目嗎?
Claude 整合

Claude 可以更動你的購物清單。

Get Bananas 在 Mac 應用程式本身內部附帶一個 Claude Desktop 擴充功能。打開 Mac 上的「設定」,點選安裝擴充功能,Claude Desktop 就會跳出安裝提示。同意之後打開新對話,Claude 就有五個工具可以讀取並編輯你真實的購物清單。問它「我清單上有什麼?」——它會告訴你。說「加雞蛋和牛奶」——下次 iCloud 同步時,這些項目就會出現在你的 iPhone 上。

沒有註冊流程、沒有 API 金鑰、也沒有屬於我們的伺服器。這個擴充功能是一份 .mcpb 套件,與 Node.js MCP 伺服器溝通,讀寫的是你自己 iCloud Drive 容器裡的單一 JSON 檔案。

Claude Desktop 你已安裝的應用程式
MCP 伺服器 get-bananas.mcpb
Get Bananas iCloud · BananaList.json

五個工具,各司一職。

工具介面刻意保持精簡。Claude 可以讀取清單、新增項目、移除項目、更新項目,或整份替換。沒有花俏的便利助手,也沒有讀取-修改-寫入的包裝層;介面就只反映你會在對話中真正提出的需求。

  • get_shopping_list讀取目前的清單
  • add_item新增一個項目
  • remove_item移除單一項目
  • update_item勾選、取消勾選、重新命名或變更數量
  • update_shopping_list整份替換(例如「開始一份感恩節清單」)

從應用程式內部安裝。

Mac 應用程式的「設定」裡有一個「安裝擴充功能」按鈕。點下去會用 NSWorkspace 開啟內附的 get-bananas.mcpb 檔案,Claude Desktop 就會將它註冊為擴充功能並請使用者確認。整個安裝過程其實只是對應用程式套件內檔案執行一次 NSWorkspace.shared.open()——因為平台已經提供了正確的基本工具:一種代表「將我註冊到 Claude」的檔案格式。

Swift · SettingsView.swift:309-324
private func installExtension() {
    guard let extensionURL = Bundle.main.url(
        forResource: "get-bananas",
        withExtension: "mcpb"
    ) else {
        extensionMessage = "Error: Extension not found in app bundle."
        return
    }

    let opened = NSWorkspace.shared.open(extensionURL)
    if opened {
        extensionMessage = "Check Claude Desktop for the install prompt..."
    } else {
        extensionMessage = "Couldn't open the extension. Make sure Claude Desktop is installed."
    }
}

這套模式對許多原生應用程式都將至關重要。擴充功能就住在你的應用程式套件裡,跟著應用程式一起發行、一起更新——沒有獨立註冊表、沒有逐個使用者的設定、也不必「把這個 URL 複製到設定檔裡」。如果你希望 Claude 能在你的應用程式裡做某件事,就把那件事放進應用程式裡,讓 OS 來居中介紹。

美學

紙上鋼筆,加上記憶。

購物清單就是用筆、寫在紙上、靠手親自完成的。這款應用程式就是這種感覺。分類標題使用 Caveat 風格的手寫字體、分隔線是淡淡的鋼筆細線、未勾選項目是空心圓圈。當你輕觸勾選某個項目時,應用程式會在文字上畫一條手繪線——而每一條線都略有不同。

Get Bananas 在 iPhone 上顯示購物清單
iPhone
Get Bananas 在 iPad 上顯示購物清單
iPad
Get Bananas 在 Mac 上顯示購物清單,搭配手繪風格標題
Mac
Get Bananas 在 Apple Watch 上顯示購物清單
Watch

刪除線是一個 <code>Shape</code>,每一個勾選都是獨一無二的。

這條手繪線是一個自訂的 SwiftUI Shape,由二十段路徑組成。每段端點都會在 -1.5 到 +1.5 點之間取得一個微小的隨機垂直偏移。結果是:每一條在執行階段繪製的刪除線,都和上一條略有差異。在一份二十項的清單裡,沒有兩條線會完全相同——就像沒有兩筆筆觸會一模一樣。

Swift · HandDrawnStrikethrough.swift
struct HandDrawnStrikethrough: Shape {
    func path(in rect: CGRect) -> Path {
        var path = Path()
        let startY = rect.midY
        let segments = 20
        let segmentWidth = rect.width / CGFloat(segments)

        path.move(to: CGPoint(x: 0, y: startY))

        for i in 1...segments {
            let x = CGFloat(i) * segmentWidth
            let randomOffset = CGFloat.random(in: -1.5...1.5)
            let y = startY + randomOffset
            path.addLine(to: CGPoint(x: x, y: y))
        }
        return path
    }
}

這只是十二行程式碼。但這也就是「看起來像手寫的」與「感覺像手寫的」之間的差別。一個靜態 SVG 刪除線同樣能在當天交付,像素數一樣,但會被當成裝飾。

Get Bananas 在 Mac 上顯示兩個已勾選項目,配上手繪刪除線,每一條都略有不同
兩條刪除線・兩條截然不同的線

仔細看看上方那兩個已勾選的項目。穿越「Egg whites」與「Cottage cheese 2%」的線條形狀並不一樣——晃動不同、角度也不同。它們是同一個 Shape 在相距 200 毫秒間生成的,每次都重新抽取隨機性。這就是這款應用程式的整體性格:細小、誠實的變化,內建在版面之中。

在地化

二十九種語言,附在地購物資料。

日本使用者第一次打開的清單,並不是翻譯過來的美式雜貨採購。它是たんぱく質分類裡的卵白——也就是蛋白,放在你真的會在東京貨架上看到的「蛋白質」分類底下。App Store 上有二十九種在地化版本,每個非英文語系都附上自己親手挑選的 SeedData-{locale}.json,內含符合當地文化的範例項目與分類名稱。阿拉伯文版本是 al-burutinat 分類裡的 biyad al-bayd。希伯來文版本是 helbonim 分類裡的 helbonei beitza。二十九份種子檔案,全靠手寫,不是丟進字串翻譯器跑一次就交差。

Get Bananas 英文版顯示蛋白質區塊,包含蛋白、茅屋起司、雞胸肉
EnglishProteins · 預設種子資料
Get Bananas 日文版以片假名與漢字顯示在地食材名稱
日本語たんぱく質 · 在地種子資料
Get Bananas 阿拉伯文版顯示由右至左的版面與在地食材名稱
العربيةالبروتينات · RTL
Get Bananas 希伯來文版顯示由右至左的版面與在地食材名稱
עבריתחלבונים · RTL
Get Bananas 簡體中文版顯示在地食材名稱
简体中文蛋白质 · 在地種子資料

只要不去抗拒它,RTL 就是免費的勝利。

SwiftUI 把 .leading.trailing 視為語意上的方向,而不是 .left.right 那種固定方位。只要在語意層面把畫面擺好一次,阿拉伯文與希伯來文就會免費自動翻轉整個版面——分類標題換到右邊、勾選圓圈換到文字左邊、「重設」與「更多」按鈕也會旋轉到對角。我們完全沒有為此寫一行 RTL 專屬的程式碼。

Get Bananas 英文版有兩個已勾選項目,由左至右版面
英文 · LTR
Get Bananas 阿拉伯文版有兩個已勾選項目,由右至左版面
阿拉伯文 · RTL
Get Bananas 希伯來文版有兩個已勾選項目,由右至左版面
希伯來文 · RTL

手繪刪除線就疊在這一切之上,根本不需要知道目前的語系。Shape 放在項目名稱 Text 上方的 ZStack 裡,在那個邊界框中繪製;周圍那一行是由 SwiftUI 的 RTL 版面負責鏡像翻轉。線條最終會落在它該去的地方——在文字之上——而 Shape 程式碼裡完全沒有任何語言相關的判斷。

架構

你 iCloud 容器裡的一個 JSON 檔。

跨裝置交換的內容就是你自己 iCloud Drive 裡的單一檔案:Get Bananas 容器中的 BananaList.json。MCP 伺服器讀寫的就是這個檔。iOS、iPad、Mac 與 Watch 應用程式讀寫的也是這個檔。iCloud 負責同步——這是 Apple 提供的免費基礎設施,靜態加密,當「進階資料保護」啟用時更是端對端私密。我們什麼都沒有。

JavaScript · mcp-extension/server/index.js:21-28
// iCloud path for Banana List data
const ICLOUD_FILE_PATH = path.join(
  os.homedir(),
  "Library/Mobile Documents/iCloud~com~941apps~Banana-List/Documents/BananaList.json"
);

// Lock file for atomic operations
const LOCK_FILE_PATH = ICLOUD_FILE_PATH + ".lock";
const LOCK_TIMEOUT_MS = 5000;

MCP 伺服器接觸到的每一條路徑,都是那個 JSON 檔的兄弟檔。鎖定檔就放在它旁邊(.lock,原子寫入,五秒逾時且若過期會自動清理)。寫入會先寫到帶有行程標記的暫存檔(.tmp.{pid}),再原子化重新命名為正式路徑。整個並行控制模型——Claude vs. 執行中的應用程式——可以用一個取得/釋放函式裝完。

在每台裝置上,SwiftData 是本地儲存層。iCloud 上的 JSON 才是傳輸格式。SwiftData 在裝置上保持快速且可查詢;JSON 則保持簡單可讀,方便同步、也方便 Claude 操作。兩個儲存層各做一件事——誰都不嘗試一人兼任兩職。

這讓我們敢於做出哪些承諾。

沒有 941 Apps 伺服器。沒有分析。沒有登入。沒有給 Claude 用的 API 金鑰——你已經在 Claude Desktop 完成驗證了。沒有訂閱。擴充功能完全開源,任何好奇的人都能讀完整條資料路徑:就是那個 JSON 檔,它從頭到尾就只碰那一個檔。你的購物清單從不透過任何屬於我們的基礎設施離開你的 iCloud 容器。

實踐

工作就是那份清單。

購物清單就是一份工作。在你想到某項東西的當下捕捉下來、找到它時打勾、其他時間就讓清單退到一旁別擋路。產品本身就是那份工作。它不是食譜應用程式、不是備餐規劃器、不是條碼掃描器、不是價格追蹤器、也不是庫存管理工具。清單,才是交付物。

Claude 整合之所以值得擁有一席之地,正因為它在「拿手機打字是錯誤工具」的場景中,加速了輸入與編輯:站在爐邊雙手沾滿大蒜味、邊聊邊規劃這週的餐點、把食譜卡上十二項東西照抄而不必逐一重打。把這些片刻交給 Claude,能讓應用程式的其他部分維持精簡。

凡是不屬於清單、輸入、勾選或那種委派的事情,都是另一款不同的產品。不同的產品該歸不同的應用程式。

克制

Get Bananas 裡沒有的東西。

多數購物清單應用程式的路線圖最終都通往「變成另一個 Instacart」。這款不是。Get Bananas 是刻意拒絕長成一個雜貨平台的。以下是它明確不做的事:

  • 沒有條碼掃描
  • 沒有價格、總計或預算功能
  • 沒有食譜匯入或備餐規劃
  • 沒有走道導引或商店地圖
  • 沒有網頁版
  • 沒有帳號、沒有登入、不蒐集電子郵件
  • 沒有與其他使用者共享清單(只有你自己的 iCloud,跨你自己的裝置)
  • 永遠沒有任何分析
  • 沒有廣告、沒有訂閱、沒有 Pro 方案
  • 沒有惱人的提示視窗,也沒有應用程式內推銷

Get Bananas 售價 $0.99。買斷一次就是你的。MCP 伺服器是開源的。資料屬於你自己,住在你的 iCloud Drive。它的工作就是快速輸入、快速勾選,以及在你雙手沾滿香菜時把編輯交給 Claude。除此之外的一切,都是別人家的應用程式。

Get Bananas.

iPhone、iPad、Mac 與 Apple Watch 版本現已在 App Store 上架。從 Mac 應用程式內安裝 Claude Desktop 擴充功能。