Skip to main content

cf-agent

A command-line tool for managing Adobe AEM Content Fragments for the Moveworks Marketplace — connectors and plugins.

Create, edit, publish, and inspect fragments across PROD / STAGE / DEV with an interactive guided mode or scriptable one-liners. Every rule (field types, allowed values, length limits, required fields) is read live from the AEM model, so the CLI always matches what AEM enforces.


Features

  • Interactive guided mode (-i) for creating and editing — pick from lists, see field descriptions, validate as you type.
  • Scriptable one-liners (-f name=value) for automation.
  • Edit without a UUID — find and select a fragment by model + name filter, or by slug.
  • Live validation against the model: required fields, enums, max-length, regex, kebab-case slugs, duplicate-slug detection, and cross-field rules.
  • Content guides from markdown files, with automatic checking that every referenced AEM image exists.
  • Upload assets straight from your machine (asset upload) — logos and content-guide images go into the DAM without opening AEM.
  • Smart defaults — logo/asset folders auto-prefixed, plugin slugs seeded with the system name, model folders chosen automatically.
  • Guardrails — immutable fields and review-locked fragments are caught up front, not after you fill in a form.
  • Command history — ↑/↓ recall previous entries in interactive prompts.

Table of Contents


Installation

Requires Python 3.10+. Install into a virtual environment to keep it isolated.

# 1. Create & activate a virtual environment
python3 -m venv ~/.venvs/cf-agent
source ~/.venvs/cf-agent/bin/activate

# 2. Install cf-agent
pip install "git+https://github.com/krishnakumar1990/cf-agent.git"

# 3. Verify
cf-agent --help

New terminal later? Re-activate first: source ~/.venvs/cf-agent/bin/activate To auto-activate in every shell: echo 'source ~/.venvs/cf-agent/bin/activate' >> ~/.zshrc

To upgrade, uninstall, or reinstall, see Troubleshooting / Debug.


Authentication

Login uses Adobe IMS OAuth (browser-based). Credentials are stored in ~/.cf-agent/config, tokens in ~/.cf-agent/tokens.

cf-agent login          # prompts for Adobe Client ID + Secret, opens browser, then pick an environment
cf-agent whoami         # show the authenticated user, org, scopes, and active environment
cf-agent logout         # clear stored tokens

If your team shares a preset with pre-filled config:

cf-agent login --preset shared.env

Tokens expire; if you see "Not logged in" or a 401, run cf-agent login again.


Environments

One login works across all environments. The active environment is where every fragment operation runs.

cf-agent env list       # show PROD / STAGE / DEV and which is current
cf-agent env select     # switch interactively
cf-agent env current    # show the active environment

Field reference

Field names, types, and rules are read from the live model. These are the fields for each type today.

Connector (marketplace-connector)

Field Required Rules
marketplace_name ✅ Title Case; max 255
slug ✅ lowercase kebab-case; contains the system name; unique; immutable
description ✅ ends with .; max 400
logo ✅ an SVG hosted in AEM; enter the file name only (auto-prefixed to the logos folder)
solution_tags ✅ pick from the list or type a new Title Case tag; multiple allowed
product_family ✅ from the model list (e.g. Google Cloud, Microsoft Graph)
content_guide — markdown guide; supply a file path
video — YouTube / Vimeo / Loom URL

Plugin (marketplace-plugin)

Field Required Rules
marketplace_name ✅ Title Case; must not include the system name; max 255
slug ✅ lowercase kebab-case; must start with a system (e.g. workday-view-pto); unique; immutable
description ✅ ends with .; max 400
availability ✅ from the model (VALIDATED, INSTALLABLE, IDEA, BUILT_IN); immutable after create
installation_asset_uuid ⛔/✅ required when availability = INSTALLABLE, forbidden otherwise; lowercase UUID
solution_tags ✅ pick from the list or type a new Title Case tag; multiple allowed
purple_chat_link ✅ starts with https://marketplace.moveworks.com/purple-chat?conversation; no mock_id; max 30000
systems ✅ from the model list; multiple allowed; immutable
agent_capabilities — from the model list (e.g. Ambient Agent)
content_guide — markdown guide; supply a file path
video — YouTube / Vimeo / Loom URL

Field names come from the live model — the interactive prompts always show the exact current name. installation_asset_uuid was formerly installation_uuid; the CLI accepts both during the transition.

reviewRequired — setting this to true sends the fragment to review, which locks it from further edits until an approver releases it. Leave it off until the content is final.


Creating a fragment

Interactive (recommended)

cf-agent fragments create -i

Walks you through it: pick the model, then it fills the folder automatically and prompts each field with its rules. For plugins it asks for systems first and pre-seeds the slug (workday-…); installation_asset_uuid is only asked when availability is INSTALLABLE. Each value is validated as you enter it.

One-liner — Connector

cf-agent fragments create \
  --parent-path "/content/dam/marketplace/content-fragment-resources/connector" \
  --model-path  "/conf/marketplace/settings/dam/cfm/models/marketplace-connector" \
  --name  "google-drive-connector" \
  --title "Google Drive Connector" \
  -f marketplace_name="Google Drive Connector" \
  -f slug="google-drive-connector" \
  -f description="Connects to Google Drive to search and retrieve files." \
  -f logo="google-drive.svg" \
  -f solution_tags="IT,Productivity" \
  -f product_family="Google Workspace" \
  -f content_guide=~/Desktop/connector-guide.md

One-liner — Plugin

cf-agent fragments create \
  --parent-path "/content/dam/marketplace/content-fragment-resources/plugin" \
  --model-path  "/conf/marketplace/settings/dam/cfm/models/marketplace-plugin" \
  --name  "workday-view-pto-balance" \
  --title "View PTO Balance" \
  -f marketplace_name="View PTO Balance" \
  -f slug="workday-view-pto-balance" \
  -f description="Check your current PTO balance from the Moveworks AI Assistant." \
  -f availability="VALIDATED" \
  -f solution_tags="HR - Time & Absence,HR - Employee Records" \
  -f purple_chat_link="https://marketplace.moveworks.com/purple-chat?conversation=%7B%22messages%22%3A%5B%5D%7D" \
  -f systems="workday" \
  -f agent_capabilities="Ambient Agent" \
  -f content_guide=~/Desktop/plugin-guide.md

For an INSTALLABLE plugin, use -f availability="INSTALLABLE" and add -f installation_asset_uuid="34cff60f-f3c8-48f9-b1c9-7658ead0d994".

Multi-value fields are comma-separated inside one flag: -f solution_tags="HR - Benefits,IT".


Updating a fragment

You can identify the fragment three ways — no UUID required.

1. Interactive (recommended)

cf-agent fragments update -i
  • Pick the model (connector / plugin).
  • Type a filter (name or slug) — or Enter to list all.
  • Choose from the numbered results.
  • Edit each editable field; press Enter to skip (keep the current value). Enums show their pick-list, exactly like create.

2. By slug (scriptable)

cf-agent fragments update --slug google-drive-connector \
  --model-path "/conf/marketplace/settings/dam/cfm/models/marketplace-connector" \
  -f content_guide=~/Desktop/updated-guide.md

3. By id

cf-agent fragments update <id> -f description="Updated description."

Which fields are editable

Only these fields can be changed on update — everything else is locked.

Model Editable fields
Connector logo, content_guide
Plugin marketplace_name, description, purple_chat_link, solution_tags, installation_asset_uuid, content_guide

Locked (cannot be changed after creation): slug, systems, availability. Attempting to change one — or to edit any non-listed field — is rejected with a clear message.

Review-locked fragments: if a fragment was sent to review (reviewRequired = true), the CLI tells you immediately on selection that it's locked and can't be edited until the review is completed or cancelled in AEM — so you don't fill in a form only to be refused at the end.


Content guides & images

content_guide is a markdown guide supplied as a file path (both create and update):

-f content_guide=~/Desktop/my-guide.md

When you provide the file, the CLI reads it and verifies every AEM image it references exists. It checks /content/dam/... paths in markdown images ![](…), links [](…), and HTML <img src="…"> (full AEM URLs too). If any referenced image is missing, the operation is blocked and the missing paths are listed.

Workflow for images: upload the image to AEM first — cf-agent asset upload ./shot.png --image (see Uploading assets) or by hand in AEM — reference it by the /content/dam/... path it returns, then create/update the guide. Relative image paths from a raw export (e.g. ![](image.png)) are not uploaded automatically — upload them and reference them by DAM path.


Other fragment commands

# List (optionally by folder)
cf-agent fragments list --path /content/dam/marketplace/content-fragment-resources/connector --limit 25

# Get one by id
cf-agent fragments get <id>

# Dry-run validate a payload against the model — no write
cf-agent fragments validate --model-path "$CONN_M" -f description="A connector." --partial

# Publish one or more
cf-agent fragments publish <id> [<id> ...]

# Delete (‑‑yes to skip the prompt)
cf-agent fragments delete <id> --yes

# Copy to another folder (‑‑deep to include references)
cf-agent fragments copy <id> --destination /content/dam/.../archive [--deep]

# List variations
cf-agent fragments variations <id>

cf-agent fragments search exists but the underlying AEM search endpoint is not available on all environments — prefer fragments list or the update -i filter to find fragments.


Models & assets

# List Content Fragment Models (connector, plugin, …)
cf-agent models list

# Check whether an asset exists in the DAM (bare name resolved against a known folder)
cf-agent asset exists workday.svg --logo
cf-agent asset exists /content/dam/marketplace/logos/workday.svg

asset exists returns exit code 0 if present, 1 if not — usable in scripts. It requires the aem.assets.author scope.


Uploading assets

asset upload puts a local file into the AEM DAM, so logos and content-guide images no longer have to be uploaded by hand in AEM.

One-time setup

Store your AWS credentials once — they are used to stage the file (see How it works below). Ask the team for a key; it will be sent to you securely.

cf-agent asset credentials set

You are prompted for both values. The secret is hidden as you paste it, so it never lands in your shell history.

cf-agent asset credentials show    # confirm they're stored (never prints the secret)
cf-agent asset credentials clear   # remove them

Credentials are kept in your OS keychain — macOS Keychain, Windows Credential Manager, or the Linux Secret Service — encrypted at rest, never in a plaintext file and never in the repo. Nothing else needs configuring: the staging bucket, region and prefix ship with the CLI.

Upload

# Into the marketplace logos folder
cf-agent asset upload ./workday.svg --logo

# Into the marketplace images folder
cf-agent asset upload ./screenshot.png --image

# Into any DAM folder
cf-agent asset upload ./diagram.png --root /content/dam/marketplace/screenshots

# Rename on the way in
cf-agent asset upload ./local-name.png --logo --name workday.svg

On success it prints the DAM path and assetId:

✓ Uploaded: /content/dam/marketplace/logos/workday.svg
  assetId: urn:aaid:aem:d3fc8f49-4c8f-49ee-b01f-3f00999201b0

Use that /content/dam/... path directly as a logo value or in content-guide markdown. Add --json for scripting.

How it works

AEM's Assets API cannot accept a binary directly from your user token — it can only pull an asset from a URL. So the CLI uploads the file to an S3 staging bucket, hands AEM a short-lived pre-signed URL to fetch it from, waits for the import to finish, then deletes the staged copy. This is why AWS credentials are needed at all; the staged object is temporary and removed automatically.

Credential precedence: AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY environment variables win if set (useful in CI), then the OS keychain, then any ~/.aws profile. Set nothing and the keychain is used.


Troubleshooting / Debug

Update the CLI to the latest version

source ~/.venvs/cf-agent/bin/activate
pip install --upgrade "git+https://github.com/krishnakumar1990/cf-agent.git"
cf-agent --help        # confirm it still runs

Uninstall & reinstall

source ~/.venvs/cf-agent/bin/activate

# uninstall
pip uninstall cf-agent

# reinstall (fresh copy)
pip install "git+https://github.com/krishnakumar1990/cf-agent.git"

For a completely clean slate, delete and recreate the virtual environment:

deactivate 2>/dev/null
rm -rf ~/.venvs/cf-agent
python3 -m venv ~/.venvs/cf-agent
source ~/.venvs/cf-agent/bin/activate
pip install "git+https://github.com/krishnakumar1990/cf-agent.git"

Uninstalling does not remove your login. Config and tokens live in ~/.cf-agent/ — delete that folder to fully reset (rm -rf ~/.cf-agent), then cf-agent login again.

Common errors

Message Cause & fix
Not logged in / 401 Token expired → cf-agent login.
403 Forbidden — You are not allowed to modify this fragment The fragment is review-locked (reviewRequired = true) or your Adobe ID lacks write access on this environment. Release the review in AEM, or ask an admin for access.
… is in review and locked Sent to review — complete/cancel the review in AEM, then retry.
Field 'X' is not editable on update Only the editable fields above can change on update.
Field 'X' cannot be changed after creation slug / systems / availability are immutable.
Slug '…' is already in use Choose a unique slug.
Referenced asset does not exist in AEM The logo / a content-guide image isn't in the DAM — upload it with cf-agent asset upload … --logo / --image, or check with cf-agent asset exists ….
cf-agent: command not found The venv isn't active → source ~/.venvs/cf-agent/bin/activate.
Asset upload requires boto3 / requires 'keyring' Your install predates 1.1.0, when these became base dependencies → pip install --upgrade "git+https://github.com/krishnakumar1990/cf-agent.git".
Could not stage file to S3: access denied The AWS key lacks permission on the staging bucket, or none is set → cf-agent asset credentials show.
The staged file isn't readable via its pre-signed URL The AWS key can write but not read the staging bucket — it needs s3:GetObject too. Ask the team for a corrected key.

Inspect your session

cf-agent whoami        # user, org, scopes, token expiry, active environment
cf-agent env current   # which environment you're pointed at

whoami is the fastest way to debug 403s — confirm the token's org matches the environment.

Metadata

Release files for cf-agent 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for cf-agent 1.1.0
File Size Uploaded
cf_agent-1.1.0.tar.gz 51.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for cf-agent 1.1.0
File Interpreter ABI Platform
cf_agent-1.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 104.0 kB

Release files / cf_agent-1.1.0.tar.gz

Download URL cf_agent-1.1.0.tar.gz
Size 51.1 kB
Tags Source
SHA-256 checksum
How to use checksums
01515ab8b9ed7512161f2b07aba29bad5127b0280b0909c466c5216644e12c56
BLAKE2b-256 checksum
How to use checksums
62b66e25959bb940d3c579c2fdba6ac7e0b78356ed578094649cf20bb8af74b9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / cf_agent-1.1.0-py3-none-any.whl

Download URL cf_agent-1.1.0-py3-none-any.whl
Size 52.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
046db606b54649f07ec9a2748ef8866f81d3ad36e75059ca96f5d7bd00c169b0
BLAKE2b-256 checksum
How to use checksums
f58ba27b4879a7639ea36bd3b73d718411181bbb26bbe839df2666006660d0dd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

1.3.3

2 release files

1.3.2

2 release files

1.3.1

2 release files

1.3.0

2 release files

1.2.0

2 release files

This release

1.1.0 This release

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page