context-attachment-manager
Codex and Claude Code plugin (works in Claude Desktop): choose which past images go to the model with your next message. Unchecked images become placeholders, the conversation goes on, and requests st
翻譯準備中
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗A browser extension for Chrome, Firefox and Safari that passively captures every push to window.adobeDataLayer, deep-clones the full getState() snapshot per push, surfaces the timeline in a panel (Chrome Side Panel, Firefox Sidebar, Safari toolbar popup), and exports it as a self-describing JSON file for post-recording debugging.
Built for debugging ACDL-instrumented sites.
adobeDataLayer.push(...) with a deep-cloned state snapshot per eventscope: 'all')storage.session.nvmrc)Each release attaches one zip per browser: acdl-debugger-vX.Y.Z-chrome.zip, -firefox.zip and -safari.zip. Releases also go to the Chrome Web Store and Firefox Add-ons automatically, and appear there once each store's review approves them, so the store links above are the easiest way to install and stay up to date. The zips are for loading the extension unpacked, for testing or where the stores aren't an option.
-chrome.zip and unzip itchrome://extensions and enable Developer mode (top-right toggle)To update, replace that folder's contents with the newer release and click the reload icon on the extension's card.
.xpi.about:debugging#/runtime/this-firefox, click Load Temporary Add-on, and pick the -firefox.zip (or dist/firefox/manifest.json). Temporary add-ons are removed when Firefox restarts.Safari only runs web extensions that ship inside a native macOS app, so the zip is the input to Apple's converter, not something you install directly. On a Mac with Xcode:
unzip acdl-debugger-vX.Y.Z-safari.zip -d acdl-safari # or use dist/safari from a local build
xcrun safari-web-extension-converter acdl-safari --macos-only --app-name "ACDL Debugger" --bundle-identifier com.example.acdl-debugger
Build and run the generated Xcode project, then enable the extension in Safari → Settings → Extensions. To load an unsigned build, first turn on Develop → Developer Settings → Allow unsigned extensions (resets each time Safari quits). Grant the extension access to the sites you debug when Safari asks. Distributing to other Macs requires an Apple Developer account (App Store or notarized app).
Safari has no side panel or sidebar API, so the panel opens as a toolbar popup and closes when you click back into the page. Capture keeps running in the background; reopen the popup to see new events. Safari has no downloads API, so Export saves through a regular download link.
Click the gear button in the panel header to open Settings.
Data layer names: the extension always watches window.adobeDataLayer. If a site exposes its data layer under another name, add that name here (comma-separated, e.g. myDataLayer). This covers a self-hosted or modified ACDL build, or a page that pushes into its own custom-named array. Adobe's Client Data Layer Tags extension can also rename the data layer, but it still creates adobeDataLayer, so those sites are usually captured without any setting. Adding the custom name there doesn't hurt: if two names point at the same data layer, each event is captured only once.
_ and $), up to 10 extra names.#2 · 10:14:03.512 · myDataLayer), and every exported event includes its dataLayer name.npm install
npm run icons # regenerate icons from assets/icon-source.png (already committed)
npm run build # produces dist/chrome, dist/firefox, dist/safari
Then load it into Chrome:
chrome://extensionsdist/chrome directoryFor Firefox and Safari, use dist/firefox / dist/safari as described above.
The panel always reflects the active tab. Switching tabs re-subscribes automatically.
window.adobeDataLayer; events appear in the panel.https://example.com/; the panel shows a "not detected" banner.myDataLayer, nothing appears until you add myDataLayer under Settings; then its events appear without reloading.for (let i = 0; i < 6000; i++) adobeDataLayer.push({ event: 'load.test', n: i }) — the store FIFO-trims at 5000.All non-trivial logic lives in src/lib/ as pure modules (no extension APIs) so it can be unit-tested in Node. The four entry files — inject.js, content.js, background.js, sidepanel/sidepanel.js — are the only places that touch extension APIs / window.*. They use ext from src/ext.js (browser in Firefox/Safari, chrome in Chrome) rather than chrome.* directly.
manifest.json is the Chrome manifest; src/lib/target-manifest.js derives the Firefox and Safari manifests from it at build time.
npm install # install dev dependencies (esbuild, vitest, jsdom, sharp)
npm test # run unit tests (103 tests: 11 lib modules + the store scripts)
npm run test:watch # re-run tests on change
npm run test:e2e # build, then run real-browser tests in headless Chromium + Firefox
npm run build # one-off bundle into dist/<chrome|firefox|safari>
npm run build -- --target=firefox # build a single target
npm run build:watch # rebuild dist/chrome on change (add -- --target=firefox for Firefox)
npm run icons # regenerate icons/ from assets/icon-source.png
Conventions:
tests/ before adding behavior to a src/lib/ module.inject.js must be self-contained — it runs in the page MAIN world and cannot import. esbuild emits IIFE bundles targeting chrome120 / firefox142 / safari17.After editing, run npm run build and reload the extension (chrome://extensions, or Reload in about:debugging for Firefox).
CI (.github/workflows/ci.yml) runs the tests, builds all three targets, runs Mozilla's web-ext lint (the AMO validator) on the Firefox build, and runs the e2e suite in Chromium and Firefox on every push to main and every pull request.
E2E tests (tests/e2e/) load the built extension into headless Chromium (Playwright) and Firefox (puppeteer-core over WebDriver BiDi), serve a local page running the real ACDL library, and check that captures, state snapshots, navigation, strict-CSP pages, the panel's event list and detail view, Clear, and renamed data layers all work. Chromium comes from npx playwright install chromium. Firefox must be installed on the machine; set FIREFOX_BIN if it isn't on PATH. Safari isn't covered: it only runs on macOS.
Page MAIN world Isolated world Extension
───────────────── ────────────── ─────────
inject.js ──▶ content.js ──▶ background.js ◀──▶ sidepanel/
(hooks ACDL, (bridge: (service worker: (UI: list,
deep-clones state, window.postMessage per-tab store + detail,
posts events) → chrome.runtime) session storage Clear/Export)
persistence)
ACDL lives on window and is invisible to isolated-world content scripts, so a page-world script (inject.js) hooks it via its documented addEventListener API. The isolated-world content.js bridges page messages to chrome.runtime. The service worker owns the canonical Map<tabId, capture> and persists to chrome.storage.session to survive MV3 eviction.
See CLAUDE.md for the full architecture notes, file layout, and known gotchas.
manifest.json # MV3 manifest for Chrome (Firefox/Safari variants derived at build)
build.mjs # esbuild bundle script
vitest.config.js # unit test config (vitest.e2e.config.js for e2e)
.github/workflows/ # CI (test + build) and tag-driven releases
scripts/ # icon generation, release version checks, store publishing helpers
assets/icon-source.png # source artwork (not shipped in dist/)
src/
inject.js # page-world entry (self-contained IIFE)
content.js # isolated-world bridge
background.js # service worker (event page in Firefox)
ext.js # browser/chrome namespace shim
lib/ # pure, unit-tested modules
sidepanel/ # panel UI (html/js/css): side panel / sidebar / popup
tests/ # vitest, one file per lib module; e2e/ = real-browser tests
icons/ # generated by `npm run icons` (committed)
dist/<target>/ # build output per browser — load unpacked (git-ignored)
Copyright 2026 Andy Lunsford. Licensed under the Apache License, Version 2.0.