miaomiao-bar

onblogAGPL-3.0活跃维护

macOS 菜单栏剪贴板工作台,自动把复制进来的文字和图片整理成可直接使用的格式,省去手动清洗排版。

A macOS clipboard workbench: text and pictures that land on the clipboard leave usable. 喵喵剪贴板:macOS 上的剪贴板工作台,文字和图片进了剪贴板就变成能直接用的样子。

暂无版本1,967star280fork同步于 2026-11-11 05:43 UTC

怎么上手

由 README 提炼,执行前请确认
从 bar.wordtk.com 下载 dmg 拖入 Applications 后启动;源码构建:npm install && npm run dev
硬件要求按 README 说明

仅支持 macOS 13 及以上,Apple Silicon 与 Intel 均有 dmg;README 未提及显存或 GPU 要求。

支持 Apple Silicon
下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

macOS 菜单栏剪贴板工作台,把复制来的杂乱文字和图片就地整理成可直接粘贴的样子

macOS 菜单栏剪贴板工作台,自动把复制进来的文字和图片整理成可直接使用的格式,省去手动清洗排版。

核心能力

  • 按当前剪贴板内容动态过滤可用动作,只显示真正适用的项
  • 富文本与 Markdown 双向转换,粘贴到 Word 或编辑器都合适
  • 中英文之间自动加空格并把标点转全角
  • 清理追踪参数、去重排序、合并成一行等 21 个纯函数动作
  • 图片一键上传到自建 S3 兼容桶并回写链接,支持 R2/COS/OSS/MinIO

容易踩的坑

构建为 ad-hoc 签名未公证,首次启动需到系统设置→隐私与安全性选「仍要打开」;图片上传需先在设置→存储里配置桶的 Endpoint、Region、密钥等字段;源码打包需在 .env 里设置 VITE_SITE_URL,否则网站按钮、更新检查和启动统计会关闭。

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

0 个版本

暂无 release 数据(可能没有发版,或尚未同步)。

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    miaomiao-bar · 喵喵剪贴板

    The clipboard workbench for macOS: whatever lands on it — a paragraph, a column of names, a picture — comes back cleaned, tidied and ready to paste.

    🇺🇸 English  ·  🇨🇳 简体中文

    Copy something messy, click the menu bar, pick what it should become. Miaomiao Bar rewrites the clipboard in place, so the next ⌘V is already right: plain text without the web styling, Chinese and English properly spaced, a list squeezed into one line, a link without the utm_source=… tail.

    No account, no window to manage, no network call. The panel shows what the current clipboard can become, never a fixed menu of everything the app can do.


    Table of contents

    What it doesActions
    ShortcutsHow it works
    PrivacyProject layout
    Build from sourceStatus
    License

    Install

    Grab the dmg from bar.wordtk.com (Apple Silicon and Intel), drag the app into Applications, and launch it. The build is ad-hoc signed rather than notarised, so the first launch needs one extra step: after macOS blocks it, open System Settings → Privacy & Security and choose Open Anyway (macOS 14 and older: right-click → Open).

    Nothing to configure for the text tools. For image uploads, add a bucket in Settings → Storage — the site's image host section walks through the four fields that matter.

    Screenshots

    Dark mode

    Toggle in the top bar — the choice is remembered, and the panel never changes appearance behind your back when the system switches.

    What it does

    One model, one job: clipboard in → transformation → clipboard out.

    • Two appearances, no auto-switching. A dark bar at night (charcoal and amber) and a light bar at daytime (cream paper and caramel ink). The switch lives in the top bar and the choice is remembered — nothing changes under you when macOS flips its own appearance.
    • Images get three buttons, nothing more. Copy the picture back to the clipboard, open it in Preview (macOS's own editor), or send it to your bucket / Downloads.
    • A menu bar panel, not a window. Click the tray icon, pick an action, paste. No dock icon, no window stealing a Space.
    • Only the actions that apply. The list is filtered by what is actually on the clipboard right now: "To plain text" only appears for rich text, the typography group only when Chinese sits next to Latin, the tracking-link cleaner only for links that carry tracking.
    • Chinese typesetting, done properly. A space between Chinese and Latin, and punctuation that belongs to the right script — the two things every Chinese writer fixes by hand.
    • Undo is one keystroke. Every action keeps the previous clipboard, so a wrong pick costs a ⌥⌘Z, not a re-copy.
    • Images go to your own bucket. One click on a screenshot uploads it to Cloudflare R2, Tencent COS, Alibaba OSS or MinIO and puts the link back on the clipboard — as a URL, Markdown, HTML tag or BBCode.
    • Zero runtime dependencies. Only Electron itself; signing, storage and every transformation are hand-written on top of Node's built-ins.

    Who this is not for: there is no Base64 encoder, no regex playground and no timestamp converter here. Those are developer tools, and this app deliberately belongs to whoever copies text — writers, ops people, anyone tidying a list at midnight. Formatting JavaScript/CSS/HTML is out of scope too: it needs a formatter dependency, which is exactly the weight this project refuses.

    Actions

    Every action is a pure function; the registry decides what to show for the clipboard at hand. The set is deliberately small: it is what a writer reaches for, not everything that is technically possible.

    Rich text ⇄ Markdown go both ways. Copy an article from a browser and get clean Markdown; write Markdown and put rich text on the clipboard, so Word, WeChat or Mail paste it formatted while a code editor still gets the Markdown source.

    GroupActions
    ConvertEdit text · Copy to clipboard · To plain text · To Markdown · To rich text
    Clean upTrim whitespace · Collapse blank lines · Join into one line · Strip line numbers · Remove invisible characters · Strip Markdown syntax
    TypeSpace between Chinese and Latin · Punctuation → full-width
    ListsRemove duplicate lines · Sort lines
    LinksClean tracking parameters · Extract every link
    ImageOpen in Preview · Copy to clipboard · Upload to your bucket · Save to Downloads

    Adding a tool means adding one file under electron/actions/ — the panel, the tests and the IPC surface pick it up automatically.

    Image hosting

    Add a bucket in Settings → Storage and the image actions appear whenever the clipboard holds a picture.

    FieldWhat to put there
    Endpointhttps://<account-id>.r2.cloudflarestorage.com for R2, https://cos.<region>.myqcloud.com for COS, https://oss-<region>.aliyuncs.com for OSS
    Regionauto for R2; the real region for COS/OSS
    BucketThe bucket name
    Public domainThe domain your images are served from — this is the link you get back
    Access key / SecretAn S3 key with write access; the secret is encrypted with the macOS Keychain
    Path-styleOn for MinIO and self-hosted, off for virtual-host buckets

    Object keys are content addressed (images/2026/10/4f9c1a2b.png), so the same picture uploaded twice is one object. The link format (URL / Markdown / HTML / BBCode) is a setting, not a per-upload choice.

    Images

    Screenshots are macOS's job: ⌘⇧⌃4 puts a region straight on the clipboard and the panel picks it up. From there the image gets three actions — copy back to the clipboard, open in Preview, or upload / save. There is no capture shortcut of our own, so the app needs no Screen Recording permission and never grabs the screen in the background.

    History

    The bottom row of the panel keeps the last three things you copied; All opens the full list.

    • Text and images, newest first, one character or a thumbnail as the preview
    • Click any entry to put it back on the clipboard
    • 100 items / 200 MB by default (50, 100 or 200 in settings), oldest dropped first
    • Re-copying something moves it to the top instead of piling up duplicates
    • Only what you copy — nothing is uploaded, ever
    • Recording can be switched off at any time

    Shortcuts

    KeysAction
    ⌥⌘VShow / hide the panel
    ⌥⌘ZUndo the last action
    EscClose the panel

    The panel is mouse-first: no arrow-key cursor, no Enter to run. Click an action and it happens.

    How it works

    electron/actions/   One file per group of transformations, pure functions
    electron/clipboard.cjs
                        Clipboard read/write for Electron 44+'s async clipboard API
    electron/main.cjs   Tray, panel window, shortcuts, IPC
    src/                Panel renderer: preview, action grid, bilingual copy
    

    Three rules keep it honest:

    1. Actions never touch Electron. They take { kind, text, html } and return { text } or { error }, which is why the whole set is covered by node:test with no dependency.
    2. The main process owns the clipboard. The renderer only ever sees a preview and a list.
    3. Writing back is the end of the flow. No drawers, no side files — the result is on the clipboard, ready to paste.

    Privacy

    • The clipboard is read while the panel is open, and polled in the background to build history — every 1.2 s for text, every 3 s for images.
    • History never leaves this Mac: it is an index plus image blobs in ~/Library/Application Support/喵喵剪贴板/.
    • Two network calls, both listed here. One is the PUT to the bucket you configured. The other is a single anonymous launch signal (a random device id generated on this Mac, the UTC date and the coarse country/city Cloudflare derives) that feeds the usage page; turning Anonymous usage off in Settings stops it immediately. No content, no IP, no user agent, no crash reporting, and the update check is a plain GET of the public release manifest. That GET uses a 15s timeout plus one retry: on slow dual-stack networks an AAAA record is often a blackhole — Chromium falls back to IPv4 via Happy Eyeballs while a stalled request looks like "the update check is broken". A failure now says why (no site configured / network unreachable / server error) instead of one generic sentence.
    • Turning history off stops recording immediately; Clear history deletes the index and every blob. Any single entry can also be deleted from the full list — hover a row and the delete button floats up on the right, which removes that entry and its blobs.
    • There is no capture of our own: the app never reads the screen, so no Screen Recording permission is ever requested.
    • No telemetry, no crash reporting, no update check.

    Project layout

    electron/           Main process: tray, panel window, clipboard, IPC surface
    electron/actions/   The transformation registry and its groups
    electron/sigv4.cjs
                        AWS Signature V4 + S3 PUT, verified against the AWS test vector
    electron/storage.cjs
                        Bucket configuration; secrets encrypted with the Keychain
    electron/history.cjs
                        History index + image blobs, Electron-free and unit tested
    electron/watcher.cjs
                        Clipboard poller (macOS has no clipboard change event)
    electron/settings.cjs
                        Persisted switches and limits
    src/                Renderer: panel markup, styles, i18n, DOM logic
    src/styles/         One dark glass theme, no CSS framework
    build/              Icon masters (PNG) and the generated icns
    scripts/            afterPack hook that ad-hoc signs the bundle
    tests/              node:test suites for the actions
    

    The renderer never touches Node: everything goes through a narrow contextBridge with contextIsolation and sandbox enabled.

    Build from source

    npm install
    npm run dev            # Vite + Electron with hot reload
    npm test               # 120 unit tests, no dependencies
    npm run dist:arm64     # dmg for Apple Silicon, output in release/
    npm run dist:x64       # dmg for Intel (fetches the x64 native addon first)
    

    No native modules ship with the app any more, so both architectures are pure Electron builds.

    Put VITE_SITE_URL=https://your-site.example in a .env file at the repo root (it is git-ignored). npm run dist then bakes it into the bundle, which feeds the settings page's Website button, the tray's website item, the update check and the anonymous launch ping. The domain never reaches the repository. Without it those features stay off and the buttons fall back to the GitHub repository.

    [email protected] in the same .env is optional: it fills the About panel's mail entry, and the entry stays hidden when it is absent.

    The marketing site lives in site/ and deploys as its own Cloudflare Worker (npm run deploy from inside it). It shares the common D1 database with sendtk, codetk and miaomiao-notes (the free plan allows 10 databases), so its table is bar_launches with bar_-prefixed indexes. Schema setup is npx wrangler d1 migrations apply common --remote; since d1_migrations is a database-wide ledger keyed by file name, files in site/migrations/ keep the project prefix (0001_bar_init.sql).

    Generated assets

    Nothing binary in this repo is hand-edited; each image has a source script:

    bash tools/build-icons.sh                              # icon.icns, site icons, favicon, apple-touch-icon, tray
    npm run build && npx electron tools/shoot-panels.cjs   # panel screenshots, light
    SHOOT_THEME=dark npx electron tools/shoot-panels.cjs   # panel screenshots, dark
    npx electron tools/make-og.cjs                         # the 1200×630 link preview card
    

    The icon masters (build/icon-source.png, build/icon-favicon.png) are the only images you edit by hand; see tools/build-icons.sh for the plate geometry and why 16/32px use the head close-up.

    Releasing

    npm run build && npm run dist     # both architectures -> release/
    cd site && npm run release        # upload to R2, rewrite the manifest, prune the old version
    

    site/scripts/publish-release.mjs uploads release/*.dmg under the miaomiao-bar/ prefix in the shared common bucket, rewrites site/latest.json (the manifest the Worker serves) and then deletes the installers the previous manifest advertised, so R2 only ever holds the live version. Shipping to production is still git push: Cloudflare Workers Builds deploys the site.

    Status

    1.14.1: 21 actions across six groups, image upload to your own S3-compatible bucket, save to Downloads and open in Preview, local clipboard history, undo next to the action count, an update check, an anonymous usage page, and the bilingual panel. The app is called 喵喵剪贴板 (Miaomiao Bar) and lives at bar.wordtk.com; dmgs for both architectures are served from Cloudflare R2.

    License

    Dual-licensed:

    • Open source — AGPL-3.0-only. Free to use, modify and self-host. If you distribute a modified version, the AGPL requires you to publish the corresponding source as well.
    • Commercial — if AGPL does not fit your product (for example, you want to ship a closed-source derivative) see LICENSE-COMMERCIAL.md.

    The name "喵喵剪贴板 / miaomiao-bar" and the icon are not covered by the open-source grant.