@alive-game/alive-tagger

中文文档
0.2.1发布于 2026/06/17MITTypeScriptES Module零依赖近 30 天下载 6.5万

Element selection and source tagging for Alive workbench

原始使用文档
文档目录23 节
  1. Features
  2. Installation
  3. Usage
  4. Vite Plugin (Required)
  5. Client Script (Optional - for iframe selection UI)
  6. How It Works
  7. 1. JSX Source Tagging (Vite Plugin)
  8. 2. Element Selection (Client Script)
  9. 3. PostMessage Communication
  10. API Reference
  11. Plugin Options
  12. Types
  13. Utility Functions
  14. Client Functions
  15. Architecture
  16. Comparison: alive-tagger vs React Grab
  17. Integration with Alive
  18. Key files:
  19. Caddy Configuration
  20. Development
  21. Files
  22. Security Considerations
  23. License

@alive-game/alive-tagger

Element selection and source tagging for Alive workbench. Enables click-to-select UI elements with source file information, allowing Claude to know exactly which component and file the user is referring to.

Features

  • JSX Source Tagging: Attaches source file info (fileName, lineNumber, columnNumber) to every DOM element at build time
  • Element Selection: Client script for click-to-select element selection with visual feedback (activated by the workbench select button)
  • PostMessage Bridge: Sends selected element context to parent frame for Claude integration

Installation

# In your Vite React project
bun add @alive-game/alive-tagger

Usage

Vite Plugin (Required)

Add the plugin to your vite.config.ts:

import { aliveTagger } from "@alive-game/alive-tagger"

export default defineConfig(({ mode }) => ({
  plugins: [
    react(),
    mode === "development" && aliveTagger()
  ].filter(Boolean),
}))

Client Script (Optional - for iframe selection UI)

The client script provides click-to-select with visual feedback. It's automatically initialized when imported:

// In your app entry point (only needed if in iframe)
import "@alive-game/alive-tagger/client"

Or inject via HTML:

<script type="module">
  import { initAliveTagger } from "@alive-game/alive-tagger/client"
  initAliveTagger()
</script>

How It Works

1. JSX Source Tagging (Vite Plugin)

The plugin intercepts React's jsx-dev-runtime and wraps the jsxDEV function to inject refs that store source information on DOM nodes:

// Every DOM element gets this attached via Symbol:
element[Symbol.for("__aliveSource__")] = {
  fileName: "client/pages/Index.tsx",
  lineNumber: 42,
  columnNumber: 8,
  displayName: "Button"
}

// Global map for reverse lookups:
window.aliveSourceMap = Map<string, Set<WeakRef<Element>>>

2. Element Selection (Client Script)

When running in an iframe:

  1. Activate: The parent frame posts TAGGER_ACTIVATE (the workbench select button); cursor becomes crosshair
  2. Hover: Elements with source info get highlighted with green border and label showing ComponentName · path/to/file.tsx:line
  3. Click: Captures element context and sends to parent frame via postMessage

3. PostMessage Communication

Selected element context is sent to the parent frame:

window.parent.postMessage({
  type: "alive-element-selected",
  context: {
    fileName: "client/pages/Index.tsx",
    lineNumber: 42,
    columnNumber: 8,
    displayName: "Button",
    html: "<button class='...'>Click me</button>",
    tagName: "button",
    className: "btn-primary",
    id: "submit-btn",
    parentComponents: ["Form", "Page"]
  }
}, "*")

API Reference

Plugin Options

interface AliveTaggerOptions {
  /** Enable source tagging (default: true in dev mode) */
  enabled?: boolean
  /** Enable debug logging */
  debug?: boolean
}

aliveTagger({ enabled: true, debug: false })

Types

import {
  SOURCE_KEY,                    // Symbol.for("__aliveSource__")
  ELEMENT_SELECTED_MESSAGE_TYPE, // "alive-element-selected"
  type SourceInfo,
  type ElementSelectedContext,
  type ElementSelectedMessage,
  type AliveTaggerOptions,
} from "@alive-game/alive-tagger"

Utility Functions

import {
  getElementSource,      // Get source info from element
  hasSourceInfo,         // Check if element has source info
  formatSourceLocation,  // Format as "file.tsx:42:8"
  isElementSelectedMessage, // Type guard for messages
} from "@alive-game/alive-tagger"

// Example usage
const source = getElementSource(document.querySelector("button"))
if (source) {
  console.log(formatSourceLocation(source)) // "client/pages/Index.tsx:42:8"
}

Client Functions

import { initAliveTagger } from "@alive-game/alive-tagger/client"

// Initialize selector (auto-called on import, but can be manual)
const cleanup = initAliveTagger()

// Later: cleanup()

Architecture

┌─────────────────────────────────────────────────────────────────────────┐
│  Alive (terminal.alive.best)                                    │
│  ┌──────────────────────┐  ┌──────────────────────────────────────────┐ │
│  │  Chat Interface      │  │  Workbench Component                       │ │
│  │                      │  │  - Listens for 'alive-element-selected'  │ │
│  │  Shows selected      │◀─┤  - Displays source info to user          │ │
│  │  element context     │  │  - Injects into next Claude message      │ │
│  └──────────────────────┘  └──────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────────────┘
                                        ▲
                                        │ postMessage
┌─────────────────────────────────────────────────────────────────────────┐
│  User Site (in preview iframe)                                          │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  alive-tagger plugin (Vite)                                       │  │
│  │  - Intercepts jsx-dev-runtime                                     │  │
│  │  - Attaches Symbol.for('__aliveSource__') to every DOM element    │  │
│  │  - Maintains window.aliveSourceMap for lookups                    │  │
│  └───────────────────────────────────────────────────────────────────┘  │
│  ┌───────────────────────────────────────────────────────────────────┐  │
│  │  alive-tagger/client (optional)                                   │  │
│  │  - Handles click-to-select (button-activated)                     │  │
│  │  - Visual highlight on hover                                      │  │
│  │  - Posts context to parent frame                                  │  │
│  └───────────────────────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────┘

Comparison: alive-tagger vs React Grab

Featurealive-taggerReact Grab
ApproachVite plugin + clientRuntime fiber traversal
Data attachmentBuild-time via refsRuntime fiber inspection
Symbol key__aliveSource____jsxSource__
Selection UIBuilt-in (button-activated click)Built-in
CommunicationpostMessageHTTP localhost:4567
Env requirementNone (dev mode auto)None
Designed forAlive iframeClaude Agent SDK CLI

Integration with Alive

The alive-tagger is integrated with Alive's workbench preview. When a user activates the select button and clicks an element:

  1. Workbench receives postMessage: Workbench.tsx and WorkbenchMobile.tsx listen for alive-element-selected messages
  2. Context propagates via WorkbenchContext: The selection is passed through useWorkbenchContext()
  3. Chat input auto-fills: The selected element is formatted as @ComponentName in src/path/file.tsx:lineNumber and inserted into the chat input
  4. User can send to Claude: The reference helps Claude understand exactly which element/component to modify

Key files:

  • apps/web/features/chat/lib/workbench-context.tsx - Context with setSelectedElement and registerElementSelectHandler
  • apps/web/features/chat/components/workbench/Workbench.tsx - Listens for postMessage, calls setSelectedElement
  • apps/web/app/chat/page.tsx - Registers handler to insert selection into chat input

Caddy Configuration

For HMR to work properly in the workbench iframe, the preview domain must NOT use forward_auth. The auth check interferes with WebSocket connections and causes the iframe to flash/reload every few seconds.

Preview domain Caddy configs must be generated WITHOUT forward_auth to avoid this issue.

Development

# Build
bun run build

# Watch mode
bun run dev

# Type check
bun run type-check

# Run tests
bun run test

Files

packages/alive-tagger/
├── src/
│   ├── index.ts      # Main exports (plugin + utilities)
│   ├── plugin.ts     # Vite plugin
│   ├── client.ts     # Client selection script
│   └── types.ts      # TypeScript types
├── dist/             # Built output
├── package.json
├── tsconfig.json
└── tsup.config.ts

Security Considerations

  1. Development only: Source tagging only active in dev mode
  2. No production impact: Plugin does nothing in production builds
  3. File paths: Relative paths exposed (not full system paths)
  4. node_modules filtered: Library internals not tagged

License

MIT

版本与发布记录

@alive-game/alive-tagger 共发布 6 个版本,首次发布于 2025/12/10;过去 12 个月发布了 6 个版本。

版本发布日期距今
0.2.1latest2026/06/174 个月前
0.2.02026/06/174 个月前
0.1.42026/01/309 个月前
0.1.32025/12/2410 个月前
0.1.12025/12/1010 个月前
0.1.02025/12/1010 个月前

关于 @alive-game/alive-tagger 的常见问题

@alive-game/alive-tagger 是什么?

Element selection and source tagging for Alive workbench

如何安装 @alive-game/alive-tagger?

在项目目录运行 npm install @alive-game/alive-tagger,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=18.0.0)、vite(>=5.0.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@alive-game/alive-tagger 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@alive-game/alive-tagger 支持 ESM 还是 CommonJS?

以 ES Module 形式发布,推荐使用 import 引入。在 CommonJS 项目中,Node.js 20.19+ / 22.12+ 可以直接 require() 不含顶层 await 的 ES Module,更早的版本需要改用动态 import()。

@alive-game/alive-tagger 可以商用吗?

@alive-game/alive-tagger 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@alive-game/alive-tagger 的下载量有多少?

根据 npm 官方下载统计,@alive-game/alive-tagger 在 2026/10/06 – 2026/11/04 这 30 天内被下载 65,457 次,日均约 2,182 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@alive-game/alive-tagger 还在维护吗?

最新版本 0.2.1 发布于 2026/06/17(4 个月前);至今共发布 6 个版本,其中过去 12 个月发布了 6 个;首次发布于 2025/12/10。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。