{"id":28448418,"url":"https://github.com/bpauli/aemcli","last_synced_at":"2025-07-01T02:31:35.361Z","repository":{"id":295956319,"uuid":"991752877","full_name":"bpauli/aemcli","owner":"bpauli","description":"A command-line tool for Adobe Experience Manager (AEM) content management","archived":false,"fork":false,"pushed_at":"2025-06-02T13:35:31.000Z","size":121,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-06-06T13:08:30.443Z","etag":null,"topics":["aem","aem-tools","cli","cms"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bpauli.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-28T05:22:40.000Z","updated_at":"2025-06-02T13:35:35.000Z","dependencies_parsed_at":"2025-05-28T08:36:24.106Z","dependency_job_id":"66997ff3-c21b-415a-a65f-14483a18d403","html_url":"https://github.com/bpauli/aemcli","commit_stats":null,"previous_names":["bpauli/aemcli"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bpauli/aemcli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpauli%2Faemcli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpauli%2Faemcli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpauli%2Faemcli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpauli%2Faemcli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bpauli","download_url":"https://codeload.github.com/bpauli/aemcli/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bpauli%2Faemcli/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262883632,"owners_count":23379228,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["aem","aem-tools","cli","cms"],"created_at":"2025-06-06T13:08:29.291Z","updated_at":"2025-07-01T02:31:35.343Z","avatar_url":"https://github.com/bpauli.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AEM CLI\n\n[![Tests](https://github.com/bpauli/aemcli/workflows/Tests/badge.svg)](https://github.com/bpauli/aemcli/actions/workflows/test.yml)\n[![CI](https://github.com/bpauli/aemcli/workflows/CI/badge.svg)](https://github.com/bpauli/aemcli/actions/workflows/ci.yml)\n\nA command-line tool for Adobe Experience Manager (AEM) content management and cleanup operations.\n\n## Overview\n\nAEM CLI provides utilities for managing AEM content repositories, with a focus on cleaning and maintaining `.content.xml` files and transferring JCR content between filesystem and server. The tool helps developers and content managers automate common AEM maintenance tasks.\n\n## Commands\n\n- **[content-cleanup](#content-cleanup-command)** - Clean AEM metadata properties and remove nodes from `.content.xml` files\n- **[asset-remove-unused](#asset-remove-unused-command)** - Find and remove unused DAM assets with reference checking\n- **[repo](#repository-content-transfer-command)** - FTP-like tool for JCR content transfer between filesystem and server\n\n## Features\n\n### Content Cleanup\n- **Remove AEM metadata properties** from `.content.xml` files\n- **Remove nodes and folders** with automatic name mangling support\n- **Flexible property selection** - use default AEM properties or specify custom ones\n- **Recursive processing** - handles entire directory trees\n- **Dry-run mode** - preview changes before applying them\n- **Detailed reporting** - see exactly what properties and nodes are removed\n\n#### Property Cleanup\nThe tool removes common AEM system properties that are typically not needed in source control:\n\n- `cq:isDelivered`, `cq:lastModified`, `cq:lastModifiedBy`\n- `cq:lastReplicated*`, `cq:lastReplicatedBy*`, `cq:lastReplicationAction*`\n- `jcr:isCheckedOut`, `jcr:lastModified`, `jcr:lastModifiedBy`, `jcr:uuid`\n\n#### Node Cleanup\n- **Remove specific nodes** from all `.content.xml` files\n- **Delete corresponding folders** with matching names\n- **Automatic name mangling** - handles JCR to filesystem name conversion (e.g., `jcr:content` ↔ `_jcr_content`)\n- **Safe removal** - preserves other nodes and content structure\n- **Current directory default** - works from any directory without specifying paths\n\n### Asset Cleanup\n- **Find unused DAM assets** with common MIME types (images, videos, documents, audio)\n- **Reference checking** - scans all `.content.xml` files for `image` and `fileReference` properties\n- **Smart thumbnail cleanup** - handles `dam:folderThumbnailPaths` references properly\n- **Confirmation prompts** - asks for confirmation before deletion with detailed summary\n- **Dry-run mode** - preview what would be deleted without making changes\n- **Comprehensive reporting** - shows used vs unused assets with reference counts\n\n#### Supported Asset Types\nThe tool focuses on common MIME types that are typically managed in DAM:\n\n- **Images**: JPEG, PNG, GIF, WebP, SVG, BMP, TIFF\n- **Videos**: MP4, AVI, MOV, WMV, FLV, WebM, MKV\n- **Documents**: PDF, Word, Excel, PowerPoint\n- **Audio**: MP3, WAV, OGG, AAC, M4A\n\n### Repository Content Transfer (repo)\n- **FTP-like tool for JCR content** with support for diffing\n- **Checkout** - initial checkout of server content to filesystem\n- **Put** - upload local filesystem content to server\n- **Get** - download server content to local filesystem\n- **Status** - list status of modified/added/deleted files\n- **Diff** - show differences between local and server content\n- **Configuration support** - `.repo` files for server/credentials\n- **Package-based transfers** - uses AEM package manager HTTP API\n\n## Installation\n\n### Prerequisites\n- Python 3.8 or higher\n- pip package manager\n\n### Install from Source\n```bash\n# Clone the repository\ngit clone \u003crepository-url\u003e\ncd aemcli\n\n# Create virtual environment\npython -m venv .venv\nsource .venv/bin/activate  # On Windows: .venv\\Scripts\\activate\n\n# Install dependencies\npip install -r requirements.txt\n\n# Install the package in development mode\npip install -e .\n```\n\n## Usage\n\n### Content Cleanup Command\n\nThe `content-cleanup` command has two subcommands for different types of cleanup operations:\n\n#### Property Cleanup (content-cleanup property)\n\n##### Basic Usage\n```bash\n# Clean using default AEM properties\naemcli content-cleanup property /path/to/content\n\n# Preview changes without modifying files\naemcli content-cleanup property /path/to/content --dry-run\n```\n\n##### Advanced Usage\n```bash\n# Use only custom properties\naemcli content-cleanup property /path/to/content cq:customProp jcr:myProp\n\n# Combine default and custom properties\naemcli content-cleanup property /path/to/content --default cq:customProp\n\n# Explicitly use default properties\naemcli content-cleanup property /path/to/content --default\n```\n\n##### Options\n- `--dry-run` - Show what would be changed without modifying files\n- `--default` - Include default AEM properties in removal list\n- `--help` - Show detailed help and examples\n\n#### Node Cleanup (content-cleanup node)\n\n##### Basic Usage\n```bash\n# Remove jcr:content nodes and folders from current directory\naemcli content-cleanup node jcr:content\n\n# Preview changes without modifying files\naemcli content-cleanup node jcr:content --dry-run\n\n# Remove nodes from specific path\naemcli content-cleanup node cq:dialog /path/to/content\n```\n\n##### Advanced Usage\n```bash\n# Remove different types of nodes\naemcli content-cleanup node rep:policy\naemcli content-cleanup node cq:EditConfig\naemcli content-cleanup node cq:childEditConfig\n\n# Remove nodes with special characters\naemcli content-cleanup node \"node-with-dashes\"\naemcli content-cleanup node \"node.with.dots\"\n```\n\n##### How Node Cleanup Works\n1. **Name Mangling**: Automatically handles JCR to filesystem name conversion\n   - `jcr:content` → `_jcr_content`\n   - `rep:policy` → `_rep_policy`\n   - Regular names remain unchanged\n2. **XML Processing**: Removes matching nodes from all `.content.xml` files\n   - Handles both self-closing tags (`\u003cnodeName /\u003e`) and tags with content\n   - Preserves other nodes and XML structure\n3. **Folder Removal**: Finds and removes folders with matching names (both original and mangled)\n4. **Safety Features**: Dry-run mode and detailed reporting\n\n##### Options\n- `--dry-run` - Show what would be changed without modifying files\n- `--help` - Show detailed help and examples\n\n### Asset Remove Unused Command\n\n#### Basic Usage\n```bash\n# Find and remove unused DAM assets (with confirmation)\naemcli asset-remove-unused /path/to/content/dam\n\n# Preview what would be deleted without making changes\naemcli asset-remove-unused /path/to/content/dam --dry-run\n```\n\n#### Advanced Usage\n```bash\n# Start from specific directory\naemcli asset-remove-unused content/dam/projects\n\n# Use current directory\naemcli asset-remove-unused .\n```\n\n#### How It Works\nThe command performs the following steps:\n\n1. **Asset Discovery**: Recursively finds all `.content.xml` files with `jcr:primaryType=\"dam:Asset\"` and common MIME types\n2. **Reference Scanning**: Checks all `.content.xml` files in the jcr_root structure for references via:\n   - `image=\"asset-path\"` properties\n   - `fileReference=\"asset-path\"` properties  \n   - `dam:folderThumbnailPaths=\"[asset-path,...]\"` properties\n3. **Smart Cleanup**: For assets only referenced in `folderThumbnailPaths`:\n   - Removes the asset path from the thumbnail array\n   - Marks asset for deletion\n4. **Confirmation**: Shows detailed summary and asks for confirmation before deletion\n5. **Deletion**: Removes entire parent folders containing unused asset `.content.xml` files\n\n#### Options\n- `--dry-run` - Preview what would be deleted without making any changes\n- `--help` - Show detailed help and examples\n\n#### Examples\n```bash\n# Preview unused assets in a project\naemcli asset-remove-unused content/dam/myproject --dry-run\n\n# Clean up unused assets with confirmation\naemcli asset-remove-unused content/dam/myproject\n\n# Check entire DAM folder\naemcli asset-remove-unused content/dam\n```\n\n### Repository Content Transfer Command\n\nThe `repo` command provides FTP-like functionality for transferring JCR content between the filesystem and AEM server.\n\n#### Basic Usage\n```bash\n# Initial checkout from server\naemcli repo checkout /apps/myproject\n\n# Upload changes to server\ncd jcr_root/apps/myproject\naemcli repo put\n\n# Download changes from server\naemcli repo get\n\n# Check status\naemcli repo status\n# or\naemcli repo st\n\n# Show differences\naemcli repo diff\n```\n\n#### Advanced Usage\n```bash\n# Use custom server and credentials\naemcli repo status -s http://localhost:8080 -u user:password\n\n# Force operations without confirmation\naemcli repo put -f\n\n# Quiet mode (minimal output)\naemcli repo get -q\n\n# Show server-side changes\naemcli repo serverdiff\n\n# Show local changes\naemcli repo localdiff\n```\n\n#### Configuration Files\n\n**`.repo` file** - Place in checkout or any parent directory:\n```\nserver=http://server.com:8080\ncredentials=user:password\n```\n\n**`.repoignore` file** - Place in jcr_root directory to exclude files:\n```\n*.tmp\n.cache/\n*.log\n```\n\n#### Available Commands\n- `checkout \u003cjcr-path\u003e` - Initial checkout of server content\n- `put [path]` - Upload local content to server\n- `get [path]` - Download server content to local\n- `status [path]` - Show status of files (alias: `st`)\n- `diff [path]` - Show local differences vs server\n- `localdiff [path]` - Show local changes\n- `serverdiff [path]` - Show server changes\n\n#### Status Legend\n- `M` - Modified\n- `A` - Added locally / deleted remotely\n- `D` - Deleted locally / added remotely\n- `~ fd` - Conflict: local file vs. remote directory\n- `~ df` - Conflict: local directory vs. remote file\n\n### Examples\n\n#### Example 1: Property Cleanup\n```bash\n# Clean all .content.xml files in an AEM project\naemcli content-cleanup property content/sites-franklin-commerce --dry-run\n\n# Apply the changes\naemcli content-cleanup property content/sites-franklin-commerce\n\n# Remove only specific custom properties\naemcli content-cleanup property /path/to/content cq:myCustomProp jcr:tempData\n\n# Remove default properties plus custom ones\naemcli content-cleanup property /path/to/content --default cq:myCustomProp\n```\n\n#### Example 2: Node Cleanup\n```bash\n# Remove jcr:content nodes and folders from current directory\ncd /path/to/aem/content\naemcli content-cleanup node jcr:content\n\n# Preview what would be removed\naemcli content-cleanup node cq:dialog --dry-run\n\n# Remove nodes from specific path\naemcli content-cleanup node rep:policy /path/to/content\n```\n\n#### Example 3: Repository Workflow\n```bash\n# Start from scratch with a server project\naemcli repo checkout /apps/myproject\n\n# Make local changes\ncd jcr_root/apps/myproject\nvim .content.xml\n\n# Check what changed\naemcli repo status\n\n# Upload changes\naemcli repo put\n\n# Later, download server changes\naemcli repo get\n\n# Show differences\naemcli repo diff\n```\n\n#### Example 4: Asset Cleanup Workflow\n```bash\n# Preview unused assets before deletion\naemcli asset-remove-unused content/dam/myproject --dry-run\n\n# Review the output, then proceed with cleanup\naemcli asset-remove-unused content/dam/myproject\n\n# Clean up entire DAM folder\naemcli asset-remove-unused content/dam --dry-run\naemcli asset-remove-unused content/dam\n```\n\n## Development\n\n### Project Structure\n```\naem-cli/\n├── src/aemcli/           # Main package\n│   ├── cli.py           # CLI entry point\n│   └── commands/        # Command modules\n│       ├── content_cleanup.py\n│       ├── asset_remove_unused.py\n│       └── repo.py\n├── tests/               # Test suite\n│   ├── test_content_cleanup.py\n│   ├── test_asset_remove_unused.py\n│   ├── test_repo.py\n│   └── test_content/    # Test data\n├── requirements.txt     # Dependencies\n├── pyproject.toml      # Project configuration\n└── README.md           # This file\n```\n\n### Running Tests\n```bash\n# Activate virtual environment\nsource .venv/bin/activate\n\n# Run all tests\npython -m pytest\n\n# Run with verbose output\npython -m pytest -v\n\n# Run with coverage\npython -m pytest --cov=aemcli\n```\n\n### Code Quality\n```bash\n# Format code\nblack src/ tests/\n\n# Lint code\nflake8 src/ tests/\n\n# Type checking\nmypy src/\n```\n\n### Local Development Checks\nRun the same checks locally that GitHub Actions will run:\n\n```bash\n# Quick checks (syntax and tests)\n./scripts/run_checks.sh\n\n# Full checks (includes linting, formatting, type checking, security)\n./scripts/run_checks.sh --full\n```\n\n### Pre-commit Hooks (Optional)\nSet up pre-commit hooks to run checks automatically before each commit:\n\n```bash\n# Install pre-commit hooks\npre-commit install\n\n# Run hooks on all files (optional)\npre-commit run --all-files\n```\n\n## CI/CD\n\nThis project uses GitHub Actions for continuous integration and deployment. Two workflows are configured:\n\n### Test Workflow (`test.yml`)\n- **Triggers**: Every push and pull request\n- **Purpose**: Quick feedback on test results and basic linting\n- **Actions**:\n  - Runs tests with pytest\n  - Performs basic syntax and error checking with flake8\n  - Uses Python 3.11 on Ubuntu\n\n### CI Workflow (`ci.yml`)\n- **Triggers**: Push/PR to main, master, or develop branches\n- **Purpose**: Comprehensive testing and code quality checks\n- **Actions**:\n  - **Multi-version testing**: Tests against Python 3.8, 3.9, 3.10, 3.11, and 3.12\n  - **Code quality**: Runs flake8, black, and mypy\n  - **Test coverage**: Generates coverage reports and uploads to Codecov\n  - **Security scanning**: Runs safety and bandit security checks\n  - **Dependency caching**: Speeds up builds by caching pip dependencies\n\n### Workflow Features\n- **Parallel execution**: Test and security jobs run in parallel\n- **Caching**: Pip dependencies are cached for faster builds\n- **Coverage reporting**: Automatic upload to Codecov (optional)\n- **Security checks**: Automated vulnerability scanning\n- **Multi-Python support**: Ensures compatibility across Python versions\n\n## Dependencies\n\n### Core Dependencies\n- **click\u003e=8.0** - Command-line interface framework\n- **requests\u003e=2.28** - HTTP library for AEM API calls\n\n### Development Dependencies\n- **pytest\u003e=7.0** - Testing framework\n- **pytest-cov\u003e=4.0** - Test coverage reporting\n- **black\u003e=23.0** - Code formatting\n- **flake8\u003e=6.0** - Code linting\n- **mypy\u003e=1.0** - Static type checking\n\n### Optional Dependencies\n- **colorama\u003e=0.4.6** - Cross-platform colored terminal text\n- **rich\u003e=13.0** - Rich text and beautiful formatting\n\n## Contributing\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feature/amazing-feature`)\n3. Make your changes\n4. Add tests for new functionality\n5. Run the test suite (`python -m pytest`)\n6. Commit your changes (`git commit -m 'Add amazing feature'`)\n7. Push to the branch (`git push origin feature/amazing-feature`)\n8. Open a Pull Request\n\n### Development Guidelines\n- Follow PEP 8 style guidelines\n- Add tests for new features\n- Update documentation as needed\n- Use type hints where appropriate\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Support\n\nFor questions, issues, or contributions, please:\n1. Check existing issues in the repository\n2. Create a new issue with detailed information\n3. Include steps to reproduce any bugs\n4. Provide example files when relevant\n\n## Changelog\n\nSee [CHANGELOG.md](CHANGELOG.md) for detailed version history and release notes.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbpauli%2Faemcli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbpauli%2Faemcli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbpauli%2Faemcli/lists"}