{"id":"41c193c9-29af-48a0-bdd3-8b48330a3767","entityType":"agent","slug":"clawhub-jhauga-adobe-illustrator-scripting","name":"Adobe Illustrator Scripting","canonicalUrl":"https://www.xpersona.co/agent/clawhub-jhauga-adobe-illustrator-scripting","canonicalPath":"/agent/clawhub-jhauga-adobe-illustrator-scripting","generatedAt":"2026-10-10T17:33:20.277Z","source":"CLAWHUB","claimStatus":"UNCLAIMED","verificationTier":"NONE","summary":{"evidence":{"source":"editorial-content","verified":true,"confidence":"high","updatedAt":"2026-10-10T14:58:49.521Z","emptyReason":null},"description":"Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d... Skill: Adobe Illustrator Scripting Owner: jhauga Summary: Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d... Tags: latest:1.0.2 Version history: v1.0.2 | 2026-05-27T20:58:33.752Z | user - Added note on \"External invocation\" to scripting environment section, describing how scripts can be launched from outside","descriptionLabel":"Technical summary","evidenceSummary":"Capability contract not published. No trust telemetry is available yet. 1.4K downloads reported by the source. Last updated 10/10/2026.","installCommand":"clawhub skill install s17ch25466qc0g2bcymk2dr8zx83pfny:adobe-illustrator-scripting","sourceUrl":"https://clawhub.ai/jhauga/adobe-illustrator-scripting","homepage":"https://clawhub.ai/jhauga/skills/adobe-illustrator-scripting","primaryLinks":[{"label":"View on ClawHub","url":"https://clawhub.ai/jhauga/adobe-illustrator-scripting","kind":"source"},{"label":"Homepage","url":"https://clawhub.ai/jhauga/skills/adobe-illustrator-scripting","kind":"homepage"}],"safetyScore":84,"overallRank":62,"popularityScore":63,"trustScore":null,"claimedByName":null,"isOwner":false,"seoDescription":"Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d..."},"coverage":{"evidence":{"source":"public-profile","verified":false,"confidence":"medium","updatedAt":"2026-10-10T14:58:49.521Z","emptyReason":null},"protocols":[{"protocol":"OPENCLEW","label":"OpenClaw","status":"self-declared","notes":"Declared in the public agent profile."}],"capabilities":[],"verifiedCount":0,"selfDeclaredCount":1,"capabilityMatrix":{"rows":[{"key":"OPENCLEW","type":"protocol","support":"unknown","confidenceSource":"profile","notes":"Listed on profile"}],"flattenedTokens":"protocol:OPENCLEW|unknown|profile"}},"adoption":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T14:58:49.521Z","emptyReason":null},"stars":null,"forks":null,"downloads":1372,"packageName":null,"latestVersion":"1.0.2","tractionLabel":"1.4K downloads"},"release":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"medium","updatedAt":"2026-10-10T14:58:49.455Z","emptyReason":null},"lastUpdatedAt":"2026-10-10T14:58:49.521Z","lastCrawledAt":"2026-10-10T14:58:49.455Z","lastIndexedAt":null,"nextCrawlAt":"2026-10-11T14:58:49.455Z","lastVerifiedAt":null,"highlights":[{"version":"1.0.2","createdAt":"2026-05-27T20:58:33.752Z","changelog":"- Added note on \"External invocation\" to scripting environment section, describing how scripts can be launched from outside Illustrator (e.g., shell scripts, CI jobs, ExtendScript Toolkit, BridgeTalk). - Linked to \"External Invocation & Argument Passing\" for further details. - No other content changes.","fileCount":7,"zipByteSize":18563},{"version":"1.0.1","createdAt":"2026-04-19T23:52:39.824Z","changelog":"- Added a Bundled Assets section documenting a new quick-reference guide for the Illustrator object model and a scripts directory with example automation scripts. - Clarified usage of reference materials and examples to support script development and debugging. - No changes to core scripting usage or technical guides.","fileCount":6,"zipByteSize":12866},{"version":"1.0.0","createdAt":"2026-04-19T21:56:51.558Z","changelog":"Initial release of Adobe Illustrator Scripting skill. - Provides comprehensive guidance for automating Illustrator with ExtendScript (JavaScript/JSX). - Covers the Illustrator scripting object model, key objects, properties, and methods. - Includes best practices for writing and debugging production-quality `.jsx` scripts. - Details measurement units, coordinate systems, and common tasks such as creating, saving, and exporting documents. - Offers examples for manipulating layers, paths, shapes, and working with batch processes or print workflows.","fileCount":6,"zipByteSize":12627}]},"execution":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No published capability contract is available yet."},"installCommand":"clawhub skill install s17ch25466qc0g2bcymk2dr8zx83pfny:adobe-illustrator-scripting","setupComplexity":"low","setupSteps":["Setup complexity is LOW. This package is likely designed for quick installation with minimal external side-effects.","Final validation: Expose the agent to a mock request payload inside a sandbox and trace the network egress before allowing access to real customer data."],"contract":{"contractStatus":"missing","authModes":[],"requires":[],"forbidden":[],"supportsMcp":false,"supportsA2a":false,"supportsStreaming":false,"inputSchemaRef":null,"outputSchemaRef":null,"dataRegion":null,"contractUpdatedAt":null,"sourceUpdatedAt":null,"freshnessSeconds":null},"invocationGuide":{"preferredApi":{"snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/trust"},"curlExamples":["curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/snapshot\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/contract\"","curl -s \"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/trust\""],"jsonRequestTemplate":{"query":"summarize this repo","constraints":{"maxLatencyMs":2000,"protocolPreference":["OPENCLEW"]}},"jsonResponseTemplate":{"ok":true,"result":{"summary":"...","confidence":0.9},"meta":{"source":"CLAWHUB","generatedAt":"2026-10-10T17:33:20.275Z"}},"retryPolicy":{"maxAttempts":3,"backoffMs":[500,1500,3500],"retryableConditions":["HTTP_429","HTTP_503","NETWORK_TIMEOUT"]}},"endpoints":{"dossierUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/dossier","snapshotUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/snapshot","contractUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/contract","trustUrl":"https://www.xpersona.co/api/v1/agents/clawhub-jhauga-adobe-illustrator-scripting/trust"}},"reliability":{"evidence":{"source":"runtime-metrics","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No trust, reliability, or runtime telemetry is available."},"trust":{"status":"unavailable","handshakeStatus":"UNKNOWN","verificationFreshnessHours":null,"reputationScore":null,"p95LatencyMs":null,"successRate30d":null,"fallbackRate":null,"attempts30d":null,"trustUpdatedAt":null,"trustConfidence":"unknown","sourceUpdatedAt":null,"freshnessSeconds":null},"decisionGuardrails":{"doNotUseIf":["Contract metadata is missing or unavailable for deterministic execution."],"safeUseWhen":[],"riskFlags":["missing_or_unavailable_contract","trust_data_unavailable","schema_references_missing"],"operationalConfidence":"low"},"executionMetrics":{"observedLatencyMsP50":null,"observedLatencyMsP95":null,"estimatedCostUsd":null,"uptime30d":null,"rateLimitRpm":null,"rateLimitBurst":null,"lastVerifiedAt":null,"verificationSource":null},"runtimeMetrics":{"successRate":null,"avgLatencyMs":null,"avgCostUsd":null,"hallucinationRate":null,"retryRate":null,"disputeRate":null,"p50Latency":null,"p95Latency":null,"lastUpdated":null}},"benchmarks":{"evidence":{"source":"no-benchmark-data","verified":false,"confidence":"low","updatedAt":null,"emptyReason":"No benchmark suites or observed failure patterns are available."},"suites":[],"failurePatterns":[]},"artifacts":{"evidence":{"source":"CLAWHUB","verified":false,"confidence":"high","updatedAt":"2026-10-10T14:58:49.521Z","emptyReason":null},"readme":"Skill: Adobe Illustrator Scripting\n\nOwner: jhauga\n\nSummary: Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d...\n\nTags: latest:1.0.2\n\nVersion history:\n\nv1.0.2 | 2026-05-27T20:58:33.752Z | user\n\n- Added note on \"External invocation\" to scripting environment section, describing how scripts can be launched from outside Illustrator (e.g., shell scripts, CI jobs, ExtendScript Toolkit, BridgeTalk).\n- Linked to \"External Invocation & Argument Passing\" for further details.\n- No other content changes.\n\nv1.0.1 | 2026-04-19T23:52:39.824Z | user\n\n- Added a Bundled Assets section documenting a new quick-reference guide for the Illustrator object model and a scripts directory with example automation scripts.\n- Clarified usage of reference materials and examples to support script development and debugging.\n- No changes to core scripting usage or technical guides.\n\nv1.0.0 | 2026-04-19T21:56:51.558Z | user\n\nInitial release of Adobe Illustrator Scripting skill.\n\n- Provides comprehensive guidance for automating Illustrator with ExtendScript (JavaScript/JSX).\n- Covers the Illustrator scripting object model, key objects, properties, and methods.\n- Includes best practices for writing and debugging production-quality `.jsx` scripts.\n- Details measurement units, coordinate systems, and common tasks such as creating, saving, and exporting documents.\n- Offers examples for manipulating layers, paths, shapes, and working with batch processes or print workflows.\n\nArchive index:\n\nArchive v1.0.2: 7 files, 18563 bytes\n\nFiles: references/object-model-quick-reference.md (5013b), scripts/batch-export-png.jsx (1339b), scripts/create-color-grid.jsx (1146b), scripts/find-replace-text.jsx (893b), skill-card.md (2639b), SKILL.md (35264b), _meta.json (146b)\n\nFile v1.0.2:SKILL.md\n\n---\nname: adobe-illustrator-scripting\ndescription: 'Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate documents, layers, paths, text frames, colors, symbols, artboards, or any Illustrator DOM objects. Covers the complete JavaScript object model, coordinate system, measurement units, export workflows, and scripting best practices.'\n---\n\n# Adobe Illustrator Scripting\n\nExpert guidance for automating Adobe Illustrator through ExtendScript (JavaScript/JSX). This skill covers the Illustrator scripting object model, all major API objects, code patterns, and best practices for writing production-quality `.jsx` scripts.\n\n## Bundled Assets\n\n- [`references/object-model-quick-reference.md`](references/object-model-quick-reference.md): Use this as a quick lookup for the Illustrator scripting object model, common document and page item types, and related DOM concepts while writing or debugging scripts.\n- `scripts/`: Contains example Illustrator automation scripts you can use as starting points or implementation patterns for common tasks such as document manipulation, exports, batch processing, and DOM usage. Review and adapt these examples when you need working JSX patterns or want to compare behavior while debugging.\n## When to Use This Skill\n\n- Writing new Illustrator automation scripts (`.jsx` or `.js` files)\n- Debugging or fixing existing Illustrator ExtendScript code\n- Manipulating documents, layers, page items, paths, text, or colors programmatically\n- Batch-processing Illustrator files or generating artwork from data\n- Exporting documents to various formats (PDF, SVG, PNG, EPS, etc.)\n- Working with the Illustrator DOM (Application, Document, Layer, PathItem, TextFrame, etc.)\n- Creating data-driven graphics using variables and datasets\n- Automating print workflows with scripted print options\n\n## Prerequisites\n\n- Adobe Illustrator CC or later installed\n- Basic JavaScript knowledge (ExtendScript is ES3-based with Adobe extensions)\n- Scripts are executed via File > Scripts > Other Scripts, the Scripts menu, or placed in the Startup Scripts folder\n- The ExtendScript Toolkit (ESTK) or any text editor can be used to write `.jsx` files\n\n## Scripting Environment\n\n### Language and File Extensions\n\n| Language | Extension | Platform |\n|---|---|---|\n| ExtendScript/JavaScript | `.jsx`, `.js` | Windows, macOS |\n| AppleScript | `.scpt` | macOS only |\n| VBScript | `.vbs` | Windows only |\n\n**This skill focuses on ExtendScript/JavaScript** as the cross-platform, most widely used option.\n\n### Executing Scripts\n\n- **Scripts menu**: File > Scripts lists scripts from the application scripts folder\n- **Other Scripts**: File > Scripts > Other Scripts to browse and run any `.jsx` file\n- **Startup Scripts**: Place scripts in the Startup Scripts folder to run automatically on launch\n- **Target directive**: Begin scripts with `#target illustrator` when running from ESTK or external tools\n- **`#targetengine` directive**: Use `#targetengine \"session\"` to persist variables across script executions\n- **External invocation**: Scripts are frequently launched from outside Illustrator — by shell scripts, task runners, CI jobs, ExtendScript Toolkit (`ExtendScript Toolkit.exe -run script.jsx`), or `BridgeTalk` messages from other Adobe apps. See [External Invocation & Argument Passing](#external-invocation--argument-passing).\n\n### Naming Conventions (JavaScript)\n\n- Objects and properties use **camelCase**: `activeDocument`, `pathItems`, `textFrames`\n- The `app` global references the `Application` object\n- Collection indices are **zero-based**: `documents[0]` is the frontmost document\n- Use `typename` property to identify object types at runtime\n\n## Object Model Overview\n\nThe Illustrator DOM follows a strict containment hierarchy:\n\n```\nApplication (app)\n├── activeDocument / documents[]\n│   ├── layers[]\n│   │   ├── pageItems[] (all artwork)\n│   │   ├── pathItems[]\n│   │   ├── compoundPathItems[]\n│   │   ├── textFrames[]\n│   │   ├── placedItems[]\n│   │   ├── rasterItems[]\n│   │   ├── meshItems[]\n│   │   ├── pluginItems[]\n│   │   ├── graphItems[]\n│   │   ├── symbolItems[]\n│   │   ├── nonNativeItems[]\n│   │   ├── legacyTextItems[]\n│   │   └── groupItems[]\n│   ├── artboards[]\n│   ├── views[]\n│   ├── selection (array of selected items)\n│   ├── swatches[], spots[], gradients[], patterns[]\n│   ├── graphicStyles[], brushes[], symbols[]\n│   ├── textFonts[] (via app.textFonts)\n│   ├── stories[], characterStyles[], paragraphStyles[]\n│   ├── variables[], datasets[]\n│   └── inkList[], printOptions\n├── preferences\n├── printerList[]\n└── textFonts[]\n```\n\n### Top-Level Objects\n\n- **Application** (`app`): The root object. Provides access to documents, preferences, fonts, and printers. Key properties: `activeDocument`, `documents`, `textFonts`, `printerList`, `userInteractionLevel`, `version`.\n- **Document**: Represents an open `.ai` file. Key properties: `layers`, `pageItems`, `selection`, `activeLayer`, `width`, `height`, `rulerOrigin`, `documentColorSpace`. Key methods: `saveAs()`, `exportFile()`, `close()`, `print()`.\n- **Layer**: A drawing layer. Key properties: `pageItems`, `pathItems`, `textFrames`, `visible`, `locked`, `opacity`, `name`, `zOrderPosition`, `color`.\n\n## Measurement Units and Coordinates\n\n### Units\n\nAll scripting API values use **points** (72 points = 1 inch). Convert other units:\n\n| Unit | Conversion |\n|---|---|\n| Inches | multiply by 72 |\n| Centimeters | multiply by 28.346 |\n| Millimeters | multiply by 2.834645 |\n| Picas | multiply by 12 |\n\nKerning, tracking, and `aki` properties use **em units** (thousandths of an em, proportional to font size).\n\n### Coordinate System\n\n- For **scripted documents**, the origin `(0,0)` is at the **bottom-left** of the artboard\n- X increases left to right; Y increases bottom to top\n- The `position` property of a page item is the **top-left corner** of its bounding box as `[x, y]`\n- Maximum page item width/height: 16348 points\n\n### Art Item Bounds\n\nEvery page item has three bounding rectangles:\n\n- `geometricBounds`: Excludes stroke width `[left, top, right, bottom]`\n- `visibleBounds`: Includes stroke width\n- `controlBounds`: Includes control/direction points\n\n## Working with Documents\n\n### Creating and Opening\n\n```javascript\n// Create a new document\nvar doc = app.documents.add();\n\n// Create with a preset\nvar preset = new DocumentPreset();\npreset.width = 612;  // 8.5 inches\npreset.height = 792; // 11 inches\npreset.colorMode = DocumentColorSpace.CMYK;\nvar doc = app.documents.addDocument(\"Print\", preset);\n\n// Open an existing file\nvar fileRef = new File(\"/path/to/file.ai\");\nvar doc = app.open(fileRef);\n```\n\n### Saving and Exporting\n\n```javascript\n// Save as Illustrator format\nvar saveOpts = new IllustratorSaveOptions();\nsaveOpts.compatibility = Compatibility.ILLUSTRATOR17; // CC\ndoc.saveAs(new File(\"/path/to/output.ai\"), saveOpts);\n\n// Export as PDF\nvar pdfOpts = new PDFSaveOptions();\npdfOpts.compatibility = PDFCompatibility.ACROBAT7;\npdfOpts.preserveEditability = false;\ndoc.saveAs(new File(\"/path/to/output.pdf\"), pdfOpts);\n\n// Export as PNG\nvar pngOpts = new ExportOptionsPNG24();\npngOpts.horizontalScale = 300;\npngOpts.verticalScale = 300;\npngOpts.transparency = true;\ndoc.exportFile(new File(\"/path/to/output.png\"), ExportType.PNG24, pngOpts);\n\n// Export as SVG\nvar svgOpts = new ExportOptionsSVG();\nsvgOpts.fontType = SVGFontType.OUTLINEFONT;\ndoc.exportFile(new File(\"/path/to/output.svg\"), ExportType.SVG, svgOpts);\n```\n\n## Working with Paths and Shapes\n\n### Built-in Shape Methods\n\nThe `pathItems` collection provides convenience methods for common shapes:\n\n```javascript\nvar doc = app.activeDocument;\nvar layer = doc.activeLayer;\n\n// Rectangle: rectangle(top, left, width, height)\nvar rect = layer.pathItems.rectangle(500, 100, 200, 150);\n\n// Rounded rectangle: roundedRectangle(top, left, width, height, hRadius, vRadius)\nvar rrect = layer.pathItems.roundedRectangle(500, 100, 200, 150, 20, 20);\n\n// Ellipse: ellipse(top, left, width, height)\nvar oval = layer.pathItems.ellipse(400, 200, 100, 100);\n\n// Polygon: polygon(centerX, centerY, radius, sides)\nvar hex = layer.pathItems.polygon(300, 300, 50, 6);\n\n// Star: star(centerX, centerY, radius, innerRadius, points)\nvar star = layer.pathItems.star(300, 300, 50, 25, 5);\n```\n\n### Freeform Paths Using Coordinate Arrays\n\n```javascript\nvar doc = app.activeDocument;\nvar path = doc.pathItems.add();\npath.setEntirePath([[100, 100], [200, 200], [300, 100]]);\npath.closed = false;\npath.stroked = true;\npath.strokeWidth = 2;\n```\n\n### Freeform Paths Using PathPoint Objects\n\n```javascript\nvar doc = app.activeDocument;\nvar path = doc.pathItems.add();\n\nvar point1 = path.pathPoints.add();\npoint1.anchor = [100, 100];\npoint1.leftDirection = [100, 100];\npoint1.rightDirection = [150, 150];\npoint1.pointType = PointType.SMOOTH;\n\nvar point2 = path.pathPoints.add();\npoint2.anchor = [300, 100];\npoint2.leftDirection = [250, 150];\npoint2.rightDirection = [300, 100];\npoint2.pointType = PointType.SMOOTH;\n\npath.closed = false;\n```\n\n### Path Properties\n\n```javascript\nvar item = doc.pathItems[0];\nitem.filled = true;\nitem.stroked = true;\nitem.strokeWidth = 1.5;\nitem.strokeCap = StrokeCap.ROUNDENDCAP;\nitem.strokeJoin = StrokeJoin.ROUNDENDJOIN;\nitem.opacity = 80;\nitem.closed = true;\n```\n\n## Working with Colors\n\n### Color Objects\n\n```javascript\n// RGB Color (values 0-255)\nvar red = new RGBColor();\nred.red = 255;\nred.green = 0;\nred.blue = 0;\n\n// CMYK Color (values 0-100)\nvar cyan = new CMYKColor();\ncyan.cyan = 100;\ncyan.magenta = 0;\ncyan.yellow = 0;\ncyan.black = 0;\n\n// Grayscale (0-100, 0 = black)\nvar gray = new GrayColor();\ngray.gray = 50;\n\n// Lab Color\nvar lab = new LabColor();\nlab.l = 50;\nlab.a = 20;\nlab.b = -30;\n\n// No color (transparent)\nvar none = new NoColor();\n```\n\n### Applying Colors\n\n```javascript\nvar item = doc.pathItems[0];\nitem.fillColor = red;\nitem.strokeColor = cyan;\n\n// Gradient fill\nvar gradient = doc.gradients.add();\ngradient.type = GradientType.LINEAR;\ngradient.gradientStops[0].color = red;\ngradient.gradientStops[1].color = cyan;\n\nvar gradColor = new GradientColor();\ngradColor.gradient = gradient;\nitem.fillColor = gradColor;\n```\n\n### Spot Colors and Swatches\n\n```javascript\n// Create a spot color\nvar spot = doc.spots.add();\nspot.name = \"My Spot Color\";\nspot.color = red; // Base color definition\n\nvar spotColor = new SpotColor();\nspotColor.spot = spot;\nspotColor.tint = 100;\n\nitem.fillColor = spotColor;\n\n// Access a swatch by name\nvar swatch = doc.swatches.getByName(\"PANTONE 185 C\");\nitem.fillColor = swatch.color;\n```\n\n## Working with Text\n\n### Text Frame Types\n\n```javascript\nvar doc = app.activeDocument;\n\n// Point text\nvar pointText = doc.textFrames.add();\npointText.contents = \"Hello World!\";\npointText.position = [100, 500];\n\n// Area text (text inside a path)\nvar rectPath = doc.pathItems.rectangle(500, 100, 200, 100);\nvar areaText = doc.textFrames.areaText(rectPath);\nareaText.contents = \"Text inside a rectangle shape.\";\n\n// Path text (text along a path)\nvar curvePath = doc.pathItems.add();\ncurvePath.setEntirePath([[50, 300], [150, 400], [250, 300]]);\nvar pathText = doc.textFrames.pathText(curvePath);\npathText.contents = \"Text on a path\";\n```\n\n### Character and Paragraph Formatting\n\n```javascript\nvar tf = doc.textFrames[0];\nvar textRange = tf.textRange;\n\n// Character attributes\nvar charAttr = textRange.characterAttributes;\ncharAttr.size = 24;           // Font size in points\ncharAttr.textFont = app.textFonts.getByName(\"ArialMT\");\ncharAttr.fillColor = red;\ncharAttr.tracking = 50;       // Em units\ncharAttr.horizontalScale = 100;\ncharAttr.verticalScale = 100;\ncharAttr.baselineShift = 0;\n\n// Paragraph attributes\nvar paraAttr = textRange.paragraphAttributes;\nparaAttr.justification = Justification.CENTER;\nparaAttr.firstLineIndent = 0;\nparaAttr.leftIndent = 0;\nparaAttr.spaceBefore = 0;\nparaAttr.spaceAfter = 0;\n```\n\n### Accessing Text Content\n\n```javascript\nvar tf = doc.textFrames[0];\n\n// Access sub-ranges\nvar firstChar = tf.characters[0];\nvar firstWord = tf.words[0];\nvar firstPara = tf.paragraphs[0];\nvar firstLine = tf.lines[0];\n\n// Modify specific ranges\ntf.words[0].characterAttributes.size = 36;\ntf.paragraphs[0].paragraphAttributes.justification = Justification.LEFT;\n```\n\n### Threading Text Frames\n\n```javascript\nvar frame1 = doc.textFrames.areaText(path1);\nvar frame2 = doc.textFrames.areaText(path2);\n\n// Link frames so text flows from frame1 to frame2\nframe1.nextFrame = frame2;\n\n// Stories represent the full text across threaded frames\nvar storyCount = doc.stories.length;\nvar fullText = doc.stories[0].textRange.contents;\n```\n\n## Working with Layers\n\n```javascript\nvar doc = app.activeDocument;\n\n// Create a layer\nvar newLayer = doc.layers.add();\nnewLayer.name = \"Background\";\nnewLayer.visible = true;\nnewLayer.locked = false;\nnewLayer.opacity = 100;\n\n// Access existing layers\nvar topLayer = doc.layers[0];\nvar layerByName = doc.layers.getByName(\"Background\");\n\n// Move items between layers\nvar item = doc.pathItems[0];\nitem.move(newLayer, ElementPlacement.PLACEATBEGINNING);\n\n// Reorder layers\nnewLayer.zOrder(ZOrderMethod.SENDTOBACK);\n```\n\n## Working with Selections\n\n```javascript\n// Get current selection\nvar sel = app.activeDocument.selection;\n\n// Iterate selected items\nfor (var i = 0; i < sel.length; i++) {\n    var item = sel[i];\n    // Check type using typename\n    if (item.typename === \"PathItem\") {\n        item.fillColor = red;\n    } else if (item.typename === \"TextFrame\") {\n        item.contents = \"Modified\";\n    }\n}\n\n// Select an item programmatically\ndoc.pathItems[0].selected = true;\n\n// Deselect all\ndoc.selection = null;\n```\n\n## Working with Symbols\n\n```javascript\n// Place a symbol instance\nvar sym = doc.symbols.getByName(\"MySymbol\");\nvar instance = doc.symbolItems.add(sym);\ninstance.position = [200, 400];\n\n// Access symbol definition\nvar symDef = instance.symbol;\n\n// Break link to symbol (expand to regular art)\ninstance.breakLink();\n```\n\n## Transformations\n\n```javascript\nvar item = doc.pathItems[0];\n\n// Rotate 45 degrees around center\nitem.rotate(45);\n\n// Scale to 50% width, 75% height\nitem.resize(50, 75);\n\n// Translate (move) by 100 points right and 50 points up\nitem.translate(100, 50);\n\n// Using a transformation matrix\nvar matrix = app.getIdentityMatrix();\nmatrix = app.concatenateRotationMatrix(matrix, 30);\nmatrix = app.concatenateScaleMatrix(matrix, 150, 150);\nitem.transform(matrix);\n```\n\n## Working with Artboards\n\n```javascript\nvar doc = app.activeDocument;\n\n// Access artboards\nvar ab = doc.artboards[0];\nvar rect = ab.artboardRect; // [left, top, right, bottom]\n\n// Create a new artboard\nvar newAB = doc.artboards.add([0, 0, 612, 792]); // Letter size\nnewAB.name = \"Page 2\";\n\n// Set active artboard\ndoc.artboards.setActiveArtboardIndex(1);\n```\n\n## Data-Driven Graphics (Variables and Datasets)\n\n```javascript\n// Variables link document items to data fields\nvar v = doc.variables.add();\nv.kind = VariableKind.TEXTUAL;\nv.name = \"headline\";\n\n// Link a text frame to the variable\nvar tf = doc.textFrames[0];\ntf.contentVariable = v;\n\n// Create datasets for batch content\nvar ds = doc.dataSets.add();\nds.name = \"Version 1\";\n// Dataset captures current variable bindings\n\n// Switch datasets to swap content\ndoc.dataSets[0].display();\n```\n\n## Printing\n\n```javascript\nvar doc = app.activeDocument;\nvar opts = new PrintOptions();\n\nopts.printPreset = \"Default\";\n\n// Paper options\nvar paperOpts = new PrintPaperOptions();\npaperOpts.name = \"Letter\";\nopts.paperOptions = paperOpts;\n\n// Job options\nvar jobOpts = new PrintJobOptions();\njobOpts.copies = 1;\njobOpts.designation = PrintArtworkDesignation.VISIBLELAYERS;\nopts.jobOptions = jobOpts;\n\ndoc.print(opts);\n```\n\n## User Interaction Levels\n\nControl whether Illustrator shows dialogs during script execution:\n\n```javascript\n// Suppress all dialogs\napp.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;\n\n// Perform operations that might prompt dialogs...\ndoc.close(SaveOptions.DONOTSAVECHANGES);\n\n// Restore dialog display\napp.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;\n```\n\n## Working with Methods (JavaScript-Specific)\n\nWhen calling methods with multiple optional parameters, use `undefined` to skip middle parameters:\n\n```javascript\n// rotate(angle, [changePositions], [changeFillPatterns], [changeFillGradients], ...)\nitem.rotate(30, undefined, undefined, true);\n```\n\n## External Invocation & Argument Passing\n\nIllustrator scripts are routinely launched from outside the application —\nshell scripts, schedulers, build pipelines, ExtendScript Toolkit, or\n`BridgeTalk` messages from other Creative Cloud apps. The execution\nenvironment under those launchers differs from the in-application *File >\nScripts* path in several ways that frequently break otherwise-correct code.\n\n### `arguments[]` Is Unreliable Under External Launchers\n\nExtendScript Toolkit's `-run` invocation and `BridgeTalk.send()` do not\nforward arbitrary launcher arguments into the script's top-level\n`arguments[]` array. In many configurations the array contains a single\n`[object BridgeTalk]` element instead of the values the caller passed, as\ndemonstrated below:\n\n```javascript\n// At top of script\nvar passed = (typeof arguments !== \"undefined\") ? arguments : [];\nfor (var i = 0; i < passed.length; i++) {\n    $.writeln(\"arg[\" + i + \"] = \" + passed[i]);\n    // Often prints: arg[0] = [object BridgeTalk]\n}\n```\n\n**Do not rely on `arguments[]` for required inputs when the script is\nlaunched externally.** Use one of the following more reliable channels.\n\n### Sidecar File for Parameters\n\nWhen a script fails under an external launcher and the source of the error\nis not obvious, fall back to a sidecar file: have the caller write a small\ntext file at a known absolute path, and read it on startup. This works\nregardless of launcher quirks and is easy to inspect after a failed run.\n\n```javascript\nvar SIDECAR_PATH = \"C:/Users/userName/job.args.txt\";\n\nfunction readSidecar(path) {\n    var f = new File(path);\n    if (!f.exists || !f.open(\"r\")) return null;\n    var lines = [];\n    while (!f.eof) {\n        var ln = f.readln();\n        if (ln && !/^\\s*$/.test(ln)) lines.push(ln);\n    }\n    f.close();\n    return {\n        input:  lines[0],\n        output: lines[1],\n        mode:   lines[2]\n    };\n}\n```\n\nA `key=value` format is equally workable and avoids positional fragility:\n\n```text\ninput=C:/path/to/input.ai\noutput=C:/path/to/output.pdf\nmode=preview\n```\n\n### Environment Variables\n\n`$.getenv(\"NAME\")` returns environment variables visible to **Illustrator's\nprocess**, not the launcher's. If the launcher needs Illustrator to see a\nvalue, it must set the variable system-wide or in Illustrator's parent\nenvironment before launching. For per-invocation values, prefer a sidecar\nfile.\n\n### `$.fileName` and `File($.fileName).parent`\n\nUnder in-application execution, `$.fileName` is the absolute path of the\nrunning script and `File($.fileName).parent` yields the script's folder.\nUnder some external launchers (notably ESTK `-run`) `$.fileName` can be\nempty, causing relative path resolution to silently fail.\n\n```javascript\n// Fragile: returns null under some launchers\nvar here = $.fileName ? File($.fileName).parent : null;\nvar sidecar = here ? new File(here.fsName + \"/job.args.txt\") : null;\n\n// Robust: hardcode a known absolute path or fall back to a stable location\nvar sidecar = new File(\"C:/Users/userName/job.args.txt\");\nif (!sidecar.exists) sidecar = new File(Folder.temp.fsName + \"/job.args.txt\");\n```\n\n### Diagnostic Logging to an Absolute Path\n\nSilent failures are common because dialogs are suppressed and the launcher\nmay not surface `$.writeln` output. Write a plain-text log to a known\nabsolute path so a run can be inspected after the fact. Create the parent\nfolder on demand so the first call cannot fail for a missing directory.\n\n```javascript\nvar LOG_PATH = \"C:/Users/userName/logs/job.log\";\n\nfunction log(msg) {\n    try {\n        var f = new File(LOG_PATH);\n        try { if (!f.parent.exists) f.parent.create(); } catch (eDir) {}\n        if (f.open(\"a\")) {\n            f.writeln(\"[\" + new Date() + \"] \" + msg);\n            f.close();\n        }\n    } catch (e) {}\n}\n```\n\n### Wrap the Entry Point in `try { ... } catch`\n\nExternally launched scripts often fail without any visible indication. A\ntop-level `try`/`catch` that writes the error to the log file converts\nsilent failures into a single inspectable line.\n\n```javascript\ntry {\n    main();\n} catch (err) {\n    log(\"FATAL: \" + err + (err && err.line ? \" line=\" + err.line : \"\"));\n}\n```\n\n### Suppress User Interaction\n\nExternal callers cannot answer dialogs. Disable them before any DOM work\nand avoid `alert()` / `confirm()` / `prompt()` entirely in scripts that may\nbe launched headlessly.\n\n```javascript\napp.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;\n```\n\n### Save Explicitly\n\nClosing or letting Illustrator return to its idle state does not save the\nworking file. After all DOM edits, call `doc.saveAs(...)` (or `doc.save()`)\nexplicitly and log whether it succeeded.\n\n```javascript\nvar opts = new IllustratorSaveOptions();\nopts.compatibility = Compatibility.ILLUSTRATOR17;\ndoc.saveAs(new File(doc.fullName.fsName), opts);\n```\n\n## Common Patterns\n\n### Iterate All Page Items in a Document\n\n```javascript\nfunction processAllItems(doc) {\n    for (var i = 0; i < doc.pageItems.length; i++) {\n        var item = doc.pageItems[i];\n        // Process based on type\n        switch (item.typename) {\n            case \"PathItem\":\n                // handle path\n                break;\n            case \"TextFrame\":\n                // handle text\n                break;\n            case \"GroupItem\":\n                // handle group (may contain nested items)\n                break;\n        }\n    }\n}\n```\n\n### Recursively Unlock Layers and Groups Before Editing\n\nA locked layer or any locked ancestor (parent group, clip group, sublayer)\nwill cause edits to throw `Error: Target layer cannot be modified`. Walk the\nfull hierarchy and clear `locked` / `hidden` flags before performing DOM\nmodifications.\n\n```javascript\nfunction unlockAll(doc) {\n    function visitLayers(layers) {\n        for (var i = 0; i < layers.length; i++) {\n            var lyr = layers[i];\n            try { lyr.locked = false; lyr.visible = true; } catch (e) {}\n            visitItems(lyr);\n            if (lyr.layers && lyr.layers.length) visitLayers(lyr.layers);\n        }\n    }\n    function visitItems(container) {\n        var items = container.pageItems;\n        for (var j = 0; j < items.length; j++) {\n            var it = items[j];\n            try { it.locked = false; it.hidden = false; } catch (e) {}\n            if (it.typename === \"GroupItem\") visitItems(it);\n        }\n    }\n    visitLayers(doc.layers);\n}\n```\n\n### Replacing the File Behind a Linked Image (Relink)\n\n`PlacedItem.file = newFile` replaces a linked image while preserving the\nparent, stacking order, and (after re-applying) the bounds. **`RasterItem`\ndoes not expose a writable `file` property**, so when a placeholder is a\nraster you must add a fresh `PlacedItem` in the same parent, copy the bounds,\nthen remove the original.\n\n```javascript\nfunction relinkOrRebuild(item, newFile) {\n    var bounds = item.geometricBounds.slice();\n    var parent = item.parent;\n    var name   = item.name;\n\n    if (item.typename === \"PlacedItem\") {\n        item.file = newFile;\n        item.geometricBounds = bounds;\n        return item;\n    }\n\n    // RasterItem path: rebuild as a linked PlacedItem in the same parent.\n    var fresh = parent.placedItems.add();\n    fresh.file = newFile;\n    fresh.geometricBounds = bounds;\n    if (name) try { fresh.name = name; } catch (e) {}\n    fresh.move(item, ElementPlacement.PLACEBEFORE);\n    item.remove();\n    return fresh;\n}\n```\n\n### Placing SVG Content (Copy/Paste Pattern)\n\n`PlacedItem.file` accepts raster formats and AI/PDF, **but not SVG**. Setting\nit to an `.svg` File throws `Unable to set placed item's file, is the file\npath provided valid?`. The reliable way to bring SVG artwork into a document\nis to open the SVG as a separate document, select all, copy, close, and paste\ninto the working document.\n\n```javascript\nfunction placeSVG(targetDoc, svgFile, targetLayer) {\n    var donor = app.open(svgFile);\n    app.executeMenuCommand(\"selectall\");\n    app.executeMenuCommand(\"copy\");\n    donor.close(SaveOptions.DONOTSAVECHANGES);\n\n    app.activeDocument = targetDoc;\n    targetDoc.activeLayer = targetLayer;\n    app.executeMenuCommand(\"pasteFront\");\n\n    var sel = targetDoc.selection;\n    if (!sel || sel.length === 0) return null;\n    if (sel.length === 1) return sel[0];\n\n    // Multiple pasted items: group them so callers get a single handle.\n    var group = targetLayer.groupItems.add();\n    for (var i = sel.length - 1; i >= 0; i--) {\n        sel[i].move(group, ElementPlacement.PLACEATBEGINNING);\n    }\n    return group;\n}\n```\n\n### Finding a Clipping Path Inside a Mask Group\n\nClip groups expose their clipping shape as a child `PathItem` (or, less\ncommonly, a child of a `CompoundPathItem`) with `clipping === true`. The\nclip's `geometricBounds` give the visible frame to size or center content\nagainst.\n\n```javascript\nfunction findClipPath(group) {\n    var items = group.pageItems;\n    for (var i = 0; i < items.length; i++) {\n        var it = items[i];\n        try {\n            if (it.typename === \"PathItem\" && it.clipping) return it;\n            if (it.typename === \"CompoundPathItem\") {\n                for (var j = 0; j < it.pathItems.length; j++) {\n                    if (it.pathItems[j].clipping) return it;\n                }\n            }\n        } catch (e) {}\n    }\n    return null;\n}\n```\n\n### Cover-Fit and Contain-Fit Sizing\n\nTo make an image fully cover a rectangle (any overflow hidden by a mask), use\nthe larger of the width/height ratios. To make it fit entirely inside, use\nthe smaller. A bleed factor (e.g. `1.10`) lets a cover image extend slightly\npast the clip edge.\n\n```javascript\nfunction fitItemToRect(item, rect, mode, bleed) {\n    // rect = [L, T, R, B] (Illustrator: T > B)\n    var rw = rect[2] - rect[0];\n    var rh = rect[1] - rect[3];\n    var ib = item.geometricBounds;\n    var iw = ib[2] - ib[0];\n    var ih = ib[1] - ib[3];\n    if (iw <= 0 || ih <= 0) return;\n\n    var sx = rw / iw;\n    var sy = rh / ih;\n    var s  = (mode === \"cover\" ? Math.max(sx, sy) : Math.min(sx, sy))\n           * (bleed || 1);\n    item.resize(s * 100, s * 100);\n\n    var cx = (rect[0] + rect[2]) / 2;\n    var cy = (rect[1] + rect[3]) / 2;\n    var b  = item.geometricBounds;\n    var w  = b[2] - b[0];\n    var h  = b[1] - b[3];\n    item.position = [cx - w / 2, cy + h / 2];\n}\n```\n\n\n\n### Batch Process Files in a Folder\n\n```javascript\nvar folder = Folder.selectDialog(\"Select folder of .ai files\");\nif (folder) {\n    var files = folder.getFiles(\"*.ai\");\n    for (var i = 0; i < files.length; i++) {\n        var doc = app.open(files[i]);\n        // Process each document...\n        doc.close(SaveOptions.DONOTSAVECHANGES);\n    }\n}\n```\n\n### Error Handling\n\n```javascript\ntry {\n    var doc = app.activeDocument;\n    var layer = doc.layers.getByName(\"NonExistentLayer\");\n} catch (e) {\n    alert(\"Error: \" + e.message);\n    // e.message, e.line, e.fileName available\n}\n```\n\n## Troubleshooting\n\n- **\"undefined is not an object\"**: Usually means the collection is empty or the index is out of bounds. Check `.length` before accessing items.\n- **Script runs but nothing changes visually**: Call `app.redraw()` to force a screen refresh after modifications.\n- **Color mode mismatch**: Document color space (RGB vs CMYK) must match color objects. Use `doc.documentColorSpace` to check.\n- **Position seems wrong**: Remember scripted documents use bottom-left origin with Y increasing upward. The `position` property is the top-left of the bounding box.\n- **Text not appearing**: Ensure the text frame has a non-zero size. For point text, set `position`; for area text, provide a valid path to `areaText()`.\n- **File paths on Windows**: Use forward slashes (`/`) or double backslashes (`\\\\`) in path strings, or use the `File` object constructor.\n- **Dialog boxes interrupting batch scripts**: Set `app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS` before batch operations.\n- **Collections use `getByName()`**: Many collection objects support `getByName(\"name\")` which throws an error if not found; wrap in try/catch.\n- **\"Target layer cannot be modified\"**: A locked layer, sublayer, or parent group (often a clip group like `Cover_Mask`) is blocking the edit. Recursively clear `locked` and `hidden` across the document before modifying. See [Recursively Unlock Layers and Groups](#recursively-unlock-layers-and-groups-before-editing).\n- **\"Unable to set placed item's file, is the file path provided valid?\"**: The file exists and the path is correct, but `PlacedItem.file` does not accept the format. SVG is the most common cause — use the [open / copy / paste pattern](#placing-svg-content-copypaste-pattern) instead.\n- **`RasterItem.file = newFile` does nothing or throws**: `RasterItem` does not expose a writable `file` property. Add a new `PlacedItem` to the same parent, restore the bounds and name, then `.remove()` the raster.\n- **`arguments[0]` is `[object BridgeTalk]`** (or empty): The script was launched through ESTK `-run` or a `BridgeTalk` message; positional arguments are not forwarded. Use a sidecar file at a known absolute path. See [External Invocation & Argument Passing](#external-invocation--argument-passing).\n- **`$.fileName` is empty**: Same external-launcher cause. Do not derive resource paths from `$.fileName` in scripts that may be invoked headlessly — use absolute paths or `Folder.temp`.\n- **Script appears to do nothing**: Almost always either a locked ancestor, suppressed dialogs swallowing the error, or a missing explicit `saveAs` after edits. Add a top-level `try`/`catch` that logs to an absolute path to confirm execution and capture the error.\n- **`item.resize(sx, sy)` recentered the artwork unexpectedly**: `resize` defaults to scaling around the item's center (`Transformation.CENTER`). Pass an explicit `scaleAbout` argument or follow with `translate(dx, dy)` to reposition.\n\n## Scripting Constants Reference\n\nCommon enumeration constants used across the API:\n\n| Category | Constants |\n|---|---|\n| **Color Space** | `DocumentColorSpace.RGB`, `DocumentColorSpace.CMYK` |\n| **Justification** | `Justification.LEFT`, `Justification.CENTER`, `Justification.RIGHT`, `Justification.FULLJUSTIFY` |\n| **Point Type** | `PointType.SMOOTH`, `PointType.CORNER` |\n| **Stroke Cap** | `StrokeCap.BUTTENDCAP`, `StrokeCap.ROUNDENDCAP`, `StrokeCap.PROJECTINGENDCAP` |\n| **Stroke Join** | `StrokeJoin.MITERENDJOIN`, `StrokeJoin.ROUNDENDJOIN`, `StrokeJoin.BEVELENDJOIN` |\n| **Blend Mode** | `BlendModes.NORMAL`, `BlendModes.MULTIPLY`, `BlendModes.SCREEN`, `BlendModes.OVERLAY` |\n| **Save Options** | `SaveOptions.SAVECHANGES`, `SaveOptions.DONOTSAVECHANGES`, `SaveOptions.PROMPTTOSAVECHANGES` |\n| **Export Type** | `ExportType.PNG24`, `ExportType.PNG8`, `ExportType.JPEG`, `ExportType.SVG`, `ExportType.TIFF`, `ExportType.PHOTOSHOP`, `ExportType.AUTOCAD`, `ExportType.FLASH` |\n| **Element Placement** | `ElementPlacement.PLACEATBEGINNING`, `ElementPlacement.PLACEATEND`, `ElementPlacement.PLACEBEFORE`, `ElementPlacement.PLACEAFTER`, `ElementPlacement.INSIDE` |\n| **Z-Order** | `ZOrderMethod.BRINGTOFRONT`, `ZOrderMethod.SENDTOBACK`, `ZOrderMethod.BRINGFORWARD`, `ZOrderMethod.SENDBACKWARD` |\n| **Gradient Type** | `GradientType.LINEAR`, `GradientType.RADIAL` |\n| **Text Frame Kind** | `TextType.POINTTEXT`, `TextType.AREATEXT`, `TextType.PATHTEXT` |\n| **Variable Kind** | `VariableKind.TEXTUAL`, `VariableKind.IMAGE`, `VariableKind.VISIBILITY`, `VariableKind.GRAPH` |\n| **User Interaction** | `UserInteractionLevel.DISPLAYALERTS`, `UserInteractionLevel.DONTDISPLAYALERTS` |\n| **Compatibility** | `Compatibility.ILLUSTRATOR10` through `Compatibility.ILLUSTRATOR24` |\n\n## JavaScript Object Reference (Complete API Object List)\n\nThe Illustrator JavaScript API contains the following objects, grouped by category:\n\n### Core Objects\n\n`Application`, `Document`, `Documents`, `DocumentPreset`, `Layer`, `Layers`, `PageItem`, `PageItems`, `View`, `Views`, `Preferences`\n\n### Path and Shape Objects\n\n`PathItem`, `PathItems`, `PathPoint`, `PathPoints`, `CompoundPathItem`, `CompoundPathItems`, `GroupItem`, `GroupItems`\n\n### Text Objects\n\n`TextFrame`, `TextRange`, `TextRanges`, `TextPath`, `Characters`, `Words`, `Paragraphs`, `Lines`, `InsertionPoint`, `InsertionPoints`, `Story`, `Stories`, `CharacterAttributes`, `ParagraphAttributes`, `CharacterStyle`, `CharacterStyles`, `ParagraphStyle`, `ParagraphStyles`, `TextFont`, `TextFonts`, `TabStopInfo`\n\n### Color Objects\n\n`RGBColor`, `CMYKColor`, `GrayColor`, `LabColor`, `NoColor`, `SpotColor`, `Spot`, `Spots`, `PatternColor`, `GradientColor`, `Color`, `Gradient`, `Gradients`, `GradientStop`, `GradientStops`\n\n### Swatch and Style Objects\n\n`Swatch`, `Swatches`, `SwatchGroup`, `SwatchGroups`, `GraphicStyle`, `GraphicStyles`, `Pattern`, `Patterns`, `Brush`, `Brushes`\n\n### Symbol Objects\n\n`Symbol`, `Symbols`, `SymbolItem`, `SymbolItems`\n\n### Artboard Objects\n\n`Artboard`, `Artboards`\n\n### Placed and Raster Objects\n\n`PlacedItem`, `PlacedItems`, `RasterItem`, `RasterItems`, `MeshItem`, `MeshItems`, `GraphItem`, `GraphItems`, `PluginItem`, `PluginItems`, `NonNativeItem`, `NonNativeItems`, `LegacyTextItem`, `LegacyTextItems`\n\n### Data-Driven Objects\n\n`Variable`, `Variables`, `Dataset`, `Datasets`\n\n### Matrix and Transform Objects\n\n`Matrix`\n\n### Tag Objects\n\n`Tag`, `Tags`\n\n### Tracing Objects\n\n`TracingObject`, `TracingOptions`\n\n### Save and Export Options\n\n`IllustratorSaveOptions`, `EPSSaveOptions`, `PDFSaveOptions`, `FXGSaveOptions`, `ExportOptionsAutoCAD`, `ExportOptionsFlash`, `ExportOptionsGIF`, `ExportOptionsJPEG`, `ExportOptionsPhotoshop`, `ExportOptionsPNG8`, `ExportOptionsPNG24`, `ExportOptionsSVG`, `ExportOptionsTIFF`\n\n### Open Options\n\n`OpenOptions`, `OpenOptionsAutoCAD`, `OpenOptionsFreeHand`, `OpenOptionsPhotoshop`, `PDFFileOptions`, `PhotoshopFileOptions`\n\n### Print Objects\n\n`PrintOptions`, `PrintJobOptions`, `PrintPaperOptions`, `PrintColorManagementOptions`, `PrintColorSeparationOptions`, `PrintCoordinateOptions`, `PrintFlattenerOptions`, `PrintFontOptions`, `PrintPageMarksOptions`, `PrintPostScriptOptions`, `Printer`, `PrinterInfo`, `Paper`, `PaperInfo`, `PPDFile`, `PPDFileInfo`, `Ink`, `InkInfo`, `Screen`, `ScreenInfo`, `ScreenSpotFunction`\n\n### Image and Rasterize Options\n\n`ImageCaptureOptions`, `RasterEffectOptions`, `RasterizeOptions`\n\n## References\n\n- [Changelog](https://ai-scripting.docsforadobe.dev/introduction/changelog/) - Recent scripting API changes (CC 2020 added `Document.getPageItemFromUuid` and `PageItem.uuid`; CC 2017 added `Application.getIsFileOpen`)\n- [Illustrator Scripting Guide](https://ai-scripting.docsforadobe.dev/) - Full community-maintained documentation\n\nFile v1.0.2:_meta.json\n\n{\n  \"ownerId\": \"kn71kvdba3t2jfkk6nbgnytg0s81617g\",\n  \"slug\": \"adobe-illustrator-scripting\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1779915513752\n}\n\nFile v1.0.2:references/object-model-quick-reference.md\n\n# Illustrator JavaScript Object Model Quick Reference\n\n## Containment Hierarchy\n\n```\nApplication (app)\n └─ Document\n     ├─ Layer\n     │   ├─ pathItems[]        → PathItem → PathPoint[]\n     │   ├─ compoundPathItems[] → CompoundPathItem\n     │   ├─ textFrames[]       → TextFrame\n     │   │   ├─ characters[]   → TextRange (single char)\n     │   │   ├─ words[]        → TextRange (word)\n     │   │   ├─ paragraphs[]   → TextRange (paragraph)\n     │   │   ├─ lines[]        → TextRange (line)\n     │   │   └─ insertionPoints[]\n     │   ├─ placedItems[]      → PlacedItem\n     │   ├─ rasterItems[]      → RasterItem\n     │   ├─ meshItems[]        → MeshItem\n     │   ├─ pluginItems[]      → PluginItem\n     │   ├─ graphItems[]       → GraphItem\n     │   ├─ symbolItems[]      → SymbolItem → Symbol\n     │   ├─ groupItems[]       → GroupItem (recursive pageItems)\n     │   ├─ nonNativeItems[]   → NonNativeItem\n     │   └─ legacyTextItems[]  → LegacyTextItem\n     ├─ Artboard[]\n     ├─ Swatch[] / Spot[] / Gradient[] / Pattern[]\n     ├─ GraphicStyle[] / Brush[] / Symbol[]\n     ├─ Story[]\n     ├─ CharacterStyle[] / ParagraphStyle[]\n     ├─ Variable[] / Dataset[]\n     └─ View[]\n```\n\n## Artwork Item Types (pageItems members)\n\n| Type | typename | Collection | Notes |\n|---|---|---|---|\n| Path | `PathItem` | `pathItems` | Lines, shapes, freeform paths |\n| Compound path | `CompoundPathItem` | `compoundPathItems` | Multiple paths combined |\n| Group | `GroupItem` | `groupItems` | Contains nested pageItems |\n| Text frame | `TextFrame` | `textFrames` | Point, area, or path text |\n| Placed image | `PlacedItem` | `placedItems` | Linked external files |\n| Raster image | `RasterItem` | `rasterItems` | Embedded bitmaps |\n| Mesh | `MeshItem` | `meshItems` | Gradient mesh objects |\n| Graph | `GraphItem` | `graphItems` | Chart/graph objects |\n| Plugin item | `PluginItem` | `pluginItems` | Plugin-generated art |\n| Symbol instance | `SymbolItem` | `symbolItems` | Instance of a Symbol |\n| Non-native | `NonNativeItem` | `nonNativeItems` | Foreign objects |\n| Legacy text | `LegacyTextItem` | `legacyTextItems` | Pre-CS text objects |\n\n## Color Object Types\n\n| Object | Color Space | Value Range | Notes |\n|---|---|---|---|\n| `RGBColor` | RGB | 0-255 per channel | `.red`, `.green`, `.blue` |\n| `CMYKColor` | CMYK | 0-100 per channel | `.cyan`, `.magenta`, `.yellow`, `.black` |\n| `GrayColor` | Grayscale | 0-100 | `.gray` (0=black, 100=white) |\n| `LabColor` | Lab | L: 0-100, a/b: -128 to 127 | `.l`, `.a`, `.b` |\n| `SpotColor` | Spot | tint 0-100 | `.spot`, `.tint` |\n| `PatternColor` | Pattern | - | `.pattern`, `.matrix` |\n| `GradientColor` | Gradient | - | `.gradient`, `.origin`, `.angle` |\n| `NoColor` | None | - | Transparent/no fill |\n\n## Common Scripting Constants\n\n### Document and Color\n\n- `DocumentColorSpace.RGB` / `.CMYK`\n\n### Text\n\n- `Justification.LEFT` / `.CENTER` / `.RIGHT` / `.FULLJUSTIFY` / `.FULLJUSTIFYLASTLINELEFT` / `.FULLJUSTIFYLASTLINECENTER` / `.FULLJUSTIFYLASTLINERIGHT`\n- `TextType.POINTTEXT` / `.AREATEXT` / `.PATHTEXT`\n- `FontBaselineOption.NORMALBASELINE` / `.SUPERSCRIPT` / `.SUBSCRIPT`\n\n### Paths\n\n- `PointType.SMOOTH` / `.CORNER`\n- `StrokeCap.BUTTENDCAP` / `.ROUNDENDCAP` / `.PROJECTINGENDCAP`\n- `StrokeJoin.MITERENDJOIN` / `.ROUNDENDJOIN` / `.BEVELENDJOIN`\n\n### Transformations\n\n- `Transformation.DOCUMENTORIGIN` / `.BOTTOM` / `.BOTTOMLEFT` / `.BOTTOMRIGHT` / `.CENTER` / `.LEFT` / `.RIGHT` / `.TOP` / `.TOPLEFT` / `.TOPRIGHT`\n\n### Blend Modes\n\n- `BlendModes.NORMAL` / `.MULTIPLY` / `.SCREEN` / `.OVERLAY` / `.SOFTLIGHT` / `.HARDLIGHT` / `.COLORDODGE` / `.COLORBURN` / `.DARKEN` / `.LIGHTEN` / `.DIFFERENCE` / `.EXCLUSION` / `.HUE` / `.SATURATIONBLEND` / `.COLORBLEND` / `.LUMINOSITY`\n\n### Element Placement\n\n- `ElementPlacement.PLACEATBEGINNING` / `.PLACEATEND` / `.PLACEBEFORE` / `.PLACEAFTER` / `.INSIDE`\n\n### Z-Order\n\n- `ZOrderMethod.BRINGTOFRONT` / `.SENDTOBACK` / `.BRINGFORWARD` / `.SENDBACKWARD`\n\n### Save/Export\n\n- `SaveOptions.SAVECHANGES` / `.DONOTSAVECHANGES` / `.PROMPTTOSAVECHANGES`\n- `ExportType.PNG24` / `.PNG8` / `.JPEG` / `.SVG` / `.TIFF` / `.PHOTOSHOP` / `.AUTOCAD` / `.FLASH` / `.GIF`\n- `Compatibility.ILLUSTRATOR8` through `.ILLUSTRATOR24`\n- `PDFCompatibility.ACROBAT4` through `.ACROBAT8`\n\n### Gradient\n\n- `GradientType.LINEAR` / `.RADIAL`\n\n### Variables\n\n- `VariableKind.TEXTUAL` / `.IMAGE` / `.VISIBILITY` / `.GRAPH`\n\n### User Interaction\n\n- `UserInteractionLevel.DISPLAYALERTS` / `.DONTDISPLAYALERTS`\n\n### Print\n\n- `PrintArtworkDesignation.ALLLAYERS` / `.VISIBLELAYERS` / `.VISIBLEPRINTABLELAYERS`\n\n## Unit Conversions\n\n| From | To Points | Formula |\n|---|---|---|\n| Inches | Points | `inches * 72` |\n| Centimeters | Points | `cm * 28.346` |\n| Millimeters | Points | `mm * 2.834645` |\n| Picas | Points | `picas * 12` |\n| Em units | Points | `(emUnits * fontSize) / 1000` |\n\nFile v1.0.2:skill-card.md\n\n## Description:\n\nWrite, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX) for documents, layers, paths, text frames, colors, symbols, artboards, export workflows, and related Illustrator DOM objects.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jhauga](https://clawhub.ai/user/jhauga)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and designers use this skill to create, debug, and adapt Illustrator ExtendScript automation for document editing, batch exports, artwork generation, text replacement, and DOM-based workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Generated or adapted Illustrator scripts can save, export, delete, remove, or otherwise modify artwork and documents.\n\nMitigation: Review scripts before execution, test on copies of files, and confirm file paths and document targets before running batch or unattended workflows.\n\nRisk: Startup or headless Illustrator scripts can run without visible prompts, especially when dialogs are suppressed.\n\nMitigation: Avoid placing unreviewed scripts in Startup Scripts, use explicit logging for unattended runs, and keep user interaction enabled unless the workflow requires suppression.\n\nRisk: Scripts that open external files or use sidecar/log files may read or write unexpected paths if inputs are wrong.\n\nMitigation: Use known absolute paths, validate inputs, and inspect sidecar or log locations before running externally launched automation.\n\n## Reference(s):\n\n- [Illustrator JavaScript Object Model Quick Reference](references/object-model-quick-reference.md)\n- [Illustrator Scripting Guide](https://ai-scripting.docsforadobe.dev/)\n- [Illustrator Scripting Changelog](https://ai-scripting.docsforadobe.dev/introduction/changelog/)\n- [ClawHub Skill Page](https://clawhub.ai/jhauga/skills/adobe-illustrator-scripting)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with JavaScript/JSX code blocks, concise guidance, and optional command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Illustrator ExtendScript snippets, workflow checks, troubleshooting notes, and file path guidance.]\n\n## Skill Version(s):\n\n1.0.2 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment.\n\nArchive v1.0.1: 6 files, 12866 bytes\n\nFiles: references/object-model-quick-reference.md (5013b), scripts/batch-export-png.jsx (1339b), scripts/create-color-grid.jsx (1146b), scripts/find-replace-text.jsx (893b), SKILL.md (23410b), _meta.json (146b)\n\nFile v1.0.1:SKILL.md\n\n---\nname: adobe-illustrator-scripting\ndescription: 'Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate documents, layers, paths, text frames, colors, symbols, artboards, or any Illustrator DOM objects. Covers the complete JavaScript object model, coordinate system, measurement units, export workflows, and scripting best practices.'\n---\n\n# Adobe Illustrator Scripting\n\nExpert guidance for automating Adobe Illustrator through ExtendScript (JavaScript/JSX). This skill covers the Illustrator scripting object model, all major API objects, code patterns, and best practices for writing production-quality `.jsx` scripts.\n\n## Bundled Assets\n\n- [`references/object-model-quick-reference.md`](references/object-model-quick-reference.md): Use this as a quick lookup for the Illustrator scripting object model, common document and page item types, and related DOM concepts while writing or debugging scripts.\n- `scripts/`: Contains example Illustrator automation scripts you can use as starting points or implementation patterns for common tasks such as document manipulation, exports, batch processing, and DOM usage. Review and adapt these examples when you need working JSX patterns or want to compare behavior while debugging.\n## When to Use This Skill\n\n- Writing new Illustrator automation scripts (`.jsx` or `.js` files)\n- Debugging or fixing existing Illustrator ExtendScript code\n- Manipulating documents, layers, page items, paths, text, or colors programmatically\n- Batch-processing Illustrator files or generating artwork from data\n- Exporting documents to various formats (PDF, SVG, PNG, EPS, etc.)\n- Working with the Illustrator DOM (Application, Document, Layer, PathItem, TextFrame, etc.)\n- Creating data-driven graphics using variables and datasets\n- Automating print workflows with scripted print options\n\n## Prerequisites\n\n- Adobe Illustrator CC or later installed\n- Basic JavaScript knowledge (ExtendScript is ES3-based with Adobe extensions)\n- Scripts are executed via File > Scripts > Other Scripts, the Scripts menu, or placed in the Startup Scripts folder\n- The ExtendScript Toolkit (ESTK) or any text editor can be used to write `.jsx` files\n\n## Scripting Environment\n\n### Language and File Extensions\n\n| Language | Extension | Platform |\n|---|---|---|\n| ExtendScript/JavaScript | `.jsx`, `.js` | Windows, macOS |\n| AppleScript | `.scpt` | macOS only |\n| VBScript | `.vbs` | Windows only |\n\n**This skill focuses on ExtendScript/JavaScript** as the cross-platform, most widely used option.\n\n### Executing Scripts\n\n- **Scripts menu**: File > Scripts lists scripts from the application scripts folder\n- **Other Scripts**: File > Scripts > Other Scripts to browse and run any `.jsx` file\n- **Startup Scripts**: Place scripts in the Startup Scripts folder to run automatically on launch\n- **Target directive**: Begin scripts with `#target illustrator` when running from ESTK or external tools\n- **`#targetengine` directive**: Use `#targetengine \"session\"` to persist variables across script executions\n\n### Naming Conventions (JavaScript)\n\n- Objects and properties use **camelCase**: `activeDocument`, `pathItems`, `textFrames`\n- The `app` global references the `Application` object\n- Collection indices are **zero-based**: `documents[0]` is the frontmost document\n- Use `typename` property to identify object types at runtime\n\n## Object Model Overview\n\nThe Illustrator DOM follows a strict containment hierarchy:\n\n```\nApplication (app)\n├── activeDocument / documents[]\n│   ├── layers[]\n│   │   ├── pageItems[] (all artwork)\n│   │   ├── pathItems[]\n│   │   ├── compoundPathItems[]\n│   │   ├── textFrames[]\n│   │   ├── placedItems[]\n│   │   ├── rasterItems[]\n│   │   ├── meshItems[]\n│   │   ├── pluginItems[]\n│   │   ├── graphItems[]\n│   │   ├── symbolItems[]\n│   │   ├── nonNativeItems[]\n│   │   ├── legacyTextItems[]\n│   │   └── groupItems[]\n│   ├── artboards[]\n│   ├── views[]\n│   ├── selection (array of selected items)\n│   ├── swatches[], spots[], gradients[], patterns[]\n│   ├── graphicStyles[], brushes[], symbols[]\n│   ├── textFonts[] (via app.textFonts)\n│   ├── stories[], characterStyles[], paragraphStyles[]\n│   ├── variables[], datasets[]\n│   └── inkList[], printOptions\n├── preferences\n├── printerList[]\n└── textFonts[]\n```\n\n### Top-Level Objects\n\n- **Application** (`app`): The root object. Provides access to documents, preferences, fonts, and printers. Key properties: `activeDocument`, `documents`, `textFonts`, `printerList`, `userInteractionLevel`, `version`.\n- **Document**: Represents an open `.ai` file. Key properties: `layers`, `pageItems`, `selection`, `activeLayer`, `width`, `height`, `rulerOrigin`, `documentColorSpace`. Key methods: `saveAs()`, `exportFile()`, `close()`, `print()`.\n- **Layer**: A drawing layer. Key properties: `pageItems`, `pathItems`, `textFrames`, `visible`, `locked`, `opacity`, `name`, `zOrderPosition`, `color`.\n\n## Measurement Units and Coordinates\n\n### Units\n\nAll scripting API values use **points** (72 points = 1 inch). Convert other units:\n\n| Unit | Conversion |\n|---|---|\n| Inches | multiply by 72 |\n| Centimeters | multiply by 28.346 |\n| Millimeters | multiply by 2.834645 |\n| Picas | multiply by 12 |\n\nKerning, tracking, and `aki` properties use **em units** (thousandths of an em, proportional to font size).\n\n### Coordinate System\n\n- For **scripted documents**, the origin `(0,0)` is at the **bottom-left** of the artboard\n- X increases left to right; Y increases bottom to top\n- The `position` property of a page item is the **top-left corner** of its bounding box as `[x, y]`\n- Maximum page item width/height: 16348 points\n\n### Art Item Bounds\n\nEvery page item has three bounding rectangles:\n\n- `geometricBounds`: Excludes stroke width `[left, top, right, bottom]`\n- `visibleBounds`: Includes stroke width\n- `controlBounds`: Includes control/direction points\n\n## Working with Documents\n\n### Creating and Opening\n\n```javascript\n// Create a new document\nvar doc = app.documents.add();\n\n// Create with a preset\nvar preset = new DocumentPreset();\npreset.width = 612;  // 8.5 inches\npreset.height = 792; // 11 inches\npreset.colorMode = DocumentColorSpace.CMYK;\nvar doc = app.documents.addDocument(\"Print\", preset);\n\n// Open an existing file\nvar fileRef = new File(\"/path/to/file.ai\");\nvar doc = app.open(fileRef);\n```\n\n### Saving and Exporting\n\n```javascript\n// Save as Illustrator format\nvar saveOpts = new IllustratorSaveOptions();\nsaveOpts.compatibility = Compatibility.ILLUSTRATOR17; // CC\ndoc.saveAs(new File(\"/path/to/output.ai\"), saveOpts);\n\n// Export as PDF\nvar pdfOpts = new PDFSaveOptions();\npdfOpts.compatibility = PDFCompatibility.ACROBAT7;\npdfOpts.preserveEditability = false;\ndoc.saveAs(new File(\"/path/to/output.pdf\"), pdfOpts);\n\n// Export as PNG\nvar pngOpts = new ExportOptionsPNG24();\npngOpts.horizontalScale = 300;\npngOpts.verticalScale = 300;\npngOpts.transparency = true;\ndoc.exportFile(new File(\"/path/to/output.png\"), ExportType.PNG24, pngOpts);\n\n// Export as SVG\nvar svgOpts = new ExportOptionsSVG();\nsvgOpts.fontType = SVGFontType.OUTLINEFONT;\ndoc.exportFile(new File(\"/path/to/output.svg\"), ExportType.SVG, svgOpts);\n```\n\n## Working with Paths and Shapes\n\n### Built-in Shape Methods\n\nThe `pathItems` collection provides convenience methods for common shapes:\n\n```javascript\nvar doc = app.activeDocument;\nvar layer = doc.activeLayer;\n\n// Rectangle: rectangle(top, left, width, height)\nvar rect = layer.pathItems.rectangle(500, 100, 200, 150);\n\n// Rounded rectangle: roundedRectangle(top, left, width, height, hRadius, vRadius)\nvar rrect = layer.pathItems.roundedRectangle(500, 100, 200, 150, 20, 20);\n\n// Ellipse: ellipse(top, left, width, height)\nvar oval = layer.pathItems.ellipse(400, 200, 100, 100);\n\n// Polygon: polygon(centerX, centerY, radius, sides)\nvar hex = layer.pathItems.polygon(300, 300, 50, 6);\n\n// Star: star(centerX, centerY, radius, innerRadius, points)\nvar star = layer.pathItems.star(300, 300, 50, 25, 5);\n```\n\n### Freeform Paths Using Coordinate Arrays\n\n```javascript\nvar doc = app.activeDocument;\nvar path = doc.pathItems.add();\npath.setEntirePath([[100, 100], [200, 200], [300, 100]]);\npath.closed = false;\npath.stroked = true;\npath.strokeWidth = 2;\n```\n\n### Freeform Paths Using PathPoint Objects\n\n```javascript\nvar doc = app.activeDocument;\nvar path = doc.pathItems.add();\n\nvar point1 = path.pathPoints.add();\npoint1.anchor = [100, 100];\npoint1.leftDirection = [100, 100];\npoint1.rightDirection = [150, 150];\npoint1.pointType = PointType.SMOOTH;\n\nvar point2 = path.pathPoints.add();\npoint2.anchor = [300, 100];\npoint2.leftDirection = [250, 150];\npoint2.rightDirection = [300, 100];\npoint2.pointType = PointType.SMOOTH;\n\npath.closed = false;\n```\n\n### Path Properties\n\n```javascript\nvar item = doc.pathItems[0];\nitem.filled = true;\nitem.stroked = true;\nitem.strokeWidth = 1.5;\nitem.strokeCap = StrokeCap.ROUNDENDCAP;\nitem.strokeJoin = StrokeJoin.ROUNDENDJOIN;\nitem.opacity = 80;\nitem.closed = true;\n```\n\n## Working with Colors\n\n### Color Objects\n\n```javascript\n// RGB Color (values 0-255)\nvar red = new RGBColor();\nred.red = 255;\nred.green = 0;\nred.blue = 0;\n\n// CMYK Color (values 0-100)\nvar cyan = new CMYKColor();\ncyan.cyan = 100;\ncyan.magenta = 0;\ncyan.yellow = 0;\ncyan.black = 0;\n\n// Grayscale (0-100, 0 = black)\nvar gray = new GrayColor();\ngray.gray = 50;\n\n// Lab Color\nvar lab = new LabColor();\nlab.l = 50;\nlab.a = 20;\nlab.b = -30;\n\n// No color (transparent)\nvar none = new NoColor();\n```\n\n### Applying Colors\n\n```javascript\nvar item = doc.pathItems[0];\nitem.fillColor = red;\nitem.strokeColor = cyan;\n\n// Gradient fill\nvar gradient = doc.gradients.add();\ngradient.type = GradientType.LINEAR;\ngradient.gradientStops[0].color = red;\ngradient.gradientStops[1].color = cyan;\n\nvar gradColor = new GradientColor();\ngradColor.gradient = gradient;\nitem.fillColor = gradColor;\n```\n\n### Spot Colors and Swatches\n\n```javascript\n// Create a spot color\nvar spot = doc.spots.add();\nspot.name = \"My Spot Color\";\nspot.color = red; // Base color definition\n\nvar spotColor = new SpotColor();\nspotColor.spot = spot;\nspotColor.tint = 100;\n\nitem.fillColor = spotColor;\n\n// Access a swatch by name\nvar swatch = doc.swatches.getByName(\"PANTONE 185 C\");\nitem.fillColor = swatch.color;\n```\n\n## Working with Text\n\n### Text Frame Types\n\n```javascript\nvar doc = app.activeDocument;\n\n// Point text\nvar pointText = doc.textFrames.add();\npointText.contents = \"Hello World!\";\npointText.position = [100, 500];\n\n// Area text (text inside a path)\nvar rectPath = doc.pathItems.rectangle(500, 100, 200, 100);\nvar areaText = doc.textFrames.areaText(rectPath);\nareaText.contents = \"Text inside a rectangle shape.\";\n\n// Path text (text along a path)\nvar curvePath = doc.pathItems.add();\ncurvePath.setEntirePath([[50, 300], [150, 400], [250, 300]]);\nvar pathText = doc.textFrames.pathText(curvePath);\npathText.contents = \"Text on a path\";\n```\n\n### Character and Paragraph Formatting\n\n```javascript\nvar tf = doc.textFrames[0];\nvar textRange = tf.textRange;\n\n// Character attributes\nvar charAttr = textRange.characterAttributes;\ncharAttr.size = 24;           // Font size in points\ncharAttr.textFont = app.textFonts.getByName(\"ArialMT\");\ncharAttr.fillColor = red;\ncharAttr.tracking = 50;       // Em units\ncharAttr.horizontalScale = 100;\ncharAttr.verticalScale = 100;\ncharAttr.baselineShift = 0;\n\n// Paragraph attributes\nvar paraAttr = textRange.paragraphAttributes;\nparaAttr.justification = Justification.CENTER;\nparaAttr.firstLineIndent = 0;\nparaAttr.leftIndent = 0;\nparaAttr.spaceBefore = 0;\nparaAttr.spaceAfter = 0;\n```\n\n### Accessing Text Content\n\n```javascript\nvar tf = doc.textFrames[0];\n\n// Access sub-ranges\nvar firstChar = tf.characters[0];\nvar firstWord = tf.words[0];\nvar firstPara = tf.paragraphs[0];\nvar firstLine = tf.lines[0];\n\n// Modify specific ranges\ntf.words[0].characterAttributes.size = 36;\ntf.paragraphs[0].paragraphAttributes.justification = Justification.LEFT;\n```\n\n### Threading Text Frames\n\n```javascript\nvar frame1 = doc.textFrames.areaText(path1);\nvar frame2 = doc.textFrames.areaText(path2);\n\n// Link frames so text flows from frame1 to frame2\nframe1.nextFrame = frame2;\n\n// Stories represent the full text across threaded frames\nvar storyCount = doc.stories.length;\nvar fullText = doc.stories[0].textRange.contents;\n```\n\n## Working with Layers\n\n```javascript\nvar doc = app.activeDocument;\n\n// Create a layer\nvar newLayer = doc.layers.add();\nnewLayer.name = \"Background\";\nnewLayer.visible = true;\nnewLayer.locked = false;\nnewLayer.opacity = 100;\n\n// Access existing layers\nvar topLayer = doc.layers[0];\nvar layerByName = doc.layers.getByName(\"Background\");\n\n// Move items between layers\nvar item = doc.pathItems[0];\nitem.move(newLayer, ElementPlacement.PLACEATBEGINNING);\n\n// Reorder layers\nnewLayer.zOrder(ZOrderMethod.SENDTOBACK);\n```\n\n## Working with Selections\n\n```javascript\n// Get current selection\nvar sel = app.activeDocument.selection;\n\n// Iterate selected items\nfor (var i = 0; i < sel.length; i++) {\n    var item = sel[i];\n    // Check type using typename\n    if (item.typename === \"PathItem\") {\n        item.fillColor = red;\n    } else if (item.typename === \"TextFrame\") {\n        item.contents = \"Modified\";\n    }\n}\n\n// Select an item programmatically\ndoc.pathItems[0].selected = true;\n\n// Deselect all\ndoc.selection = null;\n```\n\n## Working with Symbols\n\n```javascript\n// Place a symbol instance\nvar sym = doc.symbols.getByName(\"MySymbol\");\nvar instance = doc.symbolItems.add(sym);\ninstance.position = [200, 400];\n\n// Access symbol definition\nvar symDef = instance.symbol;\n\n// Break link to symbol (expand to regular art)\ninstance.breakLink();\n```\n\n## Transformations\n\n```javascript\nvar item = doc.pathItems[0];\n\n// Rotate 45 degrees around center\nitem.rotate(45);\n\n// Scale to 50% width, 75% height\nitem.resize(50, 75);\n\n// Translate (move) by 100 points right and 50 points up\nitem.translate(100, 50);\n\n// Using a transformation matrix\nvar matrix = app.getIdentityMatrix();\nmatrix = app.concatenateRotationMatrix(matrix, 30);\nmatrix = app.concatenateScaleMatrix(matrix, 150, 150);\nitem.transform(matrix);\n```\n\n## Working with Artboards\n\n```javascript\nvar doc = app.activeDocument;\n\n// Access artboards\nvar ab = doc.artboards[0];\nvar rect = ab.artboardRect; // [left, top, right, bottom]\n\n// Create a new artboard\nvar newAB = doc.artboards.add([0, 0, 612, 792]); // Letter size\nnewAB.name = \"Page 2\";\n\n// Set active artboard\ndoc.artboards.setActiveArtboardIndex(1);\n```\n\n## Data-Driven Graphics (Variables and Datasets)\n\n```javascript\n// Variables link document items to data fields\nvar v = doc.variables.add();\nv.kind = VariableKind.TEXTUAL;\nv.name = \"headline\";\n\n// Link a text frame to the variable\nvar tf = doc.textFrames[0];\ntf.contentVariable = v;\n\n// Create datasets for batch content\nvar ds = doc.dataSets.add();\nds.name = \"Version 1\";\n// Dataset captures current variable bindings\n\n// Switch datasets to swap content\ndoc.dataSets[0].display();\n```\n\n## Printing\n\n```javascript\nvar doc = app.activeDocument;\nvar opts = new PrintOptions();\n\nopts.printPreset = \"Default\";\n\n// Paper options\nvar paperOpts = new PrintPaperOptions();\npaperOpts.name = \"Letter\";\nopts.paperOptions = paperOpts;\n\n// Job options\nvar jobOpts = new PrintJobOptions();\njobOpts.copies = 1;\njobOpts.designation = PrintArtworkDesignation.VISIBLELAYERS;\nopts.jobOptions = jobOpts;\n\ndoc.print(opts);\n```\n\n## User Interaction Levels\n\nControl whether Illustrator shows dialogs during script execution:\n\n```javascript\n// Suppress all dialogs\napp.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;\n\n// Perform operations that might prompt dialogs...\ndoc.close(SaveOptions.DONOTSAVECHANGES);\n\n// Restore dialog display\napp.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;\n```\n\n## Working with Methods (JavaScript-Specific)\n\nWhen calling methods with multiple optional parameters, use `undefined` to skip middle parameters:\n\n```javascript\n// rotate(angle, [changePositions], [changeFillPatterns], [changeFillGradients], ...)\nitem.rotate(30, undefined, undefined, true);\n```\n\n## Common Patterns\n\n### Iterate All Page Items in a Document\n\n```javascript\nfunction processAllItems(doc) {\n    for (var i = 0; i < doc.pageItems.length; i++) {\n        var item = doc.pageItems[i];\n        // Process based on type\n        switch (item.typename) {\n            case \"PathItem\":\n                // handle path\n                break;\n            case \"TextFrame\":\n                // handle text\n                break;\n            case \"GroupItem\":\n                // handle group (may contain nested items)\n                break;\n        }\n    }\n}\n```\n\n### Batch Process Files in a Folder\n\n```javascript\nvar folder = Folder.selectDialog(\"Select folder of .ai files\");\nif (folder) {\n    var files = folder.getFiles(\"*.ai\");\n    for (var i = 0; i < files.length; i++) {\n        var doc = app.open(files[i]);\n        // Process each document...\n        doc.close(SaveOptions.DONOTSAVECHANGES);\n    }\n}\n```\n\n### Error Handling\n\n```javascript\ntry {\n    var doc = app.activeDocument;\n    var layer = doc.layers.getByName(\"NonExistentLayer\");\n} catch (e) {\n    alert(\"Error: \" + e.message);\n    // e.message, e.line, e.fileName available\n}\n```\n\n## Troubleshooting\n\n- **\"undefined is not an object\"**: Usually means the collection is empty or the index is out of bounds. Check `.length` before accessing items.\n- **Script runs but nothing changes visually**: Call `app.redraw()` to force a screen refresh after modifications.\n- **Color mode mismatch**: Document color space (RGB vs CMYK) must match color objects. Use `doc.documentColorSpace` to check.\n- **Position seems wrong**: Remember scripted documents use bottom-left origin with Y increasing upward. The `position` property is the top-left of the bounding box.\n- **Text not appearing**: Ensure the text frame has a non-zero size. For point text, set `position`; for area text, provide a valid path to `areaText()`.\n- **File paths on Windows**: Use forward slashes (`/`) or double backslashes (`\\\\`) in path strings, or use the `File` object constructor.\n- **Dialog boxes interrupting batch scripts**: Set `app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS` before batch operations.\n- **Collections use `getByName()`**: Many collection objects support `getByName(\"name\")` which throws an error if not found; wrap in try/catch.\n\n## Scripting Constants Reference\n\nCommon enumeration constants used across the API:\n\n| Category | Constants |\n|---|---|\n| **Color Space** | `DocumentColorSpace.RGB`, `DocumentColorSpace.CMYK` |\n| **Justification** | `Justification.LEFT`, `Justification.CENTER`, `Justification.RIGHT`, `Justification.FULLJUSTIFY` |\n| **Point Type** | `PointType.SMOOTH`, `PointType.CORNER` |\n| **Stroke Cap** | `StrokeCap.BUTTENDCAP`, `StrokeCap.ROUNDENDCAP`, `StrokeCap.PROJECTINGENDCAP` |\n| **Stroke Join** | `StrokeJoin.MITERENDJOIN`, `StrokeJoin.ROUNDENDJOIN`, `StrokeJoin.BEVELENDJOIN` |\n| **Blend Mode** | `BlendModes.NORMAL`, `BlendModes.MULTIPLY`, `BlendModes.SCREEN`, `BlendModes.OVERLAY` |\n| **Save Options** | `SaveOptions.SAVECHANGES`, `SaveOptions.DONOTSAVECHANGES`, `SaveOptions.PROMPTTOSAVECHANGES` |\n| **Export Type** | `ExportType.PNG24`, `ExportType.PNG8`, `ExportType.JPEG`, `ExportType.SVG`, `ExportType.TIFF`, `ExportType.PHOTOSHOP`, `ExportType.AUTOCAD`, `ExportType.FLASH` |\n| **Element Placement** | `ElementPlacement.PLACEATBEGINNING`, `ElementPlacement.PLACEATEND`, `ElementPlacement.PLACEBEFORE`, `ElementPlacement.PLACEAFTER`, `ElementPlacement.INSIDE` |\n| **Z-Order** | `ZOrderMethod.BRINGTOFRONT`, `ZOrderMethod.SENDTOBACK`, `ZOrderMethod.BRINGFORWARD`, `ZOrderMethod.SENDBACKWARD` |\n| **Gradient Type** | `GradientType.LINEAR`, `GradientType.RADIAL` |\n| **Text Frame Kind** | `TextType.POINTTEXT`, `TextType.AREATEXT`, `TextType.PATHTEXT` |\n| **Variable Kind** | `VariableKind.TEXTUAL`, `VariableKind.IMAGE`, `VariableKind.VISIBILITY`, `VariableKind.GRAPH` |\n| **User Interaction** | `UserInteractionLevel.DISPLAYALERTS`, `UserInteractionLevel.DONTDISPLAYALERTS` |\n| **Compatibility** | `Compatibility.ILLUSTRATOR10` through `Compatibility.ILLUSTRATOR24` |\n\n## JavaScript Object Reference (Complete API Object List)\n\nThe Illustrator JavaScript API contains the following objects, grouped by category:\n\n### Core Objects\n\n`Application`, `Document`, `Documents`, `DocumentPreset`, `Layer`, `Layers`, `PageItem`, `PageItems`, `View`, `Views`, `Preferences`\n\n### Path and Shape Objects\n\n`PathItem`, `PathItems`, `PathPoint`, `PathPoints`, `CompoundPathItem`, `CompoundPathItems`, `GroupItem`, `GroupItems`\n\n### Text Objects\n\n`TextFrame`, `TextRange`, `TextRanges`, `TextPath`, `Characters`, `Words`, `Paragraphs`, `Lines`, `InsertionPoint`, `InsertionPoints`, `Story`, `Stories`, `CharacterAttributes`, `ParagraphAttributes`, `CharacterStyle`, `CharacterStyles`, `ParagraphStyle`, `ParagraphStyles`, `TextFont`, `TextFonts`, `TabStopInfo`\n\n### Color Objects\n\n`RGBColor`, `CMYKColor`, `GrayColor`, `LabColor`, `NoColor`, `SpotColor`, `Spot`, `Spots`, `PatternColor`, `GradientColor`, `Color`, `Gradient`, `Gradients`, `GradientStop`, `GradientStops`\n\n### Swatch and Style Objects\n\n`Swatch`, `Swatches`, `SwatchGroup`, `SwatchGroups`, `GraphicStyle`, `GraphicStyles`, `Pattern`, `Patterns`, `Brush`, `Brushes`\n\n### Symbol Objects\n\n`Symbol`, `Symbols`, `SymbolItem`, `SymbolItems`\n\n### Artboard Objects\n\n`Artboard`, `Artboards`\n\n### Placed and Raster Objects\n\n`PlacedItem`, `PlacedItems`, `RasterItem`, `RasterItems`, `MeshItem`, `MeshItems`, `GraphItem`, `GraphItems`, `PluginItem`, `PluginItems`, `NonNativeItem`, `NonNativeItems`, `LegacyTextItem`, `LegacyTextItems`\n\n### Data-Driven Objects\n\n`Variable`, `Variables`, `Dataset`, `Datasets`\n\n### Matrix and Transform Objects\n\n`Matrix`\n\n### Tag Objects\n\n`Tag`, `Tags`\n\n### Tracing Objects\n\n`TracingObject`, `TracingOptions`\n\n### Save and Export Options\n\n`IllustratorSaveOptions`, `EPSSaveOptions`, `PDFSaveOptions`, `FXGSaveOptions`, `ExportOptionsAutoCAD`, `ExportOptionsFlash`, `ExportOptionsGIF`, `ExportOptionsJPEG`, `ExportOptionsPhotoshop`, `ExportOptionsPNG8`, `ExportOptionsPNG24`, `ExportOptionsSVG`, `ExportOptionsTIFF`\n\n### Open Options\n\n`OpenOptions`, `OpenOptionsAutoCAD`, `OpenOptionsFreeHand`, `OpenOptionsPhotoshop`, `PDFFileOptions`, `PhotoshopFileOptions`\n\n### Print Objects\n\n`PrintOptions`, `PrintJobOptions`, `PrintPaperOptions`, `PrintColorManagementOptions`, `PrintColorSeparationOptions`, `PrintCoordinateOptions`, `PrintFlattenerOptions`, `PrintFontOptions`, `PrintPageMarksOptions`, `PrintPostScriptOptions`, `Printer`, `PrinterInfo`, `Paper`, `PaperInfo`, `PPDFile`, `PPDFileInfo`, `Ink`, `InkInfo`, `Screen`, `ScreenInfo`, `ScreenSpotFunction`\n\n### Image and Rasterize Options\n\n`ImageCaptureOptions`, `RasterEffectOptions`, `RasterizeOptions`\n\n## References\n\n- [Changelog](https://ai-scripting.docsforadobe.dev/introduction/changelog/) - Recent scripting API changes (CC 2020 added `Document.getPageItemFromUuid` and `PageItem.uuid`; CC 2017 added `Application.getIsFileOpen`)\n- [Illustrator Scripting Guide](https://ai-scripting.docsforadobe.dev/) - Full community-maintained documentation\n\nFile v1.0.1:_meta.json\n\n{\n  \"ownerId\": \"kn71kvdba3t2jfkk6nbgnytg0s81617g\",\n  \"slug\": \"adobe-illustrator-scripting\",\n  \"version\": \"1.0.1\",\n  \"publishedAt\": 1776642759824\n}\n\nFile v1.0.1:references/object-model-quick-reference.md\n\n# Illustrator JavaScript Object Model Quick Reference\n\n## Containment Hierarchy\n\n```\nApplication (app)\n └─ Document\n     ├─ Layer\n     │   ├─ pathItems[]        → PathItem → PathPoint[]\n     │   ├─ compoundPathItems[] → CompoundPathItem\n     │   ├─ textFrames[]       → TextFrame\n     │   │   ├─ characters[]   → TextRange (single char)\n     │   │   ├─ words[]        → TextRange (word)\n     │   │   ├─ paragraphs[]   → TextRange (paragraph)\n     │   │   ├─ lines[]        → TextRange (line)\n     │   │   └─ insertionPoints[]\n     │   ├─ placedItems[]      → PlacedItem\n     │   ├─ rasterItems[]      → RasterItem\n     │   ├─ meshItems[]        → MeshItem\n     │   ├─ pluginItems[]      → PluginItem\n     │   ├─ graphItems[]       → GraphItem\n     │   ├─ symbolItems[]      → SymbolItem → Symbol\n     │   ├─ groupItems[]       → GroupItem (recursive pageItems)\n     │   ├─ nonNativeItems[]   → NonNativeItem\n     │   └─ legacyTextItems[]  → LegacyTextItem\n     ├─ Artboard[]\n     ├─ Swatch[] / Spot[] / Gradient[] / Pattern[]\n     ├─ GraphicStyle[] / Brush[] / Symbol[]\n     ├─ Story[]\n     ├─ CharacterStyle[] / ParagraphStyle[]\n     ├─ Variable[] / Dataset[]\n     └─ View[]\n```\n\n## Artwork Item Types (pageItems members)\n\n| Type | typename | Collection | Notes |\n|---|---|---|---|\n| Path | `PathItem` | `pathItems` | Lines, shapes, freeform paths |\n| Compound path | `CompoundPathItem` | `compoundPathItems` | Multiple paths combined |\n| Group | `GroupItem` | `groupItems` | Contains nested pageItems |\n| Text frame | `TextFrame` | `textFrames` | Point, area, or path text |\n| Placed image | `PlacedItem` | `placedItems` | Linked external files |\n| Raster image | `RasterItem` | `rasterItems` | Embedded bitmaps |\n| Mesh | `MeshItem` | `meshItems` | Gradient mesh objects |\n| Graph | `GraphItem` | `graphItems` | Chart/graph objects |\n| Plugin item | `PluginItem` | `pluginItems` | Plugin-generated art |\n| Symbol instance | `SymbolItem` | `symbolItems` | Instance of a Symbol |\n| Non-native | `NonNativeItem` | `nonNativeItems` | Foreign objects |\n| Legacy text | `LegacyTextItem` | `legacyTextItems` | Pre-CS text objects |\n\n## Color Object Types\n\n| Object | Color Space | Value Range | Notes |\n|---|---|---|---|\n| `RGBColor` | RGB | 0-255 per channel | `.red`, `.green`, `.blue` |\n| `CMYKColor` | CMYK | 0-100 per channel | `.cyan`, `.magenta`, `.yellow`, `.black` |\n| `GrayColor` | Grayscale | 0-100 | `.gray` (0=black, 100=white) |\n| `LabColor` | Lab | L: 0-100, a/b: -128 to 127 | `.l`, `.a`, `.b` |\n| `SpotColor` | Spot | tint 0-100 | `.spot`, `.tint` |\n| `PatternColor` | Pattern | - | `.pattern`, `.matrix` |\n| `GradientColor` | Gradient | - | `.gradient`, `.origin`, `.angle` |\n| `NoColor` | None | - | Transparent/no fill |\n\n## Common Scripting Constants\n\n### Document and Color\n\n- `DocumentColorSpace.RGB` / `.CMYK`\n\n### Text\n\n- `Justification.LEFT` / `.CENTER` / `.RIGHT` / `.FULLJUSTIFY` / `.FULLJUSTIFYLASTLINELEFT` / `.FULLJUSTIFYLASTLINECENTER` / `.FULLJUSTIFYLASTLINERIGHT`\n- `TextType.POINTTEXT` / `.AREATEXT` / `.PATHTEXT`\n- `FontBaselineOption.NORMALBASELINE` / `.SUPERSCRIPT` / `.SUBSCRIPT`\n\n### Paths\n\n- `PointType.SMOOTH` / `.CORNER`\n- `StrokeCap.BUTTENDCAP` / `.ROUNDENDCAP` / `.PROJECTINGENDCAP`\n- `StrokeJoin.MITERENDJOIN` / `.ROUNDENDJOIN` / `.BEVELENDJOIN`\n\n### Transformations\n\n- `Transformation.DOCUMENTORIGIN` / `.BOTTOM` / `.BOTTOMLEFT` / `.BOTTOMRIGHT` / `.CENTER` / `.LEFT` / `.RIGHT` / `.TOP` / `.TOPLEFT` / `.TOPRIGHT`\n\n### Blend Modes\n\n- `BlendModes.NORMAL` / `.MULTIPLY` / `.SCREEN` / `.OVERLAY` / `.SOFTLIGHT` / `.HARDLIGHT` / `.COLORDODGE` / `.COLORBURN` / `.DARKEN` / `.LIGHTEN` / `.DIFFERENCE` / `.EXCLUSION` / `.HUE` / `.SATURATIONBLEND` / `.COLORBLEND` / `.LUMINOSITY`\n\n### Element Placement\n\n- `ElementPlacement.PLACEATBEGINNING` / `.PLACEATEND` / `.PLACEBEFORE` / `.PLACEAFTER` / `.INSIDE`\n\n### Z-Order\n\n- `ZOrderMethod.BRINGTOFRONT` / `.SENDTOBACK` / `.BRINGFORWARD` / `.SENDBACKWARD`\n\n### Save/Export\n\n- `SaveOptions.SAVECHANGES` / `.DONOTSAVECHANGES` / `.PROMPTTOSAVECHANGES`\n- `ExportType.PNG24` / `.PNG8` / `.JPEG` / `.SVG` / `.TIFF` / `.PHOTOSHOP` / `.AUTOCAD` / `.FLASH` / `.GIF`\n- `Compatibility.ILLUSTRATOR8` through `.ILLUSTRATOR24`\n- `PDFCompatibility.ACROBAT4` through `.ACROBAT8`\n\n### Gradient\n\n- `GradientType.LINEAR` / `.RADIAL`\n\n### Variables\n\n- `VariableKind.TEXTUAL` / `.IMAGE` / `.VISIBILITY` / `.GRAPH`\n\n### User Interaction\n\n- `UserInteractionLevel.DISPLAYALERTS` / `.DONTDISPLAYALERTS`\n\n### Print\n\n- `PrintArtworkDesignation.ALLLAYERS` / `.VISIBLELAYERS` / `.VISIBLEPRINTABLELAYERS`\n\n## Unit Conversions\n\n| From | To Points | Formula |\n|---|---|---|\n| Inches | Points | `inches * 72` |\n| Centimeters | Points | `cm * 28.346` |\n| Millimeters | Points | `mm * 2.834645` |\n| Picas | Points | `picas * 12` |\n| Em units | Points | `(emUnits * fontSize) / 1000` |\n\nArchive v1.0.0: 6 files, 12627 bytes\n\nFiles: references/object-model-quick-reference.md (5017b), scripts/batch-export-png.jsx (1339b), scripts/create-color-grid.jsx (1146b), scripts/find-replace-text.jsx (893b), SKILL.md (22815b), _meta.json (146b)\n\nFile v1.0.0:SKILL.md\n\n---\nname: adobe-illustrator-scripting\ndescription: 'Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate documents, layers, paths, text frames, colors, symbols, artboards, or any Illustrator DOM objects. Covers the complete JavaScript object model, coordinate system, measurement units, export workflows, and scripting best practices.'\n---\n\n# Adobe Illustrator Scripting\n\nExpert guidance for automating Adobe Illustrator through ExtendScript (JavaScript/JSX). This skill covers the Illustrator scripting object model, all major API objects, code patterns, and best practices for writing production-quality `.jsx` scripts.\n\n## When to Use This Skill\n\n- Writing new Illustrator automation scripts (`.jsx` or `.js` files)\n- Debugging or fixing existing Illustrator ExtendScript code\n- Manipulating documents, layers, page items, paths, text, or colors programmatically\n- Batch-processing Illustrator files or generating artwork from data\n- Exporting documents to various formats (PDF, SVG, PNG, EPS, etc.)\n- Working with the Illustrator DOM (Application, Document, Layer, PathItem, TextFrameItem, etc.)\n- Creating data-driven graphics using variables and datasets\n- Automating print workflows with scripted print options\n\n## Prerequisites\n\n- Adobe Illustrator CC or later installed\n- Basic JavaScript knowledge (ExtendScript is ES3-based with Adobe extensions)\n- Scripts are executed via File > Scripts > Other Scripts, the Scripts menu, or placed in the Startup Scripts folder\n- The ExtendScript Toolkit (ESTK) or any text editor can be used to write `.jsx` files\n\n## Scripting Environment\n\n### Language and File Extensions\n\n| Language | Extension | Platform |\n|---|---|---|\n| ExtendScript/JavaScript | `.jsx`, `.js` | Windows, macOS |\n| AppleScript | `.scpt` | macOS only |\n| VBScript | `.vbs` | Windows only |\n\n**This skill focuses on ExtendScript/JavaScript** as the cross-platform, most widely used option.\n\n### Executing Scripts\n\n- **Scripts menu**: File > Scripts lists scripts from the application scripts folder\n- **Other Scripts**: File > Scripts > Other Scripts to browse and run any `.jsx` file\n- **Startup Scripts**: Place scripts in the Startup Scripts folder to run automatically on launch\n- **Target directive**: Begin scripts with `#target illustrator` when running from ESTK or external tools\n- **`#targetengine` directive**: Use `#targetengine \"session\"` to persist variables across script executions\n\n### Naming Conventions (JavaScript)\n\n- Objects and properties use **camelCase**: `activeDocument`, `pathItems`, `textFrames`\n- The `app` global references the `Application` object\n- Collection indices are **zero-based**: `documents[0]` is the frontmost document\n- Use `typename` property to identify object types at runtime\n\n## Object Model Overview\n\nThe Illustrator DOM follows a strict containment hierarchy:\n\n```\nApplication (app)\n├── activeDocument / documents[]\n│   ├── layers[]\n│   │   ├── pageItems[] (all artwork)\n│   │   ├── pathItems[]\n│   │   ├── compoundPathItems[]\n│   │   ├── textFrames[]\n│   │   ├── placedItems[]\n│   │   ├── rasterItems[]\n│   │   ├── meshItems[]\n│   │   ├── pluginItems[]\n│   │   ├── graphItems[]\n│   │   ├── symbolItems[]\n│   │   ├── nonNativeItems[]\n│   │   ├── legacyTextItems[]\n│   │   └── groupItems[]\n│   ├── artboards[]\n│   ├── views[]\n│   ├── selection (array of selected items)\n│   ├── swatches[], spots[], gradients[], patterns[]\n│   ├── graphicStyles[], brushes[], symbols[]\n│   ├── textFonts[] (via app.textFonts)\n│   ├── stories[], characterStyles[], paragraphStyles[]\n│   ├── variables[], datasets[]\n│   └── inkList[], printOptions\n├── preferences\n├── printerList[]\n└── textFonts[]\n```\n\n### Top-Level Objects\n\n- **Application** (`app`): The root object. Provides access to documents, preferences, fonts, and printers. Key properties: `activeDocument`, `documents`, `textFonts`, `printerList`, `userInteractionLevel`, `version`.\n- **Document**: Represents an open `.ai` file. Key properties: `layers`, `pageItems`, `selection`, `activeLayer`, `width`, `height`, `rulerOrigin`, `documentColorSpace`. Key methods: `saveAs()`, `exportFile()`, `close()`, `print()`.\n- **Layer**: A drawing layer. Key properties: `pageItems`, `pathItems`, `textFrames`, `visible`, `locked`, `opacity`, `name`, `zOrderPosition`, `color`.\n\n## Measurement Units and Coordinates\n\n### Units\n\nAll scripting API values use **points** (72 points = 1 inch). Convert other units:\n\n| Unit | Conversion |\n|---|---|\n| Inches | multiply by 72 |\n| Centimeters | multiply by 28.346 |\n| Millimeters | multiply by 2.834645 |\n| Picas | multiply by 12 |\n\nKerning, tracking, and `aki` properties use **em units** (thousandths of an em, proportional to font size).\n\n### Coordinate System\n\n- For **scripted documents**, the origin `(0,0)` is at the **bottom-left** of the artboard\n- X increases left to right; Y increases bottom to top\n- The `position` property of a page item is the **top-left corner** of its bounding box as `[x, y]`\n- Maximum page item width/height: 16348 points\n\n### Art Item Bounds\n\nEvery page item has three bounding rectangles:\n\n- `geometricBounds`: Excludes stroke width `[left, top, right, bottom]`\n- `visibleBounds`: Includes stroke width\n- `controlBounds`: Includes control/direction points\n\n## Working with Documents\n\n### Creating and Opening\n\n```javascript\n// Create a new document\nvar doc = app.documents.add();\n\n// Create with a preset\nvar preset = new DocumentPreset();\npreset.width = 612;  // 8.5 inches\npreset.height = 792; // 11 inches\npreset.colorMode = DocumentColorSpace.CMYK;\nvar doc = app.documents.addDocument(\"Print\", preset);\n\n// Open an existing file\nvar fileRef = new File(\"/path/to/file.ai\");\nvar doc = app.open(fileRef);\n```\n\n### Saving and Exporting\n\n```javascript\n// Save as Illustrator format\nvar saveOpts = new IllustratorSaveOptions();\nsaveOpts.compatibility = Compatibility.ILLUSTRATOR17; // CC\ndoc.saveAs(new File(\"/path/to/output.ai\"), saveOpts);\n\n// Export as PDF\nvar pdfOpts = new PDFSaveOptions();\npdfOpts.compatibility = PDFCompatibility.ACROBAT7;\npdfOpts.preserveEditability = false;\ndoc.saveAs(new File(\"/path/to/output.pdf\"), pdfOpts);\n\n// Export as PNG\nvar pngOpts = new ExportOptionsPNG24();\npngOpts.horizontalScale = 300;\npngOpts.verticalScale = 300;\npngOpts.transparency = true;\ndoc.exportFile(new File(\"/path/to/output.png\"), ExportType.PNG24, pngOpts);\n\n// Export as SVG\nvar svgOpts = new ExportOptionsSVG();\nsvgOpts.fontType = SVGFontType.OUTLINEFONT;\ndoc.exportFile(new File(\"/path/to/output.svg\"), ExportType.SVG, svgOpts);\n```\n\n## Working with Paths and Shapes\n\n### Built-in Shape Methods\n\nThe `pathItems` collection provides convenience methods for common shapes:\n\n```javascript\nvar doc = app.activeDocument;\nvar layer = doc.activeLayer;\n\n// Rectangle: rectangle(top, left, width, height)\nvar rect = layer.pathItems.rectangle(500, 100, 200, 150);\n\n// Rounded rectangle: roundedRectangle(top, left, width, height, hRadius, vRadius)\nvar rrect = layer.pathItems.roundedRectangle(500, 100, 200, 150, 20, 20);\n\n// Ellipse: ellipse(top, left, width, height)\nvar oval = layer.pathItems.ellipse(400, 200, 100, 100);\n\n// Polygon: polygon(centerX, centerY, radius, sides)\nvar hex = layer.pathItems.polygon(300, 300, 50, 6);\n\n// Star: star(centerX, centerY, radius, innerRadius, points)\nvar star = layer.pathItems.star(300, 300, 50, 25, 5);\n```\n\n### Freeform Paths Using Coordinate Arrays\n\n```javascript\nvar doc = app.activeDocument;\nvar path = doc.pathItems.add();\npath.setEntirePath([[100, 100], [200, 200], [300, 100]]);\npath.closed = false;\npath.stroked = true;\npath.strokeWidth = 2;\n```\n\n### Freeform Paths Using PathPoint Objects\n\n```javascript\nvar doc = app.activeDocument;\nvar path = doc.pathItems.add();\n\nvar point1 = path.pathPoints.add();\npoint1.anchor = [100, 100];\npoint1.leftDirection = [100, 100];\npoint1.rightDirection = [150, 150];\npoint1.pointType = PointType.SMOOTH;\n\nvar point2 = path.pathPoints.add();\npoint2.anchor = [300, 100];\npoint2.leftDirection = [250, 150];\npoint2.rightDirection = [300, 100];\npoint2.pointType = PointType.SMOOTH;\n\npath.closed = false;\n```\n\n### Path Properties\n\n```javascript\nvar item = doc.pathItems[0];\nitem.filled = true;\nitem.stroked = true;\nitem.strokeWidth = 1.5;\nitem.strokeCap = StrokeCap.ROUNDENDCAP;\nitem.strokeJoin = StrokeJoin.ROUNDENDJOIN;\nitem.opacity = 80;\nitem.closed = true;\n```\n\n## Working with Colors\n\n### Color Objects\n\n```javascript\n// RGB Color (values 0-255)\nvar red = new RGBColor();\nred.red = 255;\nred.green = 0;\nred.blue = 0;\n\n// CMYK Color (values 0-100)\nvar cyan = new CMYKColor();\ncyan.cyan = 100;\ncyan.magenta = 0;\ncyan.yellow = 0;\ncyan.black = 0;\n\n// Grayscale (0-100, 0 = black)\nvar gray = new GrayColor();\ngray.gray = 50;\n\n// Lab Color\nvar lab = new LabColor();\nlab.l = 50;\nlab.a = 20;\nlab.b = -30;\n\n// No color (transparent)\nvar none = new NoColor();\n```\n\n### Applying Colors\n\n```javascript\nvar item = doc.pathItems[0];\nitem.fillColor = red;\nitem.strokeColor = cyan;\n\n// Gradient fill\nvar gradient = doc.gradients.add();\ngradient.type = GradientType.LINEAR;\ngradient.gradientStops[0].color = red;\ngradient.gradientStops[1].color = cyan;\n\nvar gradColor = new GradientColor();\ngradColor.gradient = gradient;\nitem.fillColor = gradColor;\n```\n\n### Spot Colors and Swatches\n\n```javascript\n// Create a spot color\nvar spot = doc.spots.add();\nspot.name = \"My Spot Color\";\nspot.color = red; // Base color definition\n\nvar spotColor = new SpotColor();\nspotColor.spot = spot;\nspotColor.tint = 100;\n\nitem.fillColor = spotColor;\n\n// Access a swatch by name\nvar swatch = doc.swatches.getByName(\"PANTONE 185 C\");\nitem.fillColor = swatch.color;\n```\n\n## Working with Text\n\n### Text Frame Types\n\n```javascript\nvar doc = app.activeDocument;\n\n// Point text\nvar pointText = doc.textFrames.add();\npointText.contents = \"Hello World!\";\npointText.position = [100, 500];\n\n// Area text (text inside a path)\nvar rectPath = doc.pathItems.rectangle(500, 100, 200, 100);\nvar areaText = doc.textFrames.areaText(rectPath);\nareaText.contents = \"Text inside a rectangle shape.\";\n\n// Path text (text along a path)\nvar curvePath = doc.pathItems.add();\ncurvePath.setEntirePath([[50, 300], [150, 400], [250, 300]]);\nvar pathText = doc.textFrames.pathText(curvePath);\npathText.contents = \"Text on a path\";\n```\n\n### Character and Paragraph Formatting\n\n```javascript\nvar tf = doc.textFrames[0];\nvar textRange = tf.textRange;\n\n// Character attributes\nvar charAttr = textRange.characterAttributes;\ncharAttr.size = 24;           // Font size in points\ncharAttr.textFont = app.textFonts.getByName(\"ArialMT\");\ncharAttr.fillColor = red;\ncharAttr.tracking = 50;       // Em units\ncharAttr.horizontalScale = 100;\ncharAttr.verticalScale = 100;\ncharAttr.baselineShift = 0;\n\n// Paragraph attributes\nvar paraAttr = textRange.paragraphAttributes;\nparaAttr.justification = Justification.CENTER;\nparaAttr.firstLineIndent = 0;\nparaAttr.leftIndent = 0;\nparaAttr.spaceBefore = 0;\nparaAttr.spaceAfter = 0;\n```\n\n### Accessing Text Content\n\n```javascript\nvar tf = doc.textFrames[0];\n\n// Access sub-ranges\nvar firstChar = tf.characters[0];\nvar firstWord = tf.words[0];\nvar firstPara = tf.paragraphs[0];\nvar firstLine = tf.lines[0];\n\n// Modify specific ranges\ntf.words[0].characterAttributes.size = 36;\ntf.paragraphs[0].paragraphAttributes.justification = Justification.LEFT;\n```\n\n### Threading Text Frames\n\n```javascript\nvar frame1 = doc.textFrames.areaText(path1);\nvar frame2 = doc.textFrames.areaText(path2);\n\n// Link frames so text flows from frame1 to frame2\nframe1.nextFrame = frame2;\n\n// Stories represent the full text across threaded frames\nvar storyCount = doc.stories.length;\nvar fullText = doc.stories[0].textRange.contents;\n```\n\n## Working with Layers\n\n```javascript\nvar doc = app.activeDocument;\n\n// Create a layer\nvar newLayer = doc.layers.add();\nnewLayer.name = \"Background\";\nnewLayer.visible = true;\nnewLayer.locked = false;\nnewLayer.opacity = 100;\n\n// Access existing layers\nvar topLayer = doc.layers[0];\nvar layerByName = doc.layers.getByName(\"Background\");\n\n// Move items between layers\nvar item = doc.pathItems[0];\nitem.move(newLayer, ElementPlacement.PLACEATBEGINNING);\n\n// Reorder layers\nnewLayer.zOrder(ZOrderMethod.SENDTOBACK);\n```\n\n## Working with Selections\n\n```javascript\n// Get current selection\nvar sel = app.activeDocument.selection;\n\n// Iterate selected items\nfor (var i = 0; i < sel.length; i++) {\n    var item = sel[i];\n    // Check type using typename\n    if (item.typename === \"PathItem\") {\n        item.fillColor = red;\n    } else if (item.typename === \"TextFrame\") {\n        item.contents = \"Modified\";\n    }\n}\n\n// Select an item programmatically\ndoc.pathItems[0].selected = true;\n\n// Deselect all\ndoc.selection = null;\n```\n\n## Working with Symbols\n\n```javascript\n// Place a symbol instance\nvar sym = doc.symbols.getByName(\"MySymbol\");\nvar instance = doc.symbolItems.add(sym);\ninstance.position = [200, 400];\n\n// Access symbol definition\nvar symDef = instance.symbol;\n\n// Break link to symbol (expand to regular art)\ninstance.breakLink();\n```\n\n## Transformations\n\n```javascript\nvar item = doc.pathItems[0];\n\n// Rotate 45 degrees around center\nitem.rotate(45);\n\n// Scale to 50% width, 75% height\nitem.resize(50, 75);\n\n// Translate (move) by 100 points right and 50 points up\nitem.translate(100, 50);\n\n// Using a transformation matrix\nvar matrix = app.getIdentityMatrix();\nmatrix = app.concatenateRotationMatrix(matrix, 30);\nmatrix = app.concatenateScaleMatrix(matrix, 150, 150);\nitem.transform(matrix);\n```\n\n## Working with Artboards\n\n```javascript\nvar doc = app.activeDocument;\n\n// Access artboards\nvar ab = doc.artboards[0];\nvar rect = ab.artboardRect; // [left, top, right, bottom]\n\n// Create a new artboard\nvar newAB = doc.artboards.add([0, 0, 612, 792]); // Letter size\nnewAB.name = \"Page 2\";\n\n// Set active artboard\ndoc.artboards.setActiveArtboardIndex(1);\n```\n\n## Data-Driven Graphics (Variables and Datasets)\n\n```javascript\n// Variables link document items to data fields\nvar v = doc.variables.add();\nv.kind = VariableKind.TEXTUAL;\nv.name = \"headline\";\n\n// Link a text frame to the variable\nvar tf = doc.textFrames[0];\ntf.contentVariable = v;\n\n// Create datasets for batch content\nvar ds = doc.dataSets.add();\nds.name = \"Version 1\";\n// Dataset captures current variable bindings\n\n// Switch datasets to swap content\ndoc.dataSets[0].display();\n```\n\n## Printing\n\n```javascript\nvar doc = app.activeDocument;\nvar opts = new PrintOptions();\n\nopts.printPreset = \"Default\";\n\n// Paper options\nvar paperOpts = new PrintPaperOptions();\npaperOpts.name = \"Letter\";\nopts.paperOptions = paperOpts;\n\n// Job options\nvar jobOpts = new PrintJobOptions();\njobOpts.copies = 1;\njobOpts.designation = PrintArtworkDesignation.VISIBLELAYERS;\nopts.jobOptions = jobOpts;\n\ndoc.print(opts);\n```\n\n## User Interaction Levels\n\nControl whether Illustrator shows dialogs during script execution:\n\n```javascript\n// Suppress all dialogs\napp.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS;\n\n// Perform operations that might prompt dialogs...\ndoc.close(SaveOptions.DONOTSAVECHANGES);\n\n// Restore dialog display\napp.userInteractionLevel = UserInteractionLevel.DISPLAYALERTS;\n```\n\n## Working with Methods (JavaScript-Specific)\n\nWhen calling methods with multiple optional parameters, use `undefined` to skip middle parameters:\n\n```javascript\n// rotate(angle, [changePositions], [changeFillPatterns], [changeFillGradients], ...)\nitem.rotate(30, undefined, undefined, true);\n```\n\n## Common Patterns\n\n### Iterate All Page Items in a Document\n\n```javascript\nfunction processAllItems(doc) {\n    for (var i = 0; i < doc.pageItems.length; i++) {\n        var item = doc.pageItems[i];\n        // Process based on type\n        switch (item.typename) {\n            case \"PathItem\":\n                // handle path\n                break;\n            case \"TextFrame\":\n                // handle text\n                break;\n            case \"GroupItem\":\n                // handle group (may contain nested items)\n                break;\n        }\n    }\n}\n```\n\n### Batch Process Files in a Folder\n\n```javascript\nvar folder = Folder.selectDialog(\"Select folder of .ai files\");\nif (folder) {\n    var files = folder.getFiles(\"*.ai\");\n    for (var i = 0; i < files.length; i++) {\n        var doc = app.open(files[i]);\n        // Process each document...\n        doc.close(SaveOptions.DONOTSAVECHANGES);\n    }\n}\n```\n\n### Error Handling\n\n```javascript\ntry {\n    var doc = app.activeDocument;\n    var layer = doc.layers.getByName(\"NonExistentLayer\");\n} catch (e) {\n    alert(\"Error: \" + e.message);\n    // e.message, e.line, e.fileName available\n}\n```\n\n## Troubleshooting\n\n- **\"undefined is not an object\"**: Usually means the collection is empty or the index is out of bounds. Check `.length` before accessing items.\n- **Script runs but nothing changes visually**: Call `app.redraw()` to force a screen refresh after modifications.\n- **Color mode mismatch**: Document color space (RGB vs CMYK) must match color objects. Use `doc.documentColorSpace` to check.\n- **Position seems wrong**: Remember scripted documents use bottom-left origin with Y increasing upward. The `position` property is the top-left of the bounding box.\n- **Text not appearing**: Ensure the text frame has a non-zero size. For point text, set `position`; for area text, provide a valid path to `areaText()`.\n- **File paths on Windows**: Use forward slashes (`/`) or double backslashes (`\\\\`) in path strings, or use the `File` object constructor.\n- **Dialog boxes interrupting batch scripts**: Set `app.userInteractionLevel = UserInteractionLevel.DONTDISPLAYALERTS` before batch operations.\n- **Collections use `getByName()`**: Many collection objects support `getByName(\"name\")` which throws an error if not found; wrap in try/catch.\n\n## Scripting Constants Reference\n\nCommon enumeration constants used across the API:\n\n| Category | Constants |\n|---|---|\n| **Color Space** | `DocumentColorSpace.RGB`, `DocumentColorSpace.CMYK` |\n| **Justification** | `Justification.LEFT`, `Justification.CENTER`, `Justification.RIGHT`, `Justification.FULLJUSTIFY` |\n| **Point Type** | `PointType.SMOOTH`, `PointType.CORNER` |\n| **Stroke Cap** | `StrokeCap.BUTTENDCAP`, `StrokeCap.ROUNDENDCAP`, `StrokeCap.PROJECTINGENDCAP` |\n| **Stroke Join** | `StrokeJoin.MITERENDJOIN`, `StrokeJoin.ROUNDENDJOIN`, `StrokeJoin.BEVELENDJOIN` |\n| **Blend Mode** | `BlendModes.NORMAL`, `BlendModes.MULTIPLY`, `BlendModes.SCREEN`, `BlendModes.OVERLAY` |\n| **Save Options** | `SaveOptions.SAVECHANGES`, `SaveOptions.DONOTSAVECHANGES`, `SaveOptions.PROMPTTOSAVECHANGES` |\n| **Export Type** | `ExportType.PNG24`, `ExportType.PNG8`, `ExportType.JPEG`, `ExportType.SVG`, `ExportType.TIFF`, `ExportType.PHOTOSHOP`, `ExportType.AUTOCAD`, `ExportType.FLASH` |\n| **Element Placement** | `ElementPlacement.PLACEATBEGINNING`, `ElementPlacement.PLACEATEND`, `ElementPlacement.PLACEBEFORE`, `ElementPlacement.PLACEAFTER`, `ElementPlacement.INSIDE` |\n| **Z-Order** | `ZOrderMethod.BRINGTOFRONT`, `ZOrderMethod.SENDTOBACK`, `ZOrderMethod.BRINGFORWARD`, `ZOrderMethod.SENDBACKWARD` |\n| **Gradient Type** | `GradientType.LINEAR`, `GradientType.RADIAL` |\n| **Text Frame Kind** | `TextType.POINTTEXT`, `TextType.AREATEXT`, `TextType.PATHTEXT` |\n| **Variable Kind** | `VariableKind.TEXTUAL`, `VariableKind.IMAGE`, `VariableKind.VISIBILITY`, `VariableKind.GRAPH` |\n| **User Interaction** | `UserInteractionLevel.DISPLAYALERTS`, `UserInteractionLevel.DONTDISPLAYALERTS` |\n| **Compatibility** | `Compatibility.ILLUSTRATOR10` through `Compatibility.ILLUSTRATOR24` |\n\n## JavaScript Object Reference (Complete API Object List)\n\nThe Illustrator JavaScript API contains the following objects, grouped by category:\n\n### Core Objects\n\n`Application`, `Document`, `Documents`, `DocumentPreset`, `Layer`, `Layers`, `PageItem`, `PageItems`, `View`, `Views`, `Preferences`\n\n### Path and Shape Objects\n\n`PathItem`, `PathItems`, `PathPoint`, `PathPoints`, `CompoundPathItem`, `CompoundPathItems`, `GroupItem`, `GroupItems`\n\n### Text Objects\n\n`TextFrameItems`, `TextRange`, `TextRanges`, `TextPath`, `Characters`, `Words`, `Paragraphs`, `Lines`, `InsertionPoint`, `InsertionPoints`, `Story`, `Stories`, `CharacterAttributes`, `ParagraphAttributes`, `CharacterStyle`, `CharacterStyles`, `ParagraphStyle`, `ParagraphStyles`, `TextFont`, `TextFonts`, `TabStopInfo`\n\n### Color Objects\n\n`RGBColor`, `CMYKColor`, `GrayColor`, `LabColor`, `NoColor`, `SpotColor`, `Spot`, `Spots`, `PatternColor`, `GradientColor`, `Color`, `Gradient`, `Gradients`, `GradientStop`, `GradientStops`\n\n### Swatch and Style Objects\n\n`Swatch`, `Swatches`, `SwatchGroup`, `SwatchGroups`, `GraphicStyle`, `GraphicStyles`, `Pattern`, `Patterns`, `Brush`, `Brushes`\n\n### Symbol Objects\n\n`Symbol`, `Symbols`, `SymbolItem`, `SymbolItems`\n\n### Artboard Objects\n\n`Artboard`, `Artboards`\n\n### Placed and Raster Objects\n\n`PlacedItem`, `PlacedItems`, `RasterItem`, `RasterItems`, `MeshItem`, `MeshItems`, `GraphItem`, `GraphItems`, `PluginItem`, `PluginItems`, `NonNativeItem`, `NonNativeItems`, `LegacyTextItem`, `LegacyTextItems`\n\n### Data-Driven Objects\n\n`Variable`, `Variables`, `Dataset`, `Datasets`\n\n### Matrix and Transform Objects\n\n`Matrix`\n\n### Tag Objects\n\n`Tag`, `Tags`\n\n### Tracing Objects\n\n`TracingObject`, `TracingOptions`\n\n### Save and Export Options\n\n`IllustratorSaveOptions`, `EPSSaveOptions`, `PDFSaveOptions`, `FXGSaveOptions`, `ExportOptionsAutoCAD`, `ExportOptionsFlash`, `ExportOptionsGIF`, `ExportOptionsJPEG`, `ExportOptionsPhotoshop`, `ExportOptionsPNG8`, `ExportOptionsPNG24`, `ExportOptionsSVG`, `ExportOptionsTIFF`\n\n### Open Options\n\n`OpenOptions`, `OpenOptionsAutoCAD`, `OpenOptionsFreeHand`, `OpenOptionsPhotoshop`, `PDFFileOptions`, `PhotoshopFileOptions`\n\n### Print Objects\n\n`PrintOptions`, `PrintJobOptions`, `PrintPaperOptions`, `PrintColorManagementOptions`, `PrintColorSeparationOptions`, `PrintCoordinateOptions`, `PrintFlattenerOptions`, `PrintFontOptions`, `PrintPageMarksOptions`, `PrintPostScriptOptions`, `Printer`, `PrinterInfo`, `Paper`, `PaperInfo`, `PPDFile`, `PPDFileInfo`, `Ink`, `InkInfo`, `Screen`, `ScreenInfo`, `ScreenSpotFunction`\n\n### Image and Rasterize Options\n\n`ImageCaptureOptions`, `RasterEffectOptions`, `RasterizeOptions`\n\n## References\n\n- [Changelog](https://ai-scripting.docsforadobe.dev/introduction/changelog/) - Recent scripting API changes (CC 2020 added `Document.getPageItemFromUuid` and `PageItem.uuid`; CC 2017 added `Application.getIsFileOpen`)\n- [Illustrator Scripting Guide](https://ai-scripting.docsforadobe.dev/) - Full community-maintained documentation\n\nFile v1.0.0:_meta.json\n\n{\n  \"ownerId\": \"kn71kvdba3t2jfkk6nbgnytg0s81617g\",\n  \"slug\": \"adobe-illustrator-scripting\",\n  \"version\": \"1.0.0\",\n  \"publishedAt\": 1776635811558\n}\n\nFile v1.0.0:references/object-model-quick-reference.md\n\n# Illustrator JavaScript Object Model Quick Reference\n\n## Containment Hierarchy\n\n```\nApplication (app)\n └─ Document\n     ├─ Layer\n     │   ├─ pathItems[]        → PathItem → PathPoint[]\n     │   ├─ compoundPathItems[] → CompoundPathItem\n     │   ├─ textFrames[]       → TextFrameItem\n     │   │   ├─ characters[]   → TextRange (single char)\n     │   │   ├─ words[]        → TextRange (word)\n     │   │   ├─ paragraphs[]   → TextRange (paragraph)\n     │   │   ├─ lines[]        → TextRange (line)\n     │   │   └─ insertionPoints[]\n     │   ├─ placedItems[]      → PlacedItem\n     │   ├─ rasterItems[]      → RasterItem\n     │   ├─ meshItems[]        → MeshItem\n     │   ├─ pluginItems[]      → PluginItem\n     │   ├─ graphItems[]       → GraphItem\n     │   ├─ symbolItems[]      → SymbolItem → Symbol\n     │   ├─ groupItems[]       → GroupItem (recursive pageItems)\n     │   ├─ nonNativeItems[]   → NonNativeItem\n     │   └─ legacyTextItems[]  → LegacyTextItem\n     ├─ Artboard[]\n     ├─ Swatch[] / Spot[] / Gradient[] / Pattern[]\n     ├─ GraphicStyle[] / Brush[] / Symbol[]\n     ├─ Story[]\n     ├─ CharacterStyle[] / ParagraphStyle[]\n     ├─ Variable[] / Dataset[]\n     └─ View[]\n```\n\n## Artwork Item Types (pageItems members)\n\n| Type | typename | Collection | Notes |\n|---|---|---|---|\n| Path | `PathItem` | `pathItems` | Lines, shapes, freeform paths |\n| Compound path | `CompoundPathItem` | `compoundPathItems` | Multiple paths combined |\n| Group | `GroupItem` | `groupItems` | Contains nested pageItems |\n| Text frame | `TextFrame` | `textFrames` | Point, area, or path text |\n| Placed image | `PlacedItem` | `placedItems` | Linked external files |\n| Raster image | `RasterItem` | `rasterItems` | Embedded bitmaps |\n| Mesh | `MeshItem` | `meshItems` | Gradient mesh objects |\n| Graph | `GraphItem` | `graphItems` | Chart/graph objects |\n| Plugin item | `PluginItem` | `pluginItems` | Plugin-generated art |\n| Symbol instance | `SymbolItem` | `symbolItems` | Instance of a Symbol |\n| Non-native | `NonNativeItem` | `nonNativeItems` | Foreign objects |\n| Legacy text | `LegacyTextItem` | `legacyTextItems` | Pre-CS text objects |\n\n## Color Object Types\n\n| Object | Color Space | Value Range | Notes |\n|---|---|---|---|\n| `RGBColor` | RGB | 0-255 per channel | `.red`, `.green`, `.blue` |\n| `CMYKColor` | CMYK | 0-100 per channel | `.cyan`, `.magenta`, `.yellow`, `.black` |\n| `GrayColor` | Grayscale | 0-100 | `.gray` (0=black, 100=white) |\n| `LabColor` | Lab | L: 0-100, a/b: -128 to 127 | `.l`, `.a`, `.b` |\n| `SpotColor` | Spot | tint 0-100 | `.spot`, `.tint` |\n| `PatternColor` | Pattern | - | `.pattern`, `.matrix` |\n| `GradientColor` | Gradient | - | `.gradient`, `.origin`, `.angle` |\n| `NoColor` | None | - | Transparent/no fill |\n\n## Common Scripting Constants\n\n### Document and Color\n\n- `DocumentColorSpace.RGB` / `.CMYK`\n\n### Text\n\n- `Justification.LEFT` / `.CENTER` / `.RIGHT` / `.FULLJUSTIFY` / `.FULLJUSTIFYLASTLINELEFT` / `.FULLJUSTIFYLASTLINECENTER` / `.FULLJUSTIFYLASTLINERIGHT`\n- `TextType.POINTTEXT` / `.AREATEXT` / `.PATHTEXT`\n- `FontBaselineOption.NORMALBASELINE` / `.SUPERSCRIPT` / `.SUBSCRIPT`\n\n### Paths\n\n- `PointType.SMOOTH` / `.CORNER`\n- `StrokeCap.BUTTENDCAP` / `.ROUNDENDCAP` / `.PROJECTINGENDCAP`\n- `StrokeJoin.MITERENDJOIN` / `.ROUNDENDJOIN` / `.BEVELENDJOIN`\n\n### Transformations\n\n- `Transformation.DOCUMENTORIGIN` / `.BOTTOM` / `.BOTTOMLEFT` / `.BOTTOMRIGHT` / `.CENTER` / `.LEFT` / `.RIGHT` / `.TOP` / `.TOPLEFT` / `.TOPRIGHT`\n\n### Blend Modes\n\n- `BlendModes.NORMAL` / `.MULTIPLY` / `.SCREEN` / `.OVERLAY` / `.SOFTLIGHT` / `.HARDLIGHT` / `.COLORDODGE` / `.COLORBURN` / `.DARKEN` / `.LIGHTEN` / `.DIFFERENCE` / `.EXCLUSION` / `.HUE` / `.SATURATIONBLEND` / `.COLORBLEND` / `.LUMINOSITY`\n\n### Element Placement\n\n- `ElementPlacement.PLACEATBEGINNING` / `.PLACEATEND` / `.PLACEBEFORE` / `.PLACEAFTER` / `.INSIDE`\n\n### Z-Order\n\n- `ZOrderMethod.BRINGTOFRONT` / `.SENDTOBACK` / `.BRINGFORWARD` / `.SENDBACKWARD`\n\n### Save/Export\n\n- `SaveOptions.SAVECHANGES` / `.DONOTSAVECHANGES` / `.PROMPTTOSAVECHANGES`\n- `ExportType.PNG24` / `.PNG8` / `.JPEG` / `.SVG` / `.TIFF` / `.PHOTOSHOP` / `.AUTOCAD` / `.FLASH` / `.GIF`\n- `Compatibility.ILLUSTRATOR8` through `.ILLUSTRATOR24`\n- `PDFCompatibility.ACROBAT4` through `.ACROBAT8`\n\n### Gradient\n\n- `GradientType.LINEAR` / `.RADIAL`\n\n### Variables\n\n- `VariableKind.TEXTUAL` / `.IMAGE` / `.VISIBILITY` / `.GRAPH`\n\n### User Interaction\n\n- `UserInteractionLevel.DISPLAYALERTS` / `.DONTDISPLAYALERTS`\n\n### Print\n\n- `PrintArtworkDesignation.ALLLAYERS` / `.VISIBLELAYERS` / `.VISIBLEPRINTABLELAYERS`\n\n## Unit Conversions\n\n| From | To Points | Formula |\n|---|---|---|\n| Inches | Points | `inches * 72` |\n| Centimeters | Points | `cm * 28.346` |\n| Millimeters | Points | `mm * 2.834645` |\n| Picas | Points | `picas * 12` |\n| Em units | Points | `(emUnits * fontSize) / 1000` |","readmeExcerpt":"Skill: Adobe Illustrator Scripting Owner: jhauga Summary: Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d... Tags: latest:1.0.2 Version history: v1.0.2 | 2026-05-27T20:58:33.752Z | user - Added note on \"External invocation\" to scripting environment section, describing how scripts can be launched from outside ","codeSnippets":[],"executableExamples":[{"language":"text","snippet":"Application (app)\n├── activeDocument / documents[]\n│   ├── layers[]\n│   │   ├── pageItems[] (all artwork)\n│   │   ├── pathItems[]\n│   │   ├── compoundPathItems[]\n│   │   ├── textFrames[]\n│   │   ├── placedItems[]\n│   │   ├── rasterItems[]\n│   │   ├── meshItems[]\n│   │   ├── pluginItems[]\n│   │   ├── graphItems[]\n│   │   ├── symbolItems[]\n│   │   ├── nonNativeItems[]\n│   │   ├── legacyTextItems[]\n│   │   └── groupItems[]\n│   ├── artboards[]\n│   ├── views[]\n│   ├── selection (array of selected items)\n│   ├── swatches[], spots[], gradients[], patterns[]\n│   ├── graphicStyles[], brushes[], symbols[]\n│   ├── textFonts[] (via app.textFonts)\n│   ├── stories[], characterStyles[], paragraphStyles[]\n│   ├── variables[], datasets[]\n│   └── inkList[], printOptions\n├── preferences\n├── printerList[]\n└── textFonts[]"},{"language":"javascript","snippet":"// Create a new document\nvar doc = app.documents.add();\n\n// Create with a preset\nvar preset = new DocumentPreset();\npreset.width = 612;  // 8.5 inches\npreset.height = 792; // 11 inches\npreset.colorMode = DocumentColorSpace.CMYK;\nvar doc = app.documents.addDocument(\"Print\", preset);\n\n// Open an existing file\nvar fileRef = new File(\"/path/to/file.ai\");\nvar doc = app.open(fileRef);"},{"language":"javascript","snippet":"// Save as Illustrator format\nvar saveOpts = new IllustratorSaveOptions();\nsaveOpts.compatibility = Compatibility.ILLUSTRATOR17; // CC\ndoc.saveAs(new File(\"/path/to/output.ai\"), saveOpts);\n\n// Export as PDF\nvar pdfOpts = new PDFSaveOptions();\npdfOpts.compatibility = PDFCompatibility.ACROBAT7;\npdfOpts.preserveEditability = false;\ndoc.saveAs(new File(\"/path/to/output.pdf\"), pdfOpts);\n\n// Export as PNG\nvar pngOpts = new ExportOptionsPNG24();\npngOpts.horizontalScale = 300;\npngOpts.verticalScale = 300;\npngOpts.transparency = true;\ndoc.exportFile(new File(\"/path/to/output.png\"), ExportType.PNG24, pngOpts);\n\n// Export as SVG\nvar svgOpts = new ExportOptionsSVG();\nsvgOpts.fontType = SVGFontType.OUTLINEFONT;\ndoc.exportFile(new File(\"/path/to/output.svg\"), ExportType.SVG, svgOpts);"},{"language":"javascript","snippet":"var doc = app.activeDocument;\nvar layer = doc.activeLayer;\n\n// Rectangle: rectangle(top, left, width, height)\nvar rect = layer.pathItems.rectangle(500, 100, 200, 150);\n\n// Rounded rectangle: roundedRectangle(top, left, width, height, hRadius, vRadius)\nvar rrect = layer.pathItems.roundedRectangle(500, 100, 200, 150, 20, 20);\n\n// Ellipse: ellipse(top, left, width, height)\nvar oval = layer.pathItems.ellipse(400, 200, 100, 100);\n\n// Polygon: polygon(centerX, centerY, radius, sides)\nvar hex = layer.pathItems.polygon(300, 300, 50, 6);\n\n// Star: star(centerX, centerY, radius, innerRadius, points)\nvar star = layer.pathItems.star(300, 300, 50, 25, 5);"},{"language":"javascript","snippet":"var doc = app.activeDocument;\nvar path = doc.pathItems.add();\npath.setEntirePath([[100, 100], [200, 200], [300, 100]]);\npath.closed = false;\npath.stroked = true;\npath.strokeWidth = 2;"},{"language":"javascript","snippet":"var doc = app.activeDocument;\nvar path = doc.pathItems.add();\n\nvar point1 = path.pathPoints.add();\npoint1.anchor = [100, 100];\npoint1.leftDirection = [100, 100];\npoint1.rightDirection = [150, 150];\npoint1.pointType = PointType.SMOOTH;\n\nvar point2 = path.pathPoints.add();\npoint2.anchor = [300, 100];\npoint2.leftDirection = [250, 150];\npoint2.rightDirection = [300, 100];\npoint2.pointType = PointType.SMOOTH;\n\npath.closed = false;"}],"parameters":null,"dependencies":[],"permissions":[],"extractedFiles":[{"path":"SKILL.md","content":"---\nname: adobe-illustrator-scripting\ndescription: 'Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate documents, layers, paths, text frames, colors, symbols, artboards, or any Illustrator DOM objects. Covers the complete JavaScript object model, coordinate system, measurement units, export workflows, and scripting best practices.'\n---\n\n# Adobe Illustrator Scripting\n\nExpert guidance for automating Adobe Illustrator through ExtendScript (JavaScript/JSX). This skill covers the Illustrator scripting object model, all major API objects, code patterns, and best practices for writing production-quality `.jsx` scripts.\n\n## Bundled Assets\n\n- [`references/object-model-quick-reference.md`](references/object-model-quick-reference.md): Use this as a quick lookup for the Illustrator scripting object model, common document and page item types, and related DOM concepts while writing or debugging scripts.\n- `scripts/`: Contains example Illustrator automation scripts you can use as starting points or implementation patterns for common tasks such as document manipulation, exports, batch processing, and DOM usage. Review and adapt these examples when you need working JSX patterns or want to compare behavior while debugging.\n## When to Use This Skill\n\n- Writing new Illustrator automation scripts (`.jsx` or `.js` files)\n- Debugging or fixing existing Illustrator ExtendScript code\n- Manipulating documents, layers, page items, paths, text, or colors programmatically\n- Batch-processing Illustrator files or generating artwork from data\n- Exporting documents to various formats (PDF, SVG, PNG, EPS, etc.)\n- Working with the Illustrator DOM (Application, Document, Layer, PathItem, TextFrame, etc.)\n- Creating data-driven graphics using variables and datasets\n- Automating print workflows with scripted print options\n\n## Prerequisites\n\n- Adobe Illustrator CC or later installed\n- Basic JavaScript knowledge (ExtendScript is ES3-based with Adobe extensions)\n- Scripts are executed via File > Scripts > Other Scripts, the Scripts menu, or placed in the Startup Scripts folder\n- The ExtendScript Toolkit (ESTK) or any text editor can be used to write `.jsx` files\n\n## Scripting Environment\n\n### Language and File Extensions\n\n| Language | Extension | Platform |\n|---|---|---|\n| ExtendScript/JavaScript | `.jsx`, `.js` | Windows, macOS |\n| AppleScript | `.scpt` | macOS only |\n| VBScript | `.vbs` | Windows only |\n\n**This skill focuses on ExtendScript/JavaScript** as the cross-platform, most widely used option.\n\n### Executing Scripts\n\n- **Scripts menu**: File > Scripts lists scripts from the application scripts folder\n- **Other Scripts**: File > Scripts > Other Scripts to browse and run any `.jsx` file\n- **Startup Scripts**: Place scripts in the Startup Scripts folder to run automatically on launch\n- **Target directive**: Begin scripts with `#target illustrator` when running from ESTK or exte"},{"path":"_meta.json","content":"{\n  \"ownerId\": \"kn71kvdba3t2jfkk6nbgnytg0s81617g\",\n  \"slug\": \"adobe-illustrator-scripting\",\n  \"version\": \"1.0.2\",\n  \"publishedAt\": 1779915513752\n}"},{"path":"references/object-model-quick-reference.md","content":"# Illustrator JavaScript Object Model Quick Reference\n\n## Containment Hierarchy\n\n```\nApplication (app)\n └─ Document\n     ├─ Layer\n     │   ├─ pathItems[]        → PathItem → PathPoint[]\n     │   ├─ compoundPathItems[] → CompoundPathItem\n     │   ├─ textFrames[]       → TextFrame\n     │   │   ├─ characters[]   → TextRange (single char)\n     │   │   ├─ words[]        → TextRange (word)\n     │   │   ├─ paragraphs[]   → TextRange (paragraph)\n     │   │   ├─ lines[]        → TextRange (line)\n     │   │   └─ insertionPoints[]\n     │   ├─ placedItems[]      → PlacedItem\n     │   ├─ rasterItems[]      → RasterItem\n     │   ├─ meshItems[]        → MeshItem\n     │   ├─ pluginItems[]      → PluginItem\n     │   ├─ graphItems[]       → GraphItem\n     │   ├─ symbolItems[]      → SymbolItem → Symbol\n     │   ├─ groupItems[]       → GroupItem (recursive pageItems)\n     │   ├─ nonNativeItems[]   → NonNativeItem\n     │   └─ legacyTextItems[]  → LegacyTextItem\n     ├─ Artboard[]\n     ├─ Swatch[] / Spot[] / Gradient[] / Pattern[]\n     ├─ GraphicStyle[] / Brush[] / Symbol[]\n     ├─ Story[]\n     ├─ CharacterStyle[] / ParagraphStyle[]\n     ├─ Variable[] / Dataset[]\n     └─ View[]\n```\n\n## Artwork Item Types (pageItems members)\n\n| Type | typename | Collection | Notes |\n|---|---|---|---|\n| Path | `PathItem` | `pathItems` | Lines, shapes, freeform paths |\n| Compound path | `CompoundPathItem` | `compoundPathItems` | Multiple paths combined |\n| Group | `GroupItem` | `groupItems` | Contains nested pageItems |\n| Text frame | `TextFrame` | `textFrames` | Point, area, or path text |\n| Placed image | `PlacedItem` | `placedItems` | Linked external files |\n| Raster image | `RasterItem` | `rasterItems` | Embedded bitmaps |\n| Mesh | `MeshItem` | `meshItems` | Gradient mesh objects |\n| Graph | `GraphItem` | `graphItems` | Chart/graph objects |\n| Plugin item | `PluginItem` | `pluginItems` | Plugin-generated art |\n| Symbol instance | `SymbolItem` | `symbolItems` | Instance of a Symbol |\n| Non-native | `NonNativeItem` | `nonNativeItems` | Foreign objects |\n| Legacy text | `LegacyTextItem` | `legacyTextItems` | Pre-CS text objects |\n\n## Color Object Types\n\n| Object | Color Space | Value Range | Notes |\n|---|---|---|---|\n| `RGBColor` | RGB | 0-255 per channel | `.red`, `.green`, `.blue` |\n| `CMYKColor` | CMYK | 0-100 per channel | `.cyan`, `.magenta`, `.yellow`, `.black` |\n| `GrayColor` | Grayscale | 0-100 | `.gray` (0=black, 100=white) |\n| `LabColor` | Lab | L: 0-100, a/b: -128 to 127 | `.l`, `.a`, `.b` |\n| `SpotColor` | Spot | tint 0-100 | `.spot`, `.tint` |\n| `PatternColor` | Pattern | - | `.pattern`, `.matrix` |\n| `GradientColor` | Gradient | - | `.gradient`, `.origin`, `.angle` |\n| `NoColor` | None | - | Transparent/no fill |\n\n## Common Scripting Constants\n\n### Document and Color\n\n- `DocumentColorSpace.RGB` / `.CMYK`\n\n### Text\n\n- `Justification.LEFT` / `.CENTER` / `.RIGHT` / `.FULLJUSTIFY` / `.FULLJUSTIFYLASTLINELEFT` / `.FULLJUSTIFYLASTLINECENTER` / `.FULLJUSTIFYLASTLINERIGHT`\n- `Tex"},{"path":"skill-card.md","content":"## Description:\n\nWrite, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX) for documents, layers, paths, text frames, colors, symbols, artboards, export workflows, and related Illustrator DOM objects.\n\nThis skill is ready for commercial/non-commercial use.\n\n## Publisher:\n\n[jhauga](https://clawhub.ai/user/jhauga)\n\n### License/Terms of Use:\n\nMIT-0\n\n## Use Case:\n\nDevelopers and designers use this skill to create, debug, and adapt Illustrator ExtendScript automation for document editing, batch exports, artwork generation, text replacement, and DOM-based workflows.\n\n### Deployment Geography for Use:\n\nGlobal\n\n## Known Risks and Mitigations:\n\nRisk: Generated or adapted Illustrator scripts can save, export, delete, remove, or otherwise modify artwork and documents.\n\nMitigation: Review scripts before execution, test on copies of files, and confirm file paths and document targets before running batch or unattended workflows.\n\nRisk: Startup or headless Illustrator scripts can run without visible prompts, especially when dialogs are suppressed.\n\nMitigation: Avoid placing unreviewed scripts in Startup Scripts, use explicit logging for unattended runs, and keep user interaction enabled unless the workflow requires suppression.\n\nRisk: Scripts that open external files or use sidecar/log files may read or write unexpected paths if inputs are wrong.\n\nMitigation: Use known absolute paths, validate inputs, and inspect sidecar or log locations before running externally launched automation.\n\n## Reference(s):\n\n- [Illustrator JavaScript Object Model Quick Reference](references/object-model-quick-reference.md)\n- [Illustrator Scripting Guide](https://ai-scripting.docsforadobe.dev/)\n- [Illustrator Scripting Changelog](https://ai-scripting.docsforadobe.dev/introduction/changelog/)\n- [ClawHub Skill Page](https://clawhub.ai/jhauga/skills/adobe-illustrator-scripting)\n\n## Skill Output:\n\n**Output Type(s):** [Text, Markdown, Code, Shell commands, Configuration, Guidance]\n\n**Output Format:** [Markdown with JavaScript/JSX code blocks, concise guidance, and optional command examples]\n\n**Output Parameters:** [1D]\n\n**Other Properties Related to Output:** [May include Illustrator ExtendScript snippets, workflow checks, troubleshooting notes, and file path guidance.]\n\n## Skill Version(s):\n\n1.0.2 (source: server release evidence)\n\n## Ethical Considerations:\n\nUsers should evaluate whether this skill is appropriate for their environment, review any generated or modified files before relying on them, and apply their organization's safety, security, and compliance requirements before deployment."}],"languages":[],"docsSourceLabel":"CLAWHUB","editorialOverview":"Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d... Skill: Adobe Illustrator Scripting Owner: jhauga Summary: Write, debug, and optimize Adobe Illustrator automation scripts using ExtendScript (JavaScript/JSX). Use when creating or modifying scripts that manipulate d... Tags: latest:1.0.2 Version history: v1.0.2 | 2026-05-27T20:58:33.752Z | user - Added note on \"External invocation\" to scripting environment section, describing how scripts can be launched from outside","editorialQuality":{"score":100,"threshold":65,"status":"ready","wordCount":1417,"uniquenessScore":51,"reasons":[]}},"media":{"evidence":{"source":"no-media","verified":false,"confidence":"low","updatedAt":"2026-10-10T14:58:49.521Z","emptyReason":"No screenshots, media assets, or demo links are available."},"primaryImageUrl":null,"mediaAssetCount":0,"assets":[],"demoUrl":null},"ownerResources":{"evidence":{"source":"unclaimed","verified":false,"confidence":"low","updatedAt":"2026-10-10T14:58:49.521Z","emptyReason":"This page has not been claimed by the agent owner."},"hasCustomPage":false,"customPageUpdatedAt":null,"customLinks":[],"structuredLinks":{"docsUrl":null,"demoUrl":null,"supportUrl":null,"pricingUrl":null,"statusUrl":null},"customPage":null},"relatedAgents":{"evidence":{"source":"protocol-neighbors","verified":false,"confidence":"medium","updatedAt":"2026-10-10T17:33:20.277Z","emptyReason":null},"items":[{"id":"8ebccd8e-3863-4187-8355-c3f14e1f9edf","entityType":"agent","canonicalPath":"/agent/iofficeai-aionui","slug":"iofficeai-aionui","name":"AionUi","description":"Free, local, open-source 24/7 Cowork app and OpenClaw for Gemini CLI, Claude Code, Codex, OpenCode, Qwen Code, Goose CLI, Auggie, and more | 🌟 Star if you like it!","url":"https://github.com/iOfficeAI/AionUi","homepage":"https://www.aionui.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-10-09T19:11:12.944Z","createdAt":"2026-02-25T03:38:16.584Z","downloads":null},{"id":"b917f68a-ebff-438e-84f8-3f4b2494c0bc","entityType":"agent","canonicalPath":"/agent/activepieces-activepieces","slug":"activepieces-activepieces","name":"activepieces","description":"AI Agents & MCPs & AI Workflow Automation • (~400 MCP servers for AI agents) • AI Automation / AI Agent with MCPs • AI Workflows & AI Agents • MCPs for AI Agents","url":"https://github.com/activepieces/activepieces","homepage":"https://www.activepieces.com","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-15T02:22:12.426Z","createdAt":"2026-02-25T03:38:12.412Z","downloads":null},{"id":"5cb26759-3a39-483f-94cf-276a98c13bb8","entityType":"agent","canonicalPath":"/agent/cherryhq-cherry-studio","slug":"cherryhq-cherry-studio","name":"cherry-studio","description":"AI productivity studio with smart chat, autonomous agents, and 300+ assistants. Unified access to frontier LLMs","url":"https://github.com/CherryHQ/cherry-studio","homepage":"https://cherry-ai.com","source":"GITHUB_REPOS","protocols":["MCP","OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-04-11T14:38:40.986Z","createdAt":"2026-02-25T03:38:19.379Z","downloads":null},{"id":"6f6582d0-5d76-4f0f-b81d-86520247950b","entityType":"agent","canonicalPath":"/agent/copilotkit-copilotkit","slug":"copilotkit-copilotkit","name":"CopilotKit","description":"The Frontend for Agents & Generative UI. React + Angular","url":"https://github.com/CopilotKit/CopilotKit","homepage":"https://docs.copilotkit.ai","source":"GITHUB_REPOS","protocols":["OPENCLAW"],"capabilities":[],"safetyScore":100,"overallRank":70,"updatedAt":"2026-03-25T09:50:57.846Z","createdAt":"2026-02-25T03:39:14.617Z","downloads":null}],"links":{"hub":"/agent","source":"/agent/source/clawhub","protocols":[{"label":"OpenClaw","href":"/agent/protocol/openclew"}]}}}