Help us improve
Share bugs, ideas, or general feedback.
From enonic-skills
Generates Enonic XP scripts for bulk content operations — creating, updating, querying, migrating, and transforming content using lib-content and lib-node APIs. Covers the query DSL (NoQL), aggregations, batch processing, task controllers for long-running operations, and export/import workflows. Use when writing bulk content creation, update, or deletion scripts, querying with NoQL syntax, migrating content between environments, running long-running task operations, or working with aggregations and paginated retrieval. Do not use for Guillotine GraphQL frontend queries, content type schema definitions, single contentLib.get() calls, or non-Enonic data migration tools.
npx claudepluginhub webmaxru/ai-native-dev --plugin enonic-skillsHow this skill is triggered — by the user, by Claude, or both
Slash command
/enonic-skills:enonic-content-managementThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Step 1: Identify the Enonic XP project and operation scope**
Provides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.
Structures git workflow practices for committing, branching, resolving conflicts, and organizing work across parallel streams. Use when making any code change.
Share bugs, ideas, or general feedback.
Step 1: Identify the Enonic XP project and operation scope
build.gradle with com.enonic.xp dependencies, src/main/resources/ directory structure, or gradle.properties with xpVersion.node scripts/find-enonic-targets.mjs . to scan for Enonic XP project markers and existing content operation files when a Node runtime is available.gradle.properties or build.gradle to select the correct API surface.Step 2: Select the API layer and context
references/migration-reference.md for query DSL patterns, batch processing strategies, and branch handling rules.lib-content when the operation works with CMS content and needs publish/unpublish, content-type validation, and the content domain abstraction.lib-node when the operation needs low-level node manipulation, custom repositories, or bypasses content-type validation for raw data migration.lib-context to run operations in draft branch for modifications and master branch for reading published content.lib-context with role:system.admin principal when the operation requires elevated permissions.lib-task. Read references/migration-reference.md section on task controllers for the pattern.Step 3: Build the query
contentTypes parameter on contentLib.query() or a type property comparison in node queries.instant() or dateTime() functions and the range() query function.fulltext() with the appropriate field paths and operator (AND/OR)._path LIKE '/content/site-path/*' to match descendants. Note: the _path property in NoQL queries includes the internal /content/ prefix, but hit._path in results returns the content-domain path without it. Always prepend /content/ when building queries from result paths.filters for efficient post-query narrowing using exists, notExists, hasValue, or boolean combinations.aggregations when the operation needs grouped statistics (term counts, date histograms, numeric ranges, stats).references/examples.md for complete query and aggregation patterns.Step 4: Implement batch processing
start and count parameters to avoid loading all results into memory.count to a batch size between 50 and 200 depending on the complexity of per-item processing.result.hits.length === 0 or start >= result.total, incrementing start by the batch size each iteration.contentLib.create() in bulk, set refresh: false to avoid per-item index refresh; call a manual refresh after the batch completes.contentLib.modify(), use the editor callback pattern to safely transform each content item.contentLib.publish(), batch keys into groups of 50–100 to avoid timeout on large publish sets.assets/bulk-update.template.ts for the reusable batch update controller template. Note: templates use TypeScript/ESM syntax (import, const, arrow functions); adapt to CommonJS JavaScript (require(), var, function()) for XP runtime deployment as .js files.Step 5: Handle branch operations and publishing
draft branch context.master using contentLib.publish(). On XP < 7.12, pass sourceBranch: 'draft' and targetBranch: 'master'. On XP 7.12+, these parameters are ignored (publish always goes draft→master).includeDependencies: false when publishing bulk-updated items to avoid unintended dependency publishing.repo.diff() from lib-node with target: 'master' and includeChildren: true.Step 6: Wrap long-running operations in a task controller
taskLib.executeFunction() for inline task functions or taskLib.submitTask() for named task descriptors.taskLib.progress({ info, current, total }) at regular intervals during batch processing.assets/task-migration.template.ts for the reusable task controller template with progress reporting.taskLib.isRunning() before starting a duplicate operation.taskLib.sleep() for throttling between batches if the operation generates excessive load.run function receives taskId as its second argument: exports.run = function(params, taskId) { ... }.Step 7: Validate and report results
master branch.scripts/find-enonic-targets.mjs finds no Enonic XP project, explain that the workspace does not contain an Enonic XP application.contentAlreadyExists, check whether the target exists and decide whether to update or skip. Read references/troubleshooting.md for duplicate handling patterns.instant() wrapper for date comparisons) are a common cause.taskLib.get(taskId) for state and progress details. Read references/troubleshooting.md for timeout and permission issues.AccessDeniedException occurs on publish or modify, ensure the context includes role:system.admin principals via lib-context.