baoyu-electron-extract

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Electron App Extract

Electron应用提取

Extracts resources and code from an installed Electron app's
app.asar
. When a
.js.map
is present, restores the original source files from the embedded
sourcesContent
; otherwise formats the minified code with Prettier. Source-map paths are resolved relative to the
.js.map
file first, so bundled paths like
../../src/main.ts
restore to readable paths such as
restored/src/main.ts
instead of hashed placeholders. Always skips
node_modules
. Works on macOS and Windows.
可从已安装的Electron应用的
app.asar
文件中提取资源与代码。当存在
.js.map
文件时,会从其嵌入的
sourcesContent
中还原原始源文件;否则使用Prettier格式化压缩后的代码。首先相对于
.js.map
文件的目录解析源映射路径,因此像
../../src/main.ts
这样的打包路径会被还原为
restored/src/main.ts
这类可读路径,而非哈希占位符。始终会跳过
node_modules
目录,支持macOS和Windows系统。

User Input Tools

用户输入工具

When this skill prompts the user, follow this tool-selection rule (priority order):
  1. Prefer built-in user-input tools exposed by the current agent runtime — e.g.,
    AskUserQuestion
    ,
    request_user_input
    ,
    clarify
    ,
    ask_user
    , or any equivalent.
  2. Fallback: if no such tool exists, emit a numbered plain-text message and ask the user to reply with the chosen number/answer for each question.
  3. Batching: if the tool supports multiple questions per call, combine all applicable questions into a single call; if only single-question, ask them one at a time in priority order.
Concrete
AskUserQuestion
references below are examples — substitute the local equivalent in other runtimes.
当该技能需要提示用户时,请遵循以下工具选择规则(优先级顺序):
  1. 优先使用当前Agent运行时提供的内置用户输入工具——例如
    AskUserQuestion
    request_user_input
    clarify
    ask_user
    或任何等效工具。
  2. 备选方案:如果没有此类工具,则输出编号的纯文本消息,要求用户回复所选编号/答案来回答每个问题。
  3. 批量处理:如果工具支持单次调用处理多个问题,则将所有相关问题合并为一次调用;如果仅支持单个问题,则按优先级顺序逐个询问。
以下具体的
AskUserQuestion
引用仅为示例——在其他运行时中请替换为本地等效工具。

Script Directory

脚本目录

Scripts in
scripts/
subdirectory.
{baseDir}
= this SKILL.md's directory path. Resolve
${BUN_X}
runtime: if
bun
installed →
bun
; if
npx
available →
npx -y bun
; else suggest installing bun. Replace
{baseDir}
and
${BUN_X}
with actual values.
ScriptPurpose
scripts/main.ts
App discovery + asar extraction + source-map restoration + Prettier formatting
脚本位于
scripts/
子目录中。
{baseDir}
= 本SKILL.md文件所在的目录路径。解析
${BUN_X}
运行时:若已安装
bun
则使用
bun
;若
npx
可用则使用
npx -y bun
;否则建议安装bun。将
{baseDir}
${BUN_X}
替换为实际值。
脚本用途
scripts/main.ts
应用发现 + asar提取 + 源映射还原 + Prettier格式化

When to use

使用场景

Use this skill whenever the user wants to look inside an installed Electron application or inspect its bundled code. Trigger phrases include:
  • "extract Electron app", "decompile this Electron app", "unpack app.asar"
  • "show me the source of <app>", "look inside <app>", "how is <app> built"
  • "get the source code of Codex / Cursor / Discord / Slack / VS Code / Notion / Obsidian / ChatGPT desktop"
  • "提取 Electron 应用", "看 <app> 的源码", "反编译 Electron", "解包 app.asar", "还原 source map"
Both app name (e.g.,
Codex
) and absolute path (e.g.,
/Applications/Codex.app
, a
.asar
file, or a Windows install dir) are accepted. The script handles discovery for both platforms.
当用户想要查看已安装Electron应用的内部结构或检查其打包代码时,即可使用本技能。触发语句包括:
  • "提取Electron应用"、"反编译该Electron应用"、"解包app.asar"
  • "查看<应用>的源码"、"查看<应用>内部结构"、"<应用>是如何构建的"
  • "获取Codex/Cursor/Discord/Slack/VS Code/Notion/Obsidian/ChatGPT桌面版的源代码"
  • "提取 Electron 应用"、"看 <app> 的源码"、"反编译 Electron"、"解包 app.asar"、"还原 source map"
支持输入应用名称(例如
Codex
)和绝对路径(例如
/Applications/Codex.app
.asar
文件或Windows安装目录)。脚本会处理两个平台的应用发现逻辑。

Workflow

工作流程

1. Determine the input. Ask the user for the app name or path if they haven't given one. If they want a custom output directory, ask for that too.
2. Run the script.
bash
${BUN_X} {baseDir}/scripts/main.ts "<app>" [--output <dir>] [--asar <path>] [--force]
Start with
--dry-run
first if you're unsure whether discovery will find the right bundle — it prints the resolved paths and exits without touching the filesystem.
3. Handle the result.
  • Success → report the output paths and the counts (extracted / restored / formatted).
  • Multiple matches → the script lists candidates and exits non-zero. Show the user the candidates, ask which one to use (via
    AskUserQuestion
    or the runtime equivalent), then re-run with the chosen absolute path.
  • Existing non-empty output dir → the script refuses without
    --force
    . Ask the user whether to overwrite (
    --force
    ) or pick a new
    --output
    path.
  • Unsupported platform / no match → suggest passing
    --asar /full/path/to/app.asar
    if the user knows where the bundle lives.
4. Point the user at the result. The default output dir is
~/Downloads/<AppName>-electron-extract/
. The most interesting subdirectory depends on what was found:
  • restored/
    exists → the original source tree was reconstructed from
    .js.map
    files; this is what to read first.
  • Only
    extracted/
    exists (no maps) → the JS/CSS in
    extracted/
    was Prettier-formatted in place; read from there.
1. 确定输入信息。如果用户未提供应用名称或路径,请询问用户。如果用户需要自定义输出目录,也请询问该目录路径。
2. 运行脚本
bash
${BUN_X} {baseDir}/scripts/main.ts "<app>" [--output <dir>] [--asar <path>] [--force]
如果不确定应用发现能否找到正确的包,可先使用
--dry-run
参数——它会打印解析后的路径,且不会修改文件系统。
3. 处理结果
  • 成功 → 报告输出路径以及统计数据(提取/还原/格式化的文件数量)。
  • 多个匹配结果 → 脚本会列出候选项并以非零状态退出。向用户展示候选项,询问要使用哪一个(通过
    AskUserQuestion
    或运行时等效工具),然后使用所选的绝对路径重新运行脚本。
  • 输出目录已存在且非空 → 脚本在未使用
    --force
    参数时会拒绝执行。询问用户是否要覆盖(使用
    --force
    )或选择新的
    --output
    路径。
  • 不支持的平台/无匹配结果 → 如果用户知道包的位置,建议使用
    --asar /full/path/to/app.asar
    参数指定路径。
4. 引导用户查看结果。默认输出目录为
~/Downloads/<AppName>-electron-extract/
。最值得关注的子目录取决于找到的内容:
  • 若存在
    restored/
    目录 → 说明已从
    .js.map
    文件中重建了原始源码树;优先查看该目录。
  • 仅存在
    extracted/
    目录(无映射文件) →
    extracted/
    中的JS/CSS已通过Prettier格式化;查看该目录即可。

Source-map path restoration

源映射路径还原

The script should preserve original source names and directory structure as much as the source map allows:
  • Resolve each
    sources[]
    entry with
    sourceRoot
    when present, then relative to the
    .js.map
    file's directory inside
    extracted/
    .
  • Collapse normal bundler-relative paths into the restored project tree. For example,
    .vite/main/index.js.map
    +
    ../../src/main.ts
    becomes
    restored/src/main.ts
    .
  • If a source path climbs above
    extracted/
    , keep the readable remaining path under
    restored/
    instead of hashing it. For example,
    .vite/main/index.js.map
    +
    ../../../shared/src/lib/foo.ts
    becomes
    restored/shared/src/lib/foo.ts
    .
  • Strip URL/query decorations from source names, including common
    webpack://
    ,
    file://
    , and
    ?loader
    suffixes.
  • Use
    restored/__unknown/<hash>.<ext>
    only when the source name is empty or cannot be reduced to a safe file path.
  • Continue skipping
    node_modules
    and
    webpack/runtime/*
    entries; these are bundler/runtime noise, not app sources.
脚本应尽可能保留源映射允许的原始源文件名称和目录结构:
  • 当存在
    sourceRoot
    时,先结合它解析每个
    sources[]
    条目,再相对于
    extracted/
    目录中
    .js.map
    文件所在的路径进行解析。
  • 将打包工具生成的相对路径合并到还原后的项目树中。例如,
    .vite/main/index.js.map
    +
    ../../src/main.ts
    会变为
    restored/src/main.ts
  • 如果源路径超出
    extracted/
    目录范围,将可读的剩余路径保留在
    restored/
    目录下,而非使用哈希值。例如,
    .vite/main/index.js.map
    +
    ../../../shared/src/lib/foo.ts
    会变为
    restored/shared/src/lib/foo.ts
  • 移除源名称中的URL/查询参数装饰,包括常见的
    webpack://
    file://
    ?loader
    后缀。
  • 仅当源名称为空或无法转换为安全文件路径时,才使用
    restored/__unknown/<hash>.<ext>
    格式。
  • 继续跳过
    node_modules
    webpack/runtime/*
    条目;这些是打包工具/运行时的冗余内容,而非应用源码。

Usage

使用示例

bash
undefined
bash
undefined

Extract by app name (default output: ~/Downloads/Codex-electron-extract/)

通过应用名称提取(默认输出目录:~/Downloads/Codex-electron-extract/)

${BUN_X} {baseDir}/scripts/main.ts Codex
${BUN_X} {baseDir}/scripts/main.ts Codex

Extract by absolute path (works for .app bundles, install dirs, or .asar files)

通过绝对路径提取(适用于.app包、安装目录或.asar文件)

${BUN_X} {baseDir}/scripts/main.ts "/Applications/Visual Studio Code.app" ${BUN_X} {baseDir}/scripts/main.ts "C:\Users\you\AppData\Local\Programs\codex" ${BUN_X} {baseDir}/scripts/main.ts --asar /Applications/Codex.app/Contents/Resources/app.asar Codex
${BUN_X} {baseDir}/scripts/main.ts "/Applications/Visual Studio Code.app" ${BUN_X} {baseDir}/scripts/main.ts "C:\Users\you\AppData\Local\Programs\codex" ${BUN_X} {baseDir}/scripts/main.ts --asar /Applications/Codex.app/Contents/Resources/app.asar Codex

Custom output

自定义输出目录

${BUN_X} {baseDir}/scripts/main.ts Codex --output ~/work/codex-source
${BUN_X} {baseDir}/scripts/main.ts Codex --output ~/work/codex-source

Preview discovery without writing anything

预览应用发现结果(不写入任何内容)

${BUN_X} {baseDir}/scripts/main.ts Codex --dry-run
${BUN_X} {baseDir}/scripts/main.ts Codex --dry-run

Overwrite an existing output dir

覆盖已存在的输出目录

${BUN_X} {baseDir}/scripts/main.ts Codex --force
${BUN_X} {baseDir}/scripts/main.ts Codex --force

Machine-readable result (one JSON line on stdout)

机器可读结果(标准输出为一行JSON)

${BUN_X} {baseDir}/scripts/main.ts Codex --json
undefined
${BUN_X} {baseDir}/scripts/main.ts Codex --json
undefined

Options

选项说明

OptionShortDescriptionDefault
<app>
App name or absolute path. Required unless
--asar
is given.
--output
-o
Output directory
~/Downloads/<AppName>-electron-extract
--asar
Override the resolved
.asar
path
auto-discovered
--force
-f
Allow writing into a non-empty existing output dirfalse
--skip-format
Skip Prettier formattingfalse
--skip-restore
Skip source-map restorationfalse
--no-unpacked
Don't copy
app.asar.unpacked/
alongside
false
--dry-run
Print resolved paths and exit without writingfalse
--json
Emit one JSON-line summary on stdout (suppresses normal output)false
选项缩写描述默认值
<app>
应用名称或绝对路径。除非指定
--asar
,否则为必填项。
--output
-o
输出目录
~/Downloads/<AppName>-electron-extract
--asar
覆盖自动解析的
.asar
路径
自动发现
--force
-f
允许写入已存在且非空的输出目录false
--skip-format
跳过Prettier格式化false
--skip-restore
跳过源映射还原false
--no-unpacked
不复制
app.asar.unpacked/
目录
false
--dry-run
打印解析后的路径并退出,不修改文件系统false
--json
在标准输出中输出一行JSON格式的摘要(抑制常规输出)false

Output layout

输出目录结构

~/Downloads/<AppName>-electron-extract/
├── extract-report.json          # JSON summary: counts, warnings, resolved paths
├── extracted/                   # raw asar contents (JS/CSS Prettier-formatted when no map)
│   └── ...                      # node_modules left untouched (skipped from format)
├── extracted.unpacked/          # copied from <asar>.unpacked/ if present
│   └── ...                      # native modules (.node), large assets
└── restored/                    # only present if at least one .js.map was usable
    └── <original/source/tree>   # rebuilt from sourcesContent in each .js.map
~/Downloads/<AppName>-electron-extract/
├── extract-report.json          # JSON格式的摘要:统计数据、警告信息、解析后的路径
├── extracted/                   # 原始asar内容(无映射文件时,JS/CSS已通过Prettier格式化)
│   └── ...                      # node_modules目录保持原样(跳过格式化)
├── extracted.unpacked/          # 从<asar>.unpacked/复制而来(若存在)
│   └── ...                      # 原生模块(.node)、大型资源文件
└── restored/                    # 仅当至少有一个.js.map文件可用时才存在
    └── <original/source/tree>   # 从每个.js.map的sourcesContent中重建的目录

Notes

注意事项

  • node_modules is always skipped — both for source-map restoration and Prettier formatting — because vendored dependencies are noise when inspecting an app.
  • Source-map restoration only works when the
    .js.map
    embeds
    sourcesContent
    . This is the common case for modern bundlers (webpack, esbuild, Vite, rollup). If a map references external
    .ts
    /
    .js
    files without embedding them, that map is skipped and the corresponding
    .js
    is Prettier-formatted instead. Skipped maps are listed in
    extract-report.json
    under
    warnings
    .
  • Readable paths over hashes — don't treat
    ../
    segments in source-map paths as automatically unsafe. First resolve them from the map location and then sanitize the final output path so it still stays under
    restored/
    . Hash fallback is only for unusable source names.
  • App discovery searches
    /Applications
    +
    ~/Applications
    on macOS, and
    %LOCALAPPDATA%\Programs
    ,
    %PROGRAMFILES%
    ,
    %PROGRAMFILES(X86)%
    ,
    %APPDATA%
    on Windows. If discovery finds multiple matches, the script exits and lists them — re-run with an absolute path. On Linux or other platforms, pass
    --asar /path/to/app.asar
    explicitly.
  • Safety — the script refuses to write to
    /
    , the user home directly, or the current working directory, and refuses to populate an existing non-empty output dir without
    --force
    .
  • No global installs
    @electron/asar
    and
    prettier
    are resolved on-the-fly via
    npx -y
    . First run will be slower while npx caches them.
  • node_modules目录始终会被跳过——无论是源映射还原还是Prettier格式化都会忽略该目录,因为第三方依赖在检查应用时属于冗余内容。
  • 源映射还原仅在
    .js.map
    文件嵌入
    sourcesContent
    时有效。这是现代打包工具(webpack、esbuild、Vite、rollup)的常见情况。如果映射文件引用外部
    .ts
    /
    .js
    文件但未嵌入内容,则会跳过该映射文件,并对对应的
    .js
    文件进行Prettier格式化。被跳过的映射文件会在
    extract-report.json
    warnings
    字段中列出。
  • 优先使用可读路径而非哈希值——不要将源映射路径中的
    ../
    片段视为自动不安全。先从映射文件所在位置解析路径,然后清理最终输出路径,确保其仍在
    restored/
    目录下。仅当源名称无法使用时才回退到哈希值。
  • 应用发现在macOS上会搜索
    /Applications
    ~/Applications
    目录,在Windows上会搜索
    %LOCALAPPDATA%\Programs
    %PROGRAMFILES%
    %PROGRAMFILES(X86)%
    %APPDATA%
    目录。如果发现多个匹配结果,脚本会退出并列出这些结果——请使用绝对路径重新运行脚本。在Linux或其他平台上,请显式使用
    --asar /path/to/app.asar
    参数指定路径。
  • 安全性——脚本拒绝写入
    /
    目录、用户主目录或当前工作目录,且在未使用
    --force
    参数时拒绝写入已存在且非空的输出目录。
  • 无需全局安装——
    @electron/asar
    prettier
    会通过
    npx -y
    动态解析。首次运行时会较慢,因为npx会缓存这些依赖。