Edge Delivery Services Admin Operations
Execute admin operations on AEM Edge Delivery Services projects using natural language commands.
Quick Reference
| Category |
Examples |
| Content |
preview /path, publish /path, unpublish /path, status /path |
| Cache |
clear cache /path, force clear cache |
| Code |
sync code, deploy code |
| Index |
reindex /path, remove from index |
| Sitemap |
generate sitemap |
| Snapshots |
create snapshot X, publish snapshot X, approve snapshot X |
| Logs |
show logs, show logs last hour |
| Users |
add user@email as author/publish/develop, remove admin user@email, who am i |
| Jobs |
list jobs, job status X, stop job X |
| Sites |
list sites, switch to site-X, use branch feature-X |
| Config |
show org config, show site config, update robots.txt |
| Secrets |
list secrets, create secret, delete secret |
| API Keys |
list API keys, create API key, revoke API key |
| Tokens |
list tokens, create token, revoke token |
| Profiles |
show profile config, create profile, delete profile |
| Index Config |
show index config, update index config (query.yaml) |
| Sitemap Config |
show sitemap config, update sitemap config (sitemap.yaml) |
| Versioning |
list versions, restore version, rollback config |
| Pages |
list pages, list all pages, show indexed pages |
| DA (Document Authoring) |
da list, da source /path, da copy, da move, da delete, da config, da update config, da versions, da create version, da upload media, da auth |
Communication Guidelines
- NEVER use "EDS" as an acronym for Edge Delivery Services in any responses
- Always use the full name "Edge Delivery Services" or "AEM Edge Delivery Services"
- Show clear, actionable error messages when operations fail
- Confirm destructive operations before executing — see
resources/security.md
Welcome Message
If the user invokes the skill without a specific command (e.g., just /ops or "help me with ops"), show:
Edge Delivery Services Operations
Quick commands to try:
list pages - Show all indexed pages
who am i - Check your user profile
list sites - Show available sites
show site config - View site configuration
preview /path - Preview a content path
show logs - View recent activity
For the full command list: type help, /ops help, or what can you do?
Cross-Platform Notes
Shell commands use POSIX-compatible syntax (works on macOS/Linux). On Windows, Git Bash or WSL works as-is. The agent should adapt syntax to the user's environment.
Intent Router
Step 0: Get Organization and Site (REQUIRED FIRST)
Check ~/.aem/ops-config.json for previously stored org and site:
eval $(node -e "
const fs = require('fs');
try {
const c = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ops-config.json', 'utf8'));
console.log('ORG=' + JSON.stringify(c.org || ''));
console.log('SITE=' + JSON.stringify(c.site || ''));
} catch(e) {
console.log('ORG='); console.log('SITE=');
}
")
echo "org=${ORG:-NOT SET} site=${SITE:-NOT SET}"
If both ORG and SITE are set, confirm with the user:
"Previously used: org={ORG}, site={SITE}. Do you want to continue with these? If not, provide a different site URL (e.g., https://main--mysite--myorg.aem.page/)."
- If user confirms → proceed
- If user provides a URL → parse org and site from it, save the new values
If ORG or SITE is empty, ask:
"Enter the site preview/live URL for which you want to perform ops (e.g., https://main--mysite--myorg.aem.page/)."
Parse org and site from the URL:
URL="$USER_INPUT"
if echo "$URL" | grep -q '\.aem\.page\|\.aem\.live'; then
HOST_PART=$(echo "$URL" | cut -d'/' -f3 | cut -d'.' -f1)
ORG=$(echo "$HOST_PART" | awk -F'--' '{print $NF}')
SITE=$(echo "$HOST_PART" | awk -F'--' '{print $(NF-1)}')
echo "Parsed from URL: org=$ORG site=$SITE"
fi
If the user provides something other than a valid .aem.page or .aem.live URL, ask again.
Save org and site:
mkdir -p "${HOME}/.aem"
node -e "
const fs = require('fs');
const p = process.env.HOME + '/.aem/ops-config.json';
let c = {};
try { c = JSON.parse(fs.readFileSync(p, 'utf8')); } catch(e) {}
c.org = '${ORG}';
c.site = '${SITE}';
fs.writeFileSync(p, JSON.stringify(c, null, 2));
"
Only use org/site from ~/.aem/ops-config.json or direct user input. Never infer from git remote, fstab.yaml, or folder/repo names.
Do NOT proceed until both org and site are confirmed.
Step 1: Authenticate (REQUIRED)
Before ANY API call, check if auth token exists:
AUTH_TOKEN=$(node -e "
const fs = require('fs');
try {
const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));
if (t.authToken && t.authTokenExpiry > Math.floor(Date.now()/1000) + 60) {
process.stdout.write(t.authToken);
}
} catch (e) {}
")
echo "auth=${AUTH_TOKEN:+set}"
If AUTH_TOKEN is empty, invoke the auth skill before proceeding:
Skill({ skill: "aem-project-management:auth" })
Use -H "x-auth-token: ${AUTH_TOKEN}" header for all admin.hlx.page API calls.
For sensitive endpoints and destructive operations, read resources/security.md and resources/sensitive.md before proceeding.
Step 2: Load Full Configuration and Validate Role
eval $(node -e "
const fs = require('fs');
try {
const c = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ops-config.json', 'utf8'));
console.log('ORG=' + JSON.stringify(c.org || ''));
console.log('SITE=' + JSON.stringify(c.site || ''));
console.log('REF=' + JSON.stringify(c.ref || 'main'));
} catch(e) {
console.log('ORG='); console.log('SITE='); console.log('REF=main');
}
")
AUTH_TOKEN=$(node -e "
const fs = require('fs');
try {
const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));
process.stdout.write(t.authToken || '');
} catch (e) {}
")
echo "Config: org=$ORG site=$SITE ref=$REF auth=${AUTH_TOKEN:+set}"
Fetch profile to verify auth and record user identity:
PROFILE_RESPONSE=$(curl -s -w "\n%{http_code}" \
-H "x-auth-token: ${AUTH_TOKEN}" \
"https://admin.hlx.page/profile")
HTTP_CODE=$(echo "$PROFILE_RESPONSE" | tail -n1)
PROFILE=$(echo "$PROFILE_RESPONSE" | sed '$d')
if [ "$HTTP_CODE" = "401" ]; then
echo "Auth token expired. Need to re-authenticate..."
echo "REAUTH_REQUIRED"
exit 1
elif [ "$HTTP_CODE" != "200" ]; then
echo "Failed to fetch profile (HTTP $HTTP_CODE). Check network/API status."
exit 1
fi
eval $(echo "$PROFILE" | node -e "
const d = require('fs').readFileSync(0,'utf8');
try {
const p = JSON.parse(d).profile || {};
console.log('USER_EMAIL=' + JSON.stringify(p.email || ''));
console.log('USER_NAME=' + JSON.stringify(p.name || ''));
} catch(e) { console.log('USER_EMAIL=\"\"'); console.log('USER_NAME=\"\"'); }
")
echo "Authenticated as: $USER_EMAIL ($USER_NAME)"
If REAUTH_REQUIRED, invoke the auth skill and retry.
To determine user role on the site, check the site access config:
curl -s -H "x-auth-token: ${AUTH_TOKEN}" \
"https://admin.hlx.page/config/${ORG}/sites/${SITE}.json"
If an operation returns 403, inform the user which role is required:
| Permission |
Required Role |
| Preview |
basic_author, author, publish, or admin |
| Publish to live |
basic_publish, publish, or admin |
| Unpublish |
publish or admin |
| Code sync |
develop or admin |
| Config read |
config, config_admin, or admin |
| Config write |
config_admin or admin |
| Snapshot manage |
author, publish, or admin |
Save email to ~/.aem/ops-config.json for future use.
Read resources/config.md if site or other values are missing.
Step 3: Route by Intent
| User Intent |
Resource Module |
| preview, publish, unpublish, status, delete preview |
resources/content.md |
| cache, purge, clear cache, invalidate |
resources/cache.md |
| sync code, deploy code, update code |
resources/code.md |
| reindex, index, remove from index, search |
resources/index.md |
| sitemap, generate sitemap |
resources/sitemap.md |
| snapshot, staged release, bundle |
resources/snapshots.md |
| logs, audit, activity |
resources/logs.md |
| user, access, permission, who am i, add user, remove user |
resources/users.md |
| job, bulk operation, stop job |
resources/jobs.md |
| site, branch, switch, list sites |
resources/sites.md |
| org config, site config, robots.txt |
resources/config-api.md |
| secret, secrets, create secret, delete secret |
resources/secrets.md |
| API key, apikey, create key, revoke key |
resources/apikeys.md |
| token, tokens, access token |
resources/tokens.md |
| profile config, profile settings |
resources/profiles.md |
| index config, helix-index, search config |
resources/index-config.md |
| sitemap config, helix-sitemap, sitemap rules |
resources/sitemap-config.md |
| version, versions, history, rollback, restore |
resources/versioning.md |
| pages, list pages, indexed pages, all pages |
resources/pages.md |
| da, da list, da source, da copy, da move, da delete, da config, da versions |
resources/da.md |
| destructive operation, confirmation required |
resources/security.md |
| sensitive endpoint (emails, credentials, API keys) |
resources/sensitive.md |
Step 4: Read Resource and Execute
- Read the appropriate resource file from
resources/
- Follow instructions in that resource
- For config updates: always GET current config first and show it to the user before modifying
- For code sync: always check repoless status before syncing (see
code.md)
- For destructive operations: read
resources/security.md and follow the Confirmation Protocol — no exceptions (state action, explain impact, ask "yes/no", only execute after "yes")
- Execute the API call
- Handle response per completion standards below
Completion Standards
| HTTP Response |
Meaning |
Required Action |
| 200/201 |
Success |
Display result with full URLs (https://{ref}--{site}--{org}.aem.page{path}) |
| 202 |
Async job started |
Report job name; instruct: check job status {jobName} to track progress |
| 204 |
Success (no body) |
Confirm: "{action} completed for {path}" |
| 4xx/5xx |
Error |
Show API error verbatim, then suggest fix per resources/errors.md |
Before reporting success:
- For content operations: include both preview and live URLs where applicable
- For bulk operations: never say "published" or "previewed" — say "job started" until job completes
- For destructive operations: confirm what was removed and what still exists
URL Parsing Helper
If user provides an AEM URL instead of separate org/site/path values:
# Pattern: https://{ref}--{site}--{org}.aem.page{path}
URL="$USER_INPUT"
if echo "$URL" | grep -q '\.aem\.page\|\.aem\.live'; then
DOMAIN=$(echo "$URL" | cut -d'/' -f3)
HOST_PART=$(echo "$DOMAIN" | cut -d'.' -f1)
REF=$(echo "$HOST_PART" | awk -F'--' '{print $1}')
ORG=$(echo "$HOST_PART" | awk -F'--' '{print $NF}')
SITE=$(echo "$HOST_PART" | awk -F'--' '{
r=""; for(i=2;i<NF;i++) r=(r==""?"":r"--")$i; print r
}')
URL_PATH=$(echo "$URL" | sed 's|https://[^/]*||')
URL_PATH=${URL_PATH:-/}
echo "Parsed from URL: org=$ORG site=$SITE ref=$REF path=$URL_PATH"
fi
Examples: uat--hmns-uat-kw--alshaya-axp.aem.page → ref=uat, site=hmns-uat-kw, org=alshaya-axp.
Prerequisites
- Onboarded to Admin Service — Project must have admin.hlx.page access
- User has an account — Required for authentication (supports federated login)
- User has a site role — Roles defined in site configuration (
access.admin.role). Eight roles: admin, author, publish, develop, basic_author, basic_publish, config, config_admin. If the user lacks a role, the API returns 403.
- Network access — Can reach admin.hlx.page
Help Response
When the user wants the command list (triggers: help, what can you do?, /ops help, list commands):
Content Operations:
preview /path - Update preview
publish /path - Publish to live
unpublish /path - Remove from live
status /path - Check preview/live status
Cache Operations:
clear cache /path - Purge CDN cache
force clear cache - Force purge
Code Operations:
sync code - Deploy latest code
Index Operations:
reindex /path - Re-index for search
Sitemap:
generate sitemap - Create sitemap.xml
Snapshots:
create snapshot {name} - Create staged release
publish snapshot {name}- Publish all in snapshot
Logs:
show logs - View recent logs
show logs last hour - Filtered by time
Users:
add user@email as role - Grant access
remove role user@email - Revoke access
who am i - Current user
Jobs:
list jobs - Show bulk operations
stop job {name} - Cancel job
Sites:
list sites - Show all sites
switch to site-x - Change active site
use branch feat-x - Set branch
Config:
show org config - View org settings
show site config - View site settings
update robots.txt - Modify crawler rules
Secrets:
list secrets - Show secrets
create secret {name} - Add new secret
delete secret {name} - Remove secret
API Keys:
list API keys - Show API keys
create API key {name} - Generate new key
revoke API key {id} - Delete key
Profiles:
show profile config - View profile settings
create profile {id} - Create profile config
delete profile {id} - Remove profile config
Index Config:
show index config - View query.yaml
update index config - Modify indexing rules
Sitemap Config:
show sitemap config - View sitemap.yaml
update sitemap config - Modify sitemap rules
Versioning:
list versions - Show config history
restore version {id} - Rollback to version
Pages:
list pages - Show all indexed pages
list pages /blog - Filter by path prefix
Document Authoring (DA):
da auth - Authenticate with DA
da list - List DA organizations
da list /path - List files in DA path
da source /path - Get file content from DA
da copy /src to /dest - Copy file/folder in DA
da move /src to /dest - Move/rename in DA
da delete /path - Delete from DA
da upload /path - Upload content to DA
da upload media /path - Upload image/media to DA
da config - View DA site config
da update config - Update DA site config
da versions /path - List file versions
da create version - Create labeled version snapshot
da restore version X - Restore a previous version
da preview /path - Preview DA content
da publish /path - Publish DA content
1---2name: ops3description: Execute AEM Edge Delivery Services admin operations: manage content, cache, code, indexes, sitemaps, snapshots, logs, users, jobs, sites, config, secrets, API keys, tokens, profiles, and versioning. Also supports Document Authoring operations.4license: Apache-2.05---67# Edge Delivery Services Admin Operations89Execute admin operations on AEM Edge Delivery Services projects using natural language commands.1011## Quick Reference1213| Category | Examples |14|----------|----------|15| **Content** | preview /path, publish /path, unpublish /path, status /path |16| **Cache** | clear cache /path, force clear cache |17| **Code** | sync code, deploy code |18| **Index** | reindex /path, remove from index |19| **Sitemap** | generate sitemap |20| **Snapshots** | create snapshot X, publish snapshot X, approve snapshot X |21| **Logs** | show logs, show logs last hour |22| **Users** | add user@email as author/publish/develop, remove admin user@email, who am i |23| **Jobs** | list jobs, job status X, stop job X |24| **Sites** | list sites, switch to site-X, use branch feature-X |25| **Config** | show org config, show site config, update robots.txt |26| **Secrets** | list secrets, create secret, delete secret |27| **API Keys** | list API keys, create API key, revoke API key |28| **Tokens** | list tokens, create token, revoke token |29| **Profiles** | show profile config, create profile, delete profile |30| **Index Config** | show index config, update index config (query.yaml) |31| **Sitemap Config** | show sitemap config, update sitemap config (sitemap.yaml) |32| **Versioning** | list versions, restore version, rollback config |33| **Pages** | list pages, list all pages, show indexed pages |34| **DA (Document Authoring)** | da list, da source /path, da copy, da move, da delete, da config, da update config, da versions, da create version, da upload media, da auth |3536---3738## Communication Guidelines3940- **NEVER use "EDS"** as an acronym for Edge Delivery Services in any responses41- Always use the full name "Edge Delivery Services" or "AEM Edge Delivery Services"42- Show clear, actionable error messages when operations fail43- Confirm destructive operations before executing — see `resources/security.md`4445---4647## Welcome Message4849If the user invokes the skill without a specific command (e.g., just `/ops` or "help me with ops"), show:5051```52Edge Delivery Services Operations5354Quick commands to try:55 list pages - Show all indexed pages56 who am i - Check your user profile57 list sites - Show available sites58 show site config - View site configuration59 preview /path - Preview a content path60 show logs - View recent activity6162For the full command list: type help, /ops help, or what can you do?63```6465---6667## Cross-Platform Notes6869Shell commands use POSIX-compatible syntax (works on macOS/Linux). On Windows, Git Bash or WSL works as-is. The agent should adapt syntax to the user's environment.7071---7273## Intent Router7475### Step 0: Get Organization and Site (REQUIRED FIRST)7677Check `~/.aem/ops-config.json` for previously stored org and site:7879```bash80eval $(node -e "81 const fs = require('fs');82 try {83 const c = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ops-config.json', 'utf8'));84 console.log('ORG=' + JSON.stringify(c.org || ''));85 console.log('SITE=' + JSON.stringify(c.site || ''));86 } catch(e) {87 console.log('ORG='); console.log('SITE=');88 }89")90echo "org=${ORG:-NOT SET} site=${SITE:-NOT SET}"91```9293If both `ORG` and `SITE` are set, confirm with the user:9495> "Previously used: org=`{ORG}`, site=`{SITE}`. Do you want to continue with these? If not, provide a different site URL (e.g., `https://main--mysite--myorg.aem.page/`)."9697- If user confirms → proceed98- If user provides a URL → parse org and site from it, save the new values99100If `ORG` or `SITE` is empty, ask:101102> "Enter the site preview/live URL for which you want to perform ops (e.g., `https://main--mysite--myorg.aem.page/`)."103104Parse org and site from the URL:105106```bash107URL="$USER_INPUT"108if echo "$URL" | grep -q '\.aem\.page\|\.aem\.live'; then109 HOST_PART=$(echo "$URL" | cut -d'/' -f3 | cut -d'.' -f1)110 ORG=$(echo "$HOST_PART" | awk -F'--' '{print $NF}')111 SITE=$(echo "$HOST_PART" | awk -F'--' '{print $(NF-1)}')112 echo "Parsed from URL: org=$ORG site=$SITE"113fi114```115116If the user provides something other than a valid `.aem.page` or `.aem.live` URL, ask again.117118Save org and site:119120```bash121mkdir -p "${HOME}/.aem"122node -e "123 const fs = require('fs');124 const p = process.env.HOME + '/.aem/ops-config.json';125 let c = {};126 try { c = JSON.parse(fs.readFileSync(p, 'utf8')); } catch(e) {}127 c.org = '${ORG}';128 c.site = '${SITE}';129 fs.writeFileSync(p, JSON.stringify(c, null, 2));130"131```132133Only use org/site from `~/.aem/ops-config.json` or direct user input. Never infer from `git remote`, `fstab.yaml`, or folder/repo names.134135Do NOT proceed until both org and site are confirmed.136137### Step 1: Authenticate (REQUIRED)138139Before ANY API call, check if auth token exists:140141```bash142AUTH_TOKEN=$(node -e "143 const fs = require('fs');144 try {145 const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));146 if (t.authToken && t.authTokenExpiry > Math.floor(Date.now()/1000) + 60) {147 process.stdout.write(t.authToken);148 }149 } catch (e) {}150")151echo "auth=${AUTH_TOKEN:+set}"152```153154If `AUTH_TOKEN` is empty, invoke the auth skill before proceeding:155156```157Skill({ skill: "aem-project-management:auth" })158```159160Use `-H "x-auth-token: ${AUTH_TOKEN}"` header for all `admin.hlx.page` API calls.161162For sensitive endpoints and destructive operations, read `resources/security.md` and `resources/sensitive.md` before proceeding.163164### Step 2: Load Full Configuration and Validate Role165166```bash167eval $(node -e "168 const fs = require('fs');169 try {170 const c = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ops-config.json', 'utf8'));171 console.log('ORG=' + JSON.stringify(c.org || ''));172 console.log('SITE=' + JSON.stringify(c.site || ''));173 console.log('REF=' + JSON.stringify(c.ref || 'main'));174 } catch(e) {175 console.log('ORG='); console.log('SITE='); console.log('REF=main');176 }177")178AUTH_TOKEN=$(node -e "179 const fs = require('fs');180 try {181 const t = JSON.parse(fs.readFileSync(process.env.HOME + '/.aem/ims-token.json', 'utf8'));182 process.stdout.write(t.authToken || '');183 } catch (e) {}184")185echo "Config: org=$ORG site=$SITE ref=$REF auth=${AUTH_TOKEN:+set}"186```187188Fetch profile to verify auth and record user identity:189190```bash191PROFILE_RESPONSE=$(curl -s -w "\n%{http_code}" \192 -H "x-auth-token: ${AUTH_TOKEN}" \193 "https://admin.hlx.page/profile")194HTTP_CODE=$(echo "$PROFILE_RESPONSE" | tail -n1)195PROFILE=$(echo "$PROFILE_RESPONSE" | sed '$d')196197if [ "$HTTP_CODE" = "401" ]; then198 echo "Auth token expired. Need to re-authenticate..."199 echo "REAUTH_REQUIRED"200 exit 1201elif [ "$HTTP_CODE" != "200" ]; then202 echo "Failed to fetch profile (HTTP $HTTP_CODE). Check network/API status."203 exit 1204fi205206eval $(echo "$PROFILE" | node -e "207 const d = require('fs').readFileSync(0,'utf8');208 try {209 const p = JSON.parse(d).profile || {};210 console.log('USER_EMAIL=' + JSON.stringify(p.email || ''));211 console.log('USER_NAME=' + JSON.stringify(p.name || ''));212 } catch(e) { console.log('USER_EMAIL=\"\"'); console.log('USER_NAME=\"\"'); }213")214215echo "Authenticated as: $USER_EMAIL ($USER_NAME)"216```217218If `REAUTH_REQUIRED`, invoke the auth skill and retry.219220To determine user role on the site, check the site access config:221222```bash223curl -s -H "x-auth-token: ${AUTH_TOKEN}" \224 "https://admin.hlx.page/config/${ORG}/sites/${SITE}.json"225```226227If an operation returns 403, inform the user which role is required:228229| Permission | Required Role |230|-----------|---------------|231| Preview | `basic_author`, `author`, `publish`, or `admin` |232| Publish to live | `basic_publish`, `publish`, or `admin` |233| Unpublish | `publish` or `admin` |234| Code sync | `develop` or `admin` |235| Config read | `config`, `config_admin`, or `admin` |236| Config write | `config_admin` or `admin` |237| Snapshot manage | `author`, `publish`, or `admin` |238239Save `email` to `~/.aem/ops-config.json` for future use.240241Read `resources/config.md` if site or other values are missing.242243### Step 3: Route by Intent244245| User Intent | Resource Module |246|-------------|-----------------|247| preview, publish, unpublish, status, delete preview | `resources/content.md` |248| cache, purge, clear cache, invalidate | `resources/cache.md` |249| sync code, deploy code, update code | `resources/code.md` |250| reindex, index, remove from index, search | `resources/index.md` |251| sitemap, generate sitemap | `resources/sitemap.md` |252| snapshot, staged release, bundle | `resources/snapshots.md` |253| logs, audit, activity | `resources/logs.md` |254| user, access, permission, who am i, add user, remove user | `resources/users.md` |255| job, bulk operation, stop job | `resources/jobs.md` |256| site, branch, switch, list sites | `resources/sites.md` |257| org config, site config, robots.txt | `resources/config-api.md` |258| secret, secrets, create secret, delete secret | `resources/secrets.md` |259| API key, apikey, create key, revoke key | `resources/apikeys.md` |260| token, tokens, access token | `resources/tokens.md` |261| profile config, profile settings | `resources/profiles.md` |262| index config, helix-index, search config | `resources/index-config.md` |263| sitemap config, helix-sitemap, sitemap rules | `resources/sitemap-config.md` |264| version, versions, history, rollback, restore | `resources/versioning.md` |265| pages, list pages, indexed pages, all pages | `resources/pages.md` |266| da, da list, da source, da copy, da move, da delete, da config, da versions | `resources/da.md` |267| destructive operation, confirmation required | `resources/security.md` |268| sensitive endpoint (emails, credentials, API keys) | `resources/sensitive.md` |269270### Step 4: Read Resource and Execute2712721. Read the appropriate resource file from `resources/`2732. Follow instructions in that resource2743. For config updates: always GET current config first and show it to the user before modifying2754. For code sync: always check repoless status before syncing (see `code.md`)2765. For destructive operations: read `resources/security.md` and follow the Confirmation Protocol — no exceptions (state action, explain impact, ask "yes/no", only execute after "yes")2776. Execute the API call2787. Handle response per completion standards below279280### Completion Standards281282| HTTP Response | Meaning | Required Action |283|---------------|---------|-----------------|284| **200/201** | Success | Display result with full URLs (`https://{ref}--{site}--{org}.aem.page{path}`) |285| **202** | Async job started | Report job name; instruct: `check job status {jobName}` to track progress |286| **204** | Success (no body) | Confirm: "{action} completed for {path}" |287| **4xx/5xx** | Error | Show API error verbatim, then suggest fix per `resources/errors.md` |288289Before reporting success:290- For content operations: include both preview and live URLs where applicable291- For bulk operations: never say "published" or "previewed" — say "job started" until job completes292- For destructive operations: confirm what was removed and what still exists293294---295296## URL Parsing Helper297298If user provides an AEM URL instead of separate org/site/path values:299300```bash301# Pattern: https://{ref}--{site}--{org}.aem.page{path}302URL="$USER_INPUT"303if echo "$URL" | grep -q '\.aem\.page\|\.aem\.live'; then304 DOMAIN=$(echo "$URL" | cut -d'/' -f3)305 HOST_PART=$(echo "$DOMAIN" | cut -d'.' -f1)306 REF=$(echo "$HOST_PART" | awk -F'--' '{print $1}')307 ORG=$(echo "$HOST_PART" | awk -F'--' '{print $NF}')308 SITE=$(echo "$HOST_PART" | awk -F'--' '{309 r=""; for(i=2;i<NF;i++) r=(r==""?"":r"--")$i; print r310 }')311 URL_PATH=$(echo "$URL" | sed 's|https://[^/]*||')312 URL_PATH=${URL_PATH:-/}313 echo "Parsed from URL: org=$ORG site=$SITE ref=$REF path=$URL_PATH"314fi315```316317Examples: `uat--hmns-uat-kw--alshaya-axp.aem.page` → `ref=uat`, `site=hmns-uat-kw`, `org=alshaya-axp`.318319---320321## Prerequisites3223231. **Onboarded to Admin Service** — Project must have admin.hlx.page access3242. **User has an account** — Required for authentication (supports federated login)3253. **User has a site role** — Roles defined in site configuration (`access.admin.role`). Eight roles: `admin`, `author`, `publish`, `develop`, `basic_author`, `basic_publish`, `config`, `config_admin`. If the user lacks a role, the API returns 403.3264. **Network access** — Can reach admin.hlx.page327328---329330## Help Response331332When the user wants the command list (triggers: `help`, `what can you do?`, `/ops help`, `list commands`):333334```335Content Operations:336 preview /path - Update preview337 publish /path - Publish to live338 unpublish /path - Remove from live339 status /path - Check preview/live status340341Cache Operations:342 clear cache /path - Purge CDN cache343 force clear cache - Force purge344345Code Operations:346 sync code - Deploy latest code347348Index Operations:349 reindex /path - Re-index for search350351Sitemap:352 generate sitemap - Create sitemap.xml353354Snapshots:355 create snapshot {name} - Create staged release356 publish snapshot {name}- Publish all in snapshot357358Logs:359 show logs - View recent logs360 show logs last hour - Filtered by time361362Users:363 add user@email as role - Grant access364 remove role user@email - Revoke access365 who am i - Current user366367Jobs:368 list jobs - Show bulk operations369 stop job {name} - Cancel job370371Sites:372 list sites - Show all sites373 switch to site-x - Change active site374 use branch feat-x - Set branch375376Config:377 show org config - View org settings378 show site config - View site settings379 update robots.txt - Modify crawler rules380381Secrets:382 list secrets - Show secrets383 create secret {name} - Add new secret384 delete secret {name} - Remove secret385386API Keys:387 list API keys - Show API keys388 create API key {name} - Generate new key389 revoke API key {id} - Delete key390391Profiles:392 show profile config - View profile settings393 create profile {id} - Create profile config394 delete profile {id} - Remove profile config395396Index Config:397 show index config - View query.yaml398 update index config - Modify indexing rules399400Sitemap Config:401 show sitemap config - View sitemap.yaml402 update sitemap config - Modify sitemap rules403404Versioning:405 list versions - Show config history406 restore version {id} - Rollback to version407408Pages:409 list pages - Show all indexed pages410 list pages /blog - Filter by path prefix411412Document Authoring (DA):413 da auth - Authenticate with DA414 da list - List DA organizations415 da list /path - List files in DA path416 da source /path - Get file content from DA417 da copy /src to /dest - Copy file/folder in DA418 da move /src to /dest - Move/rename in DA419 da delete /path - Delete from DA420 da upload /path - Upload content to DA421 da upload media /path - Upload image/media to DA422 da config - View DA site config423 da update config - Update DA site config424 da versions /path - List file versions425 da create version - Create labeled version snapshot426 da restore version X - Restore a previous version427 da preview /path - Preview DA content428 da publish /path - Publish DA content429```