MCPInstall

happy-app-audit

Audit a local macOS app's telemetry / reporting behavior using static analysis only. Reverse-engineers an .app bundle to identify embedded SDKs (AppLog/TEA, Parfait, TTNet, mars, MMKV, Sentry, Firebase, Bugly, Umeng, etc.), mapped upload endpoints, local on-disk queues, and privacy-relevant fields — without packet capture, network requests, debugger attach, or DRM bypass. Use when user asks to investigate, audit, or reverse-engineer a macOS app for telemetry, reporting, data upload, privacy, or SDK fingerprinting. Targets /Applications, /Applications, /Library/Input Methods, /Library/PrivilegedHelperTools, and similar local install paths.

Installs
127
Last 24h
—
Trending rank
—
Security
Not audited

Install

Works with every agent the skills CLI supports.

npx skills add https://github.com/iamzhihuix/happy-claude-skills --skill happy-app-audit
  1. 01

    Install

    Run the command in your project. The CLI asks which agents to install for.

  2. 02

    Describe the task

    Ask your agent for something this skill covers. It loads happy-app-audit automatically when relevant.

  3. 03

    Review the result

    The agent follows the SKILL.md steps, scripts and references bundled with the skill.

SKILL.md

The instructions your agent reads when the skill is triggered.

Happy App Audit

Static-only macOS app telemetry auditor. Produces a markdown report describing what an installed .app bundle reports, to whom, how often (inferred), and what it leaves on disk.

When to invoke

Invoke when the user says any of: "审计 / 调查 / 看看 / 拆 / 逆向 / 上报 / 埋点 / 隐私 / 抓 SDK" combined with a .app path or app name. Also invoke when given paths under /Applications, ~/Applications, /Library/Input Methods, or /Library/PrivilegedHelperTools.

Do NOT invoke for: source-code repos, web sites, mobile (iOS/Android) packages — this skill is macOS-bundle specific.

Hard rules (non-negotiable)

  • Read only. No curl/wget/nc/dig against discovered endpoints. No lldb attach, dtrace, fs_usage, tcpdump, mitmproxy, frida. No Keychain reads. No DRM bypass. No memory dump.
  • Allowed commands only. See references/safe_commands.md. If a step seems to need something outside the whitelist, stop and tell the user instead of improvising.
  • Privacy by default. In every output file, scrub device_id, uid, session_id, email, IDFV, IDFA, JWT, and any 16+ hex blob to <redacted:N> (keep length, drop content).
  • Scope cap. Refuse a single invocation that targets more than 5 apps. Refuse paths under /System/, /usr/libexec/, /private/var/db/com.apple.*. Those are OS components, not third-party telemetry targets.

Runtime

{baseDir} = directory of this SKILL.md.

All scripts are bun + TypeScript. Resolve runtime as: prefer bun in PATH, otherwise npx -y bun. If neither exists, abort with a one-line install hint.

# Smoke check
bun --version  ||  npx --version  ||  echo "Need bun (recommended) or npx"

Workflow — 6 phases, in order

Each phase has: Goal → Inputs → Commands → Output → Stop conditions. Do not skip ahead. Do not interleave.

Phase 0 — Scope confirm

Goal. Lock the target list to ≤5 valid .app paths.

Inputs. Whatever the user said — could be a path, a name, or "the input methods I have installed."

Commands.

  • If user gave a path → verify it exists and ends with .app
  • If user gave a name → search a fixed list:
    /Applications         (depth 2)
    ~/Applications        (depth 2)
    /Library/Input Methods (depth 1)
    /Library/PrivilegedHelperTools  (depth 1)
    
  • Reject anything under /System/, /usr/libexec/, /private/var/db/com.apple.*

Output. A list target_apps[] with absolute paths.

Stop. If the list is empty, ask the user once. If >5, ask which to keep.

Phase 1 — Metadata snapshot

Goal. Per app, capture the immutable surface: bundle id, version, signing, entitlements, network policy, embedded frameworks.

Inputs. target_apps[] from Phase 0.

Commands. Run scripts/snapshot_app.ts:

bun {baseDir}/scripts/snapshot_app.ts <app-path> --out <workdir>/meta.json

The script collects:

  • plutil -p <app>/Contents/Info.plist
  • codesign -dv --entitlements - <app> (stderr)
  • find <app>/Contents/Frameworks -maxdepth 3 -name '*.dylib' -o -name '*.framework'
  • otool -L <main-binary>
  • file <main-binary> for arch
  • Sizes via du -sh

Output. <workdir>/meta.json with: bundle_id, version, sandboxed, arbitrary_loads, ats_exceptions[], entitlements_summary[], frameworks[] (each: name, path, size_bytes, archs).

Stop. If bundle_id cannot be read → abort, app is malformed.

Phase 2 — Strings preprocessing

Goal. Turn raw strings of every embedded binary into bucketed markdown that fits in context.

Inputs. meta.json::frameworks[].

Commands.

bun {baseDir}/scripts/classify_strings.ts <workdir>/meta.json --out <workdir>/strings/

For each binary, the script runs strings -a -n 6 and sorts each line into one of:

  • urls — anything matching https?://
  • domains — bare hostnames
  • paths — /Library/..., ~/Library/..., container-relative paths
  • sql — CREATE TABLE, INSERT INTO, SELECT ... FROM
  • events — looks like an event name (/^[a-z][a-z0-9_]{8,80}$/ with at least one underscore)
  • keys — base64 / hex blobs ≥ 24 chars (kept count + first 12 chars only, never full)
  • noise — discarded

Output. <workdir>/strings/<binary-name>.{urls,domains,paths,sql,events}.md (the keys bucket holds only counts + redacted previews).

Stop. If a binary is >200 MB → skip it and emit a warning line, do not OOM.

Phase 3 — SDK fingerprint matching

Goal. Identify which third-party SDKs are present and how confident.

Inputs. <workdir>/strings/, plus references/sdk_fingerprints.md.

Commands.

bun {baseDir}/scripts/match_fingerprints.ts <workdir>/strings/ \
  --fingerprints {baseDir}/references/sdk_fingerprints.md \
  --out <workdir>/matched.md

The script applies each fingerprint's tell-tale strings regex set to the bucketed strings. A fingerprint counts as confirmed when its min_hits threshold is met (defined per fingerprint).

Output. <workdir>/matched.md with one row per SDK: name, vendor, hits, evidence file lines, status (confirmed / partial / absent).

Stop. If zero fingerprints confirmed AND the app embeds no third-party .framework → write a one-line "no telemetry detected" report and skip Phase 4-5.

Phase 4 — Endpoint mapping

Goal. Build the table that answers "where does it talk to, with what protocol, for what purpose, how often?"

Inputs. <workdir>/strings/*.urls.md + <workdir>/strings/*.domains.md + <workdir>/matched.md + references/known_endpoints.md.

Commands. This phase is mostly Claude reading the files. The only mechanical step:

bun {baseDir}/scripts/match_fingerprints.ts <workdir>/strings/ \
  --fingerprints {baseDir}/references/known_endpoints.md \
  --out <workdir>/endpoints.md

Then Claude writes <workdir>/endpoint_table.md:

EndpointSDKProtocolInferred purposeFrequency source

Frequency source MUST cite either: a literal interval found in <workdir>/strings/, or a config file found in Phase 5, or "unknown — not stated in static evidence." Never guess.

Stop. If endpoints.md is empty but Phase 3 confirmed an SDK → flag in the report (likely runtime-resolved hosts).

Phase 5 — Local data dive

Goal. Inventory the on-disk surface that the app writes to.

Inputs. meta.json::bundle_id, plus references/data_locations.md.

Commands.

bun {baseDir}/scripts/inventory_data.ts <bundle_id> --out <workdir>/local_data.md

The script finds:

  • ~/Library/Application Support/<bundle>/
  • ~/Library/Containers/<bundle>/Data/
  • ~/Library/Group Containers/group.<bundle-prefix>.*/
  • ~/Library/Caches/<bundle>/
  • ~/Library/Preferences/<bundle>.plist
  • ~/Library/Logs/<bundle>/

For each .sqlite* file: sqlite3 <file> '.schema' and .tables only — never SELECT. For each .mmkv / .json config: list path + size, do not open.

Output. <workdir>/local_data.md with: tree of relevant paths, sizes, and SQLite schemas.

Stop. If user is not the file owner → skip with a note (do not prompt sudo).

Phase 6 — Report rendering (+ optional 4:5 card)

Goal. Assemble the user-facing report. Optionally render a 4:5 infographic card for sharing.

Inputs. All prior phase outputs.

Commands.

bun {baseDir}/scripts/render_report.ts <workdir> \
  --template {baseDir}/templates/report.md.tmpl \
  --out ~/Documents/app-telemetry-audit/<YYYY-MM-DD>_<bundle-id>/report.md

When --card is passed to scripts/run.ts, the orchestrator additionally:

  1. Calls lib/card.ts::renderCardPrompt(), which extracts top-6 SDKs (by size, with privacy-hot ones flagged red), top-6 endpoints (preferring endpoints.md confirmed matches with Chinese purpose labels and synthesized proto for quic/-ws. hosts), and top-5 local-data buckets (collapsed by parent dir + note, with DoubaoIme/doubaoime casing variants merged).
  2. Writes the filled prompt to <workdir>/card_prompt.md.
  3. Auto-discovers baoyu-imagine at ~/.claude/skills/baoyu-imagine/scripts/main.ts (or via BAOYU_IMAGINE_SCRIPT env), invokes it with --ar 4:5 --quality 2k defaults, and writes <workdir>/card.png.

Pass --no-image to write only the prompt and skip the image call. Pass any --image-* flag (--image-provider, --image-model, --image-imageSize, etc.) to override the defaults — e.g. --image-provider google --image-model gemini-3-pro-image-preview --image-imageSize 4K for native nano-banana-pro 4K output.

If baoyu-imagine is not installed, Phase 6 still writes card_prompt.md and prints an install hint, but skips the PNG. The skill remains fully functional without it.

Output. Final markdown report. Print its absolute path. If --card, also card_prompt.md and card.png.

Output layout (per app)

~/Documents/app-telemetry-audit/<YYYY-MM-DD>_<bundle-id>/
├── meta.json
├── matched.md
├── endpoints.md
├── endpoint_table.md
├── local_data.md
├── strings/
│   └── <binary>.{urls,domains,paths,sql,events}.md
├── card_prompt.md          # only if --card requested
└── report.md               # the deliverable

Working files (strings/, intermediate *.md) are kept by default — they are the audit trail. Pass --clean to delete them after report.md is written.

Quick start

# Single app, full audit (markdown report only)
bun {baseDir}/scripts/run.ts /Library/Input\ Methods/DoubaoIme.app

# Add a 4:5 share card (prompt + PNG via baoyu-imagine)
bun {baseDir}/scripts/run.ts /Library/Input\ Methods/DoubaoIme.app --card

# Card prompt only — skip image generation
bun {baseDir}/scripts/run.ts /Library/Input\ Methods/DoubaoIme.app --card --no-image

# Card with Google nano-banana-pro at 4K
bun {baseDir}/scripts/run.ts /Library/Input\ Methods/DoubaoIme.app --card \
  --image-provider google \
  --image-model gemini-3-pro-image-preview \
  --image-imageSize 4K

# Multiple apps in one go (capped at 5)
bun {baseDir}/scripts/run.ts /Library/Input\ Methods/DoubaoIme.app /Applications/Foo.app

scripts/run.ts is a thin orchestrator that calls Phases 1→6 in sequence. Use it for the common case. Use individual phase scripts only when iterating.

--card flag surface

FlagPurposeDefault
--cardRender card_prompt.md AND card.pngoff
--no-imageWith --card: write prompt, skip PNGoff
--image-providerbaoyu-imagine provider (google, openai, replicate, dashscope, …)provider auto-selected
--image-modelModel id within the providerprovider default
--image-arAspect ratio4:5
--image-sizeExplicit WxHfrom --image-quality / provider
--image-qualitynormal or 2k2k
--image-imageSizeGoogle/OpenRouter 1K/2K/4Kfrom --image-quality
--outOverride output root~/Documents/app-telemetry-audit/

Any --image-* flag implicitly enables --card.

Relevant references

  • references/safe_commands.md — command whitelist + rationale
  • references/sdk_fingerprints.md — SDK detection rules (12+ SDKs MVP)
  • references/known_endpoints.md — domain → product reverse lookup
  • references/data_locations.md — typical on-disk layout per vendor
  • references/methodology_examples.md — two worked examples (WeType, DoubaoIme)
  • templates/report.md.tmpl — final report skeleton
  • templates/card_prompt.md.tmpl — 4:5 visual card prompt skeleton

Failure modes Claude should NOT do

  • Do not paraphrase strings into "looks like X" without quoting the literal evidence line + file path
  • Do not infer frequencies from SDK names — only from literal numbers in strings or config files
  • Do not run any binary inside the target app
  • Do not open .sqlite content — only schemas
  • Do not write a report when Phase 3 found nothing — write the short "no telemetry detected" note instead
  • Do not invent endpoints from training memory; if the URL is not in <workdir>/strings/, it does not go in the table

Verification (when developing this skill)

Smoke test on /Library/Input Methods/DoubaoIme.app and confirm the report covers:

  • Frameworks: applogrs, Parfait, bytenn, onnxruntime, sscronet, TTNet, ime_net_sdk, sami
  • Endpoints: at least 3 of ime.doubao.com/obric/ime/cloud/convert, log-klink.zijieapi.com, ime-gw.oceancloudapi.com, frontier-audio
  • Local data: ~/Library/Application Support/DoubaoIme/Parfait/ready/685343/0/

Regression: run on the WeType IME bundle and confirm wetype.weixin.qq.com + CACHE_LOG_TBL schema appear.

Negative: run on a small app with no third-party telemetry — must produce the short "no telemetry detected" output without inventing SDKs.

FAQ

What does the happy-app-audit skill do?

Audit a local macOS app's telemetry / reporting behavior using static analysis only. Reverse-engineers an .app bundle to identify embedded SDKs (AppLog/TEA, Parfait, TTNet, mars, MMKV, Sentry, Firebase, Bugly, Umeng, etc.), mapped upload endpoints, local on-disk queues, and privacy-relevant fields — without packet capture, network requests, debugger attach, or DRM bypass. Use when user asks to investigate, audit, or reverse-engineer a macOS app for telemetry, reporting, data upload, privacy, or SDK fingerprinting. Targets /Applications, /Applications, /Library/Input Methods, /Library/PrivilegedHelperTools, and similar local install paths.

How do I install happy-app-audit?

Run npx skills add https://github.com/iamzhihuix/happy-claude-skills --skill happy-app-audit in your project. The skills CLI detects the agents you use and copies the skill into the right folder. For Claude Code you can also place the skill folder at ~/.claude/skills/happy-app-audit/ (personal) or .claude/skills/happy-app-audit/ (project).

Which AI agents can use happy-app-audit?

Any agent that supports the open Agent Skills format (a folder with a SKILL.md file), including Claude Code, Codex, Cursor, GitHub Copilot, Gemini CLI, Windsurf, Cline, OpenCode and more.

Is happy-app-audit safe to install?

No partner security audit is available yet. Skills can run commands and scripts, so read the SKILL.md and any bundled files before installing.

Who maintains happy-app-audit?

It is published by iamzhihuix in iamzhihuix/happy-claude-skills. It has 127 recorded installs.

More from iamzhihuix/happy-claude-skills

View all →

wechat-article-writer

iamzhihuix/happy-claude-skills

公众号文章自动化写作流程。支持资料搜索、文章撰写、爆款标题生成、排版优化。当用户提到写公众号、微信文章、自媒体写作、爆款文章、内容创作时使用此 skill。

Docs & Writing3.3K installs

docx-format-replicator

iamzhihuix/happy-claude-skills

Extract formatting from existing Word documents and generate new documents with the same format but different content. Use this skill when users need to create multiple documents with consistent formatting, replicate document templates, or maintain corporate document standards across different content.

Docs & Writing655 installs

browser

iamzhihuix/happy-claude-skills

Minimal Chrome DevTools Protocol tools for browser automation and scraping. Use when you need to start Chrome, navigate pages, execute JavaScript, take screenshots, or interactively pick DOM elements. Triggers include "browse website", "scrape page", "take screenshot", "automate browser", "extract DOM", "web scraping".

video-processor

iamzhihuix/happy-claude-skills

Download and process videos from YouTube and other platforms. Supports video download, audio extraction, format conversion (mp4, webm), and Whisper transcription. Use when user mentions YouTube download, video conversion, audio extraction, transcription, mp4, webm, ffmpeg, yt-dlp, or whisper transcription.

Media & Creative256 installs

happy-video-gen

iamzhihuix/happy-claude-skills

Open the skill to read its SKILL.md instructions.

Media & Creative163 installs

happy-dreamina

iamzhihuix/happy-claude-skills

Open the skill to read its SKILL.md instructions.

161 installs

Popular security skills

View category →

azure-compliance

microsoft/azure-skills

Run Azure compliance and security audits with azqr plus Key Vault expiration checks. Covers best-practice assessment, resource review, policy/compliance validation, and security posture checks. WHEN: compliance scan, security audit, BEFORE running azqr (compliance cli tool), Azure best practices, Key Vault expiration check, expired certificates, expiring secrets, orphaned resources, compliance assessment.

OfficialSecurity567K installs

minimal-run-and-audit

lllllllama/rigorpilot-skills

Rigor Run skill for README-first deep learning repo reproduction. Use when the task is specifically to capture or normalize evidence from the selected smoke test or documented inference or evaluation command and write standardized reprooutputs/ files, including patch notes when repository files changed. Do not use for training execution, initial repo intake, generic environment setup, paper lookup, target selection, hidden scientific-meaning changes, or end-to-end orchestration by itself.

Security477.4K installs

seo-audit

coreyhaines31/marketingskills

When the user wants to audit, review, or diagnose SEO issues on their site. Also use when the user mentions "SEO audit," "technical SEO," "why am I not ranking," "SEO issues," "on-page SEO," "meta tags review," "SEO health check," "my traffic dropped," "lost rankings," "not showing up in Google," "site isn't ranking," "Google update hit me," "page speed," "core web vitals," "crawl errors," "indexing issues," "stuck on page 2," "striking distance keywords," "title tag rewrite," "low CTR," "local SEO," "Google Business Profile," or "map pack." Use this even if the user just says something vague like "my SEO is bad" or "help with SEO" — start with an audit. For building pages at scale to target keywords, see programmatic-seo. For adding structured data, see schema. For AI search optimization, see ai-seo.

Security238.7K installs

firebase-security-rules-auditor

firebase/agent-skills

Audits Firebase (Firestore, Cloud Storage) security rules for vulnerabilities, privilege escalation, role bypasses, create vs update inconsistencies, resource exhaustion, type safety, size limits, and hasOnly ownership checks. Use when auditing/reviewing rules, running red-team rule assessments, or scoring against auditor checklists. Don't use for Firebase CLI (login, deploy), Auth, Crashlytics, Remote Config, or database queries.

OfficialSecurity139.1K installs

audit

pbakaus/impeccable

Run technical quality checks across accessibility, performance, theming, responsive design, and anti-patterns. Generates a scored report with P0-P3 severity ratings and actionable plan. Use when the user wants an accessibility check, performance audit, or technical quality review.

Security81.9K installs

competitors

coreyhaines31/marketingskills

When the user wants to create competitor comparison or alternative pages for SEO and buyer-facing use. Also use when the user mentions 'alternative page,' 'vs page,' 'competitor comparison,' 'comparison page,' '[Product] vs [Product],' '[Product] alternative,' 'competitive landing pages,' 'how do we compare to X,' 'competitor teardown,' 'audit our competitor pages,' 'are our comparison pages out of date,' or 'competitive asset audit.' Use this for any content that positions your product against competitors. Covers four formats: singular alternative, plural alternatives, you vs competitor, and competitor vs competitor. For auditing existing claims (not researching competitors from scratch, which is competitor-profiling; not technical SEO on these pages, which is seo-audit), use the asset audit here. For internal battle cards and sales-specific competitor docs, see sales-enablement.

Security79.3K installs