CommunityWriting & Editinggithub.com

saidake/code-trace-tree-jetbrains

Code Trace Tree is a VS Code/JetBrains plugin that lets AI agents build nested code workflows as trace points. Add traces from the editor menu or the Agent Skill; double-click to jump to the source.

What is code-trace-tree-jetbrains?

code-trace-tree-jetbrains is a Claude Code agent skill that code Trace Tree is a VS Code/JetBrains plugin that lets AI agents build nested code workflows as trace points. Add traces from the editor menu or the Agent Skill; double-click to jump to the source.

Works withClaude CodeCodex CLICursorGemini CLI
npx skills add saidake/code-trace-tree-jetbrains

Installed? Explore more Writing & Editing skills: steipete/notion, affaan-m/seo, affaan-m/brand-voice · View all 6 →

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Code Trace Tree

Build and display code workflows as nested trees of line, file, and directory trace points. Use the provided Python scripts to operate the hybrid storage used by Code Trace Tree IDE plugins, then ask the IDE to reload.

Only edit or sync traces when the user explicitly asks (for example: generate topic-related nodes, add a tip at a line, rebind after edits). Do not auto-sync every turn. Never delete existing trace points (including ones rebind reports as "invalid") unless the user explicitly asks to remove them.

How to use this skill

Read this SKILL.md only. Do not list, search, or explore this skill's scripts/ or references/ folders, and do not open script source to learn the API. Invoke the documented Python commands by absolute path.

Open scripts/ or references/ only if you hit a critical problem while using the skill (script missing or crashing, storage corrupt, or an error this file does not cover).

Skill scripts location

Helper scripts live under <Agent Skill Path>/code-trace-tree/scripts/.

Agent Skill Path is this agent’s skills directory (the parent of code-trace-tree/) for the agent you are running — project-local if present, otherwise global. It ends at skills, not at code-trace-tree. Paths match npx skills. The table lists common examples; other listed agents work the same.

Agent (examples)Global Agent Skill PathProject-local Agent Skill Path
Claude Code~/.claude/skills<repo>/.claude/skills
Cursor~/.cursor/skills<repo>/.agents/skills
GitHub Copilot~/.copilot/skills<repo>/.agents/skills
Codex~/.codex/skills<repo>/.agents/skills
Gemini CLI~/.gemini/skills<repo>/.agents/skills

On Windows, ~ is %USERPROFILE%. Resolve Agent Skill Path once per session. Invoke scripts with absolute paths via python (or python3 if that is what is on PATH). Keep the process CWD in the IDE project (do not cd into the skill folder). Direct invocations: Trace Tree OPs. On PowerShell, also see Windows PowerShell.

Trace Tree OPs

All skill script calls. Substitute the absolute Agent Skill Path for THIS agent. Keep the process CWD in the IDE project (do not cd into the skill folder). On PowerShell, see Windows PowerShell.

resolve_storage.py

Resolve the project id and bound global XML. If storage is missing, create it (Case C). If .idea/code-trace-tree.project.id exists but XML is gone, recreates XML with that same projectId. Does not create/overwrite the .idea id file. Mutating create_tree and trace_tree add / ensure / move / delete / rebind also create storage automatically. trace_tree search does not auto-create.

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/resolve_storage.py" [project_path]

Optional Parameters:

  • [project_path]: Path used to discover the IDE project root (default: CWD). Pass the project root so XML <path> is correct.

Return value

Stdout is JSON (indent=2, UTF-8). Errors print ERROR: … on stderr.

{
  "created": false,
  "project_root": "<abs>",
  "global_dir": "<OS Config Dir>/code-trace-tree",
  "project_id": "<uuid or null>",
  "storage_xml": "<abs xml path>"
}

created is true when a new XML was written. Exit 0 on success; 1 if the project root cannot be found.

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/resolve_storage.py"
python "<Agent Skill Path>/code-trace-tree/scripts/resolve_storage.py" /path/to/project

create_tree.py

Create a nested trace-point tree in one call. Ensures only the payload roots (and children of roots that already exist). Once a node is created, its descendants are added (no per-child ensure). Do not search if not needed — this script already ensures existing nodes. Use search when you need ids (select/move/delete) or to inspect. LINE locators are the same as trace_tree.py (file + line + content). Ignore line-content occurrence (occurrenceIndex / totalOccurrences) — the script calculates it. Prefer --tree-file on PowerShell.

Optional --parent-id attaches the payload under an existing node (that parent is resolved, not ensured).

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/create_tree.py" --tree-file tree.json
python "<Agent Skill Path>/code-trace-tree/scripts/create_tree.py" tree.json
python "<Agent Skill Path>/code-trace-tree/scripts/create_tree.py" --tree '<json>'

Required Parameters (exactly one tree source):

  • --tree-file <path>: JSON file (- = stdin). Prefer this over --tree.
  • --tree <json>: JSON string.
  • Positional <path>: same as --tree-file.

Parameters (shared; all optional):

  • --project <path>: Project path (default: CWD).
  • --profile <name>: Profile name override (default: <activeProfileName>).
  • --dry-run: Do not write XML or refresh.
  • --no-refresh: Skip the IDE refresh signal.
  • --parent-id <uuid>: Existing parent; repeat rootward → immediate parent. Omit for profile root.
  • --parent <json>: Existing parent path JSON (do not combine with --parent-id).

Tree JSON (one node object, or an array of node objects). Every node uses the same shape, including children (description on every node, not only the root):

{
  "file": "src/A.java",
  "line": 10,
  "content": "void methodA() {",
  "name": "methodA",
  "description": "",
  "type": "LINE",
  "children": [
    {
      "file": "src/B.java",
      "line": 40,
      "content": "void methodB() {",
      "name": "methodB",
      "description": "",
      "type": "LINE",
      "children": [
        {
          "file": "src/C.java",
          "line": 20,
          "content": "void methodC() {",
          "name": "methodC",
          "description": "",
          "type": "LINE"
        },
        {
          "type": "FILE",
          "file": "src/Util.java",
          "name": "Util",
          "description": ""
        }
      ]
    }
  ]
}

Fields (every node, including children): file (required); type (LINE | FILE | DIRECTORY; omit to infer: line/content → LINE, else path on disk); LINE needs line + content; name / description / children optional. Do not include occurrenceIndex / totalOccurrences. children is an array of the same objects.

Return value

Stdout is JSON (indent=2, UTF-8). skipped: true on a node means ensure found it; that node's children are still ensured. created: true means add; descendants of that node were added without ensure.

{
  "action": "create_tree",
  "profile": "<profile-name>",
  "storage_xml": "<abs>",
  "parentId": "<uuid or empty>",
  "created": 3,
  "skipped": 1,
  "ids": ["<uuid>", …],
  "roots": [ { "skipped": false, "created": true, "node": <node-object>, "children": [ … ] } ],
  "refreshed": true
}

Exit 0 on success.

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/create_tree.py" --tree-file tree.json
python "<Agent Skill Path>/code-trace-tree/scripts/create_tree.py" --parent-id "$PARENT_ID" --tree-file tree.json

trace_tree.py

Search, add, ensure, move, delete, and rebind nodes. Ignore line-content occurrence (occurrenceIndex / totalOccurrences) — never pass those fields; the script calculates them.

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" <subcommand> [flags…]
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" [shared-flags] <subcommand> [flags…]

Shared flags (--project, --profile, --dry-run, --no-refresh) may appear before or after the subcommand. Omit --project when CWD is already inside the IDE project (scripts walk upward to find .vscode / .idea / .git, or other common project markers). Default profile: <activeProfileName>.

LINE locators: stored tip is [file, line, full-trimmed-line]. --line is required. The script checks the trimmed text at that line, stores the full trimmed line (a substring --content is expanded), then sets occurrenceIndex / totalOccurrences by scanning the file. Duplicate trimmed lines in one file are distinct because --line picks which copy. Ignore occurrence: do not read, pass, or compute occurrenceIndex / totalOccurrences. On PowerShell, protect quoted --content with --% (see Windows PowerShell) or use a substring tip plus --line. Never wrap the CLI in a helper that uses a parameter named $Args.

TipResult
Exact line + full trimmed textUsed as-is
Distinctive substring of that line (e.g. .handleEmailTriggerRequest()--line required; stores the full trimmed line
Same trimmed text on 2+ linesPass --line for the intended copy; script sets occurrence
Multi-line callPrefer the most distinctive physical line (often the .methodName( continuation)

add vs ensure: add always creates a new UUID (same as the IDE plugin). Use it for a second node on the same line with a different label or parent. ensure is get-or-create: same identity → "skipped": true (exit 0). For LINE, identity is file + trimmed lineContent + the copy selected by --line (the script stores occurrence; do not pass it). FILE/DIRECTORY identity is path + type. --trace-name, description, and parent are not identity.

Generating a tree: prefer create_tree.py. Do not search if not needed — the script ensures existing nodes and adds new subtrees. Use search when you need ids for select/move/delete or to inspect. For a single node, use ensure (get-or-create; no search required) or add (always a new UUID).

Parent path: prefer repeated --parent-id from rootward ancestor → immediate parent. Omit for root on add / ensure. Do not combine --parent-id with --parent. Bare strings inside --parent JSON are UUIDs only, not traceName labels.

--parent formExample
Root--parent [] (needed for move to root; add / ensure default to root)
Node id in JSON--parent '["3d41c2d1-…"]'
[file, line, content]--parent '[["src/A.java",10,"void methodA() {"]]'
method A def
  method B call
    method C call   ← add (or ensure if B already existed) with --parent-id idA --parent-id idB

Rebind after disk edits: Agents do not edit through the IDE editor, so live line shifting does not apply. After any turn that modified project source, run rebind (optionally --file for touched paths) before relying on locators or select/navigate. Rebind repairs lineNumber from trimmed lineContent and recomputes occurrences. The "invalid" array means those LINE locators were not found — leave those nodes in the tree; do not delete them unless the user asked to remove them.

For many mutating calls, use --no-refresh on each, then one request_refresh.py at the end.

Required Subcommand:

  • <subcommand>: search | add | ensure | move | delete | rebind

Parameters (shared; all optional):

  • --project <path>: Project path (default: CWD).
  • --profile <name>: Profile name override (default: <activeProfileName>).
  • --dry-run: Do not write XML or refresh.
  • --no-refresh: Skip the IDE refresh signal.

Parameters (search; all optional):

  • --id <uuid>: Node UUID.
  • --file <path>: Relative file/directory path.
  • --line <n>: 1-based line number.
  • --content <text>: Substring match on lineContent.
  • --trace-name <text>: Substring match on traceName.
  • --type <LINE|FILE|DIRECTORY>: Filter by type.

Parameters (add / ensure):

  • Locator (required): --file + --line + --content for LINE (substring of that line is OK); --file for FILE/DIRECTORY. Or positional FILE LINE CONTENT, or path.
  • --parent-id <uuid> (optional): Parent node UUID; repeat rootward → immediate parent (preferred). Omit for root.
  • --parent <json> (optional): JSON parent path (do not combine with --parent-id).
  • --trace-name <text> (optional): Trace point label.
  • --description <text> (optional): Description.
  • --type <LINE|FILE|DIRECTORY> (optional): Type override (default: LINE).

Parameters (move):

  • Locator (required): --id, or --file + --line + --content, or --file alone for FILE/DIRECTORY.
  • New parent (required): --parent-id (repeat rootward → immediate parent) or --parent JSON. For root, use --parent []. Do not combine --parent-id with --parent.

Parameters (delete):

  • Locator (required): --id, or --file + --line + --content, or --file alone for FILE/DIRECTORY.

Parameters (rebind; all optional):

  • --file <path>: Limit to relative path(s); repeatable. Default: all LINE nodes in the profile.

Return value

Stdout is JSON (indent=2, UTF-8). Errors print ERROR: … on stderr and exit nonzero.

node-object:

{
  "id": "<uuid>",
  "parentId": "<uuid or empty>",
  "type": "LINE|FILE|DIRECTORY",
  "file": "<relative path>",
  "line": "<n or empty>",
  "content": "<trimmed lineContent>",
  "name": "<traceName>",
  "depth": 0,
  "childCount": 0
}

search:

{
  "project_root": "<abs>",
  "storage_xml": "<abs>",
  "profile": "<profile-name>",
  "matches": [ <node-object>, … ]
}

add (always created; no "skipped"):

{
  "action": "add",
  "profile": "<profile-name>",
  "storage_xml": "<abs>",
  "parentId": "<uuid or empty>",
  "node": <node-object>,
  "refreshed": true,
  "resolve": <resolve-object>
}

ensure (created):

{
  "action": "ensure",
  "skipped": false,
  "profile": "<profile-name>",
  "storage_xml": "<abs>",
  "parentId": "<uuid or empty>",
  "node": <node-object>,
  "refreshed": true,
  "resolve": <resolve-object>
}

ensure (already present, exit 0):

{
  "action": "ensure",
  "skipped": true,
  "reason": "already_exists",
  "profile": "<profile-name>",
  "id": "<uuid>",
  "parentId": "<uuid or empty>",
  "node": <node-object>,
  "resolve": <resolve-object>
}

resolve-object (LINE only; omitted for FILE/DIRECTORY):

{
  "reason": "<exact|substring_on_line>",
  "needle": "<passed --content>",
  "resolved": ["<file>", <line>, "<full trimmed line>"],
  "totalOccurrences": 1,
  "occurrenceIndex": 1
}

move:

{
  "action": "move",
  "profile": "<profile-name>",
  "id": "<uuid>",
  "newParentId": "<uuid or empty>",
  "refreshed": true
}

delete:

{
  "action": "delete",
  "profile": "<profile-name>",
  "deletedIds": ["<uuid>", …],
  "refreshed": true
}

rebind:

{
  "action": "rebind",
  "dry_run": false,
  "profile": "<profile-name>",
  "storage_xml": "<abs>",
  "updated": [ <rebind-row-object>, … ],
  "invalid": [ <rebind-row-object>, … ],
  "unchanged": 0,
  "refreshed": true
}

rebind-row-object:

{
  "id": "<uuid>",
  "file": "<relative path>",
  "oldLine": 10,
  "newLine": 12,
  "content": "<trimmed lineContent>",
  "totalOccurrences": 1,
  "occurrenceIndex": 1,
  "reason": "<exact|moved|refresh_occurrences|…>"
}

--dry-run adds "dry_run": true and does not write XML / refresh. Exit 0 on success (including skipped ensure). add never skips. Rebind "invalid" is a locator status, not a delete list.

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" search
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" search --project /path/to/project
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" --project /path/to/project search
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" ensure --file src/A.java --line 42 --content '.handleEmailTriggerRequest(' --trace-name 'handleEmail'
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" ensure --file src/A.java --line 10 --content 'void methodA() {' --trace-name 'methodA'
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" ensure src/B.java 40 'void methodB() {' \
  --parent-id "$PARENT_ID" \
  --trace-name 'methodB'
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" ensure --file src/C.java --line 20 --content 'void methodC() {' \
  --parent-id "$ID_A" --parent-id "$ID_B" --trace-name 'methodC'
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" add --file src/A.java --line 10 --content 'void methodA() {' --trace-name 'methodA alt'
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" move --file src/B.java --line 40 --content 'void methodB() {' --parent '[]'
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" move --id "$NODE_ID" --parent []
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" delete --id <uuid>
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" rebind
python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" rebind --file src/A.java --file src/B.java

request_refresh.py

Ask the IDE to fully reload Code Trace Tree storage (all profiles + toolbar flags). Also writes storage-ready. After agent edits, always write a refresh signal (the plugin does not watch the XML file).

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh.py" [project_path]

Optional Parameters:

  • [project_path]: Path used to discover the IDE project root (default: CWD).

Return value

Stdout is JSON (indent=2, UTF-8):

{ "ok": true }

Exit 0 on success; 1 if the project root cannot be found; 2 if there is no bound project id (ERROR on stderr).

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh.py"

request_refresh_profile.py

Reload one profile’s tree from XML into memory. Does not change active profile or toolbar flags. Also writes storage-ready. Structure ops (add / ensure / move / delete / rebind) emit this.

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh_profile.py" [project_path] [profile_name]
python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh_profile.py" [profile_name]

With one argument: a path (exists, or contains / \) is treated as project_path; otherwise it is profile_name. Omitted or empty profile → IDE refreshes its current active profile.

Optional Parameters:

  • [project_path]: Path used to discover the IDE project root (default: CWD).
  • [profile_name]: Profile to reload (default: active).

Return value

Stdout is JSON (indent=2, UTF-8). profile is null when reloading the active profile.

{ "profile": "<profile-name or null>" }

Exit 0 on success; 1 if the project root cannot be found; 2 if there is no bound project id (ERROR on stderr).

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh_profile.py" main
python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh_profile.py" /path/to/project main

request_refresh_settings.py

Reload project toolbar flags / activeProfileName only (not profile trees or global highlight colors).

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh_settings.py" [project_path]

Optional Parameters:

  • [project_path]: Path used to discover the IDE project root (default: CWD).

Return value

Stdout is JSON (indent=2, UTF-8):

{ "ok": true }

Exit 0 on success; 1 if there is no bound project id (ERROR on stderr).

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/request_refresh_settings.py"

select_trace_points.py

Write node UUIDs to the select signal. Every open IDE window for that project selects / reveals those nodes. Prefer a single id when you want the editor to jump to the source. Uses CWD to discover the project root.

RequestTreeEditor
1 valid idSelect + revealNavigate to source
2+ valid idsSelect + reveal allNo navigation
Unknown ids onlyNo-opNo navigation

Usage

python "<Agent Skill Path>/code-trace-tree/scripts/select_trace_points.py" <id> [id...]

Required Parameters:

  • <id>: Trace point node UUID (one or more).

Return value

Stdout is JSON (indent=2, UTF-8):

{ "ids": ["<uuid>", …] }

Exit 0 on success; 1 if no ids were passed or the project root cannot be found; 2 if there is no bound project id (ERROR on stderr).

Example:

python "<Agent Skill Path>/code-trace-tree/scripts/select_trace_points.py" 3d41c2d1-…

Windows PowerShell

Prefer invoking python …/trace_tree.py directly (or via cmd /c). Do not wrap calls in a PowerShell helper that uses a parameter named $Args — that overwrites PowerShell’s automatic $Args, so real CLI args never reach the script and every call fails with the following arguments are required: command.

Quoting: inner " in --content (and similar flags) are often stripped — e.g. @PostMapping("/testPost") arrives as @PostMapping(/testPost), so LINE matching fails even with a correct --line. Insert --% (stop-parsing) after the script path and before those flags. --% is PowerShell-only (not cmd.exe / bash / Git Bash).

python "<Agent Skill Path>/code-trace-tree/scripts/trace_tree.py" --% add --file src/A.java --line 38 --content "@PostMapping(\"/testPost\")" --trace-name testPost

Fallback when quotes are still awkward: distinctive substring tip + --line (e.g. --content "@PostMapping(" --line 38).

Deep nests: prefer create_tree.py --tree-file (one write, one refresh). For one-off nodes, repeated --parent-id on add / ensure (rootward → parent). For many individual mutating calls, use --no-refresh on each, then one request_refresh.py at the end. If PowerShell quoting remains fragile, write tree JSON to a file rather than --tree. Do not replace the skill scripts.

Console encoding: trace_tree.py reconfigures stdout/stderr to UTF-8. If the console is still legacy (cp1252) or a wrapper interferes, set $env:PYTHONIOENCODING = "utf-8" for the session. Prefer ASCII (or simple Latin) for --trace-name / descriptions when the console is not UTF-8, so JSON status output cannot fail the process after a successful write.

Preferred code workflow format

  • When generating a code workflow, nest by call flow: start from an entry method definition; under it put the calls made inside that method; under each call nest further calls made inside the callee (siblings for fan-out). Prefer call nesting over inserting a separate definition node for every hop. Pass that nest to create_tree.py. Do not search if not needed; do not ensure each child yourself.

    Example:

    method A definition
      - method B call
        - method C call  (inside B)
        - method D call  (inside B)
    
  • Keep trace point names simple and concise. Add descriptions only when additional context is needed.

  • Prefer LINE anchors whose trimmed text is unique (or rare) in that file. Avoid generic lines such as }, return;, or blank-looking braces. Duplicate content in the same file makes rebinding fragile; distinguish copies with --line only (ignore occurrence fields).

  • For multi-line calls, pass --line and a distinctive substring of that physical line (e.g. .handleEmailTriggerRequest(); the script stores the full trimmed line. Do not invent a logical “call name” that is not on one source line.

Edit plugin data action

Prefer scripts (Trace Tree OPs). Do not create .idea/code-trace-tree.project.id.

  1. Resolve (creates if missing): resolve_storage.py. Mutating trace_tree / create_tree also auto-init.
  2. Mutate: prefer create_tree.py for a nested workflow (do not search if not needed). Use trace_tree.py (search / add / ensure / move / delete / rebind) for inspect and single-node ops. Use delete only when the user asked to remove nodes (never to “clean up” invalid tips or to replace a tree).
  3. Refresh is automatic on mutating trace_tree calls unless --no-refresh. For a batch, use --no-refresh on each then one request_refresh.py. Settings-only: request_refresh_settings.py. One profile without a structure op: request_refresh_profile.py.

If a skill op fails in a way this file does not cover, then read references/data-format.md. Do not open it otherwise.

Select / navigate in the IDE action

Use select_trace_points.py (Trace Tree OPs) after creating or locating traces when the user should see them in the IDE. Prefer a single id when you want the editor to jump to the source.

RequestTreeEditor
1 valid idSelect + revealNavigate to source
2+ valid idsSelect + reveal allNo navigation
Unknown ids onlyNo-opNo navigation

Additional resources

Do not open these during normal use. Only if a skill op fails in a way this file does not cover: references/data-format.md.

Related Skills

steipete/notion

Notion CLI/API for pages, Markdown content, data sources, files, comments, search, Workers, and raw API calls.

community

affaan-m/seo

Audit, plan, and implement SEO improvements across technical SEO, on-page optimization, structured data, Core Web Vitals, and content strategy. Use when the user wants better search visibility, SEO remediation, schema markup, sitemap/robots work, or keyword mapping.

community

affaan-m/brand-voice

Build a source-derived writing style profile from real posts, essays, launch notes, docs, or site copy, then reuse that profile across content, outreach, and social workflows. Use when the user wants voice consistency without generic AI writing tropes.

community

affaan-m/crosspost

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

community

affaan-m/x-api

X/Twitter API integration for posting tweets, threads, reading timelines, search, and analytics. Covers OAuth auth patterns, rate limits, and platform-native content posting. Use when the user wants to interact with X programmatically.

community

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

community