diff --git a/CHANGELOG.md b/CHANGELOG.md
index f2e8172..6dfe78c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,21 +6,9 @@ This project follows [Semantic Versioning](https://semver.org).
## [Unreleased]
-### Added
-- Initial structure for Customer Engineering template repo
-- GitHub Issue Forms for bug reports and feature requests
-- CI workflow with Python setup
-
-### Changed
-- N/A
-
-### Fixed
-- N/A
-
----
-
-## [1.0.0] - 2025-07-11
+## [Cloudsmith Docker Sleuth] [v1.0] [2025-12-12]
### Added
-- π First release of the CENG template!
-- Includes CI, GitHub forms, CONTRIBUTING, CODEOWNERS, and PR template
\ No newline at end of file
+- Analyze your Cloudsmith Docker repositories with a hierarchical view of multi-arch tags,
+manifest digests, platform support, sync status, and download statistics.
+- Query untagged (orphaned) multi-arch images and delete them.
diff --git a/Docker/Cloudsmith Docker Sleuth/README.md b/Docker/Cloudsmith Docker Sleuth/README.md
new file mode 100644
index 0000000..3899a85
--- /dev/null
+++ b/Docker/Cloudsmith Docker Sleuth/README.md
@@ -0,0 +1,114 @@
+# Cloudsmith Docker Sleuth
+
+
+
+ββββββββββ βββββββ βββ ββββββββββ ββββββββββββ βββββββββββββββββββ βββ
+βββββββββββ ββββββββββββ ββββββββββββββββββββββββ ββββββββββββββββββββ βββ
+βββ βββ βββ ββββββ ββββββ βββββββββββββββββββββββββ βββ ββββββββ
+βββ βββ βββ ββββββ ββββββ βββββββββββββββββββββββββ βββ ββββββββ
+βββββββββββββββββββββββββββββββββββββββββββββββββββββ βββ ββββββ βββ βββ βββ
+ βββββββββββββββ βββββββ βββββββ βββββββ βββββββββββ ββββββ βββ βββ βββ
+
+βββββββ βββββββ ββββββββββ ββββββββββββββββββ βββββββββββ βββββββββββ βββββββββββββββ βββ
+ββββββββββββββββββββββββββββ ββββββββββββββββββββ βββββββββββ βββββββββββ βββββββββββββββ βββ
+βββ ββββββ ββββββ βββββββ ββββββ ββββββββ βββββββββββ ββββββ βββ βββ βββ ββββββββ
+βββ ββββββ ββββββ βββββββ ββββββ ββββββββ βββββββββββ ββββββ βββ βββ βββ ββββββββ
+ββββββββββββββββββββββββββββ ββββββββββββββ βββ βββββββββββββββββββββββββββββββββ βββ βββ βββ
+βββββββ βββββββ ββββββββββ ββββββββββββββ βββ ββββββββββββββββββββββββ βββββββ βββ βββ βββ
+
+
+
+**Analyze your Cloudsmith Docker repositories with a hierarchical view of multi-arch tags,
+manifest digests, platform support, sync status, and download statistics.**
+
+
+
+
+
+This Python script audits multi-architecture Docker images stored in your Cloudsmith repository. It interacts with both the Cloudsmith API and Docker Manifest V2 endpoints to provide a detailed analysis of your container images.
+
+Here is a summary of its capabilities:
+
+1. **Visualization & Hierarchy**
+ - **Rich Tables:** Uses the `rich` library to render formatted, colored terminal tables.
+ - **Manifest Lists:** Visually groups architecture-specific images (children) under their parent Manifest List tag.
+ - **Details:** Displays the Tag, Type (manifest/list vs. image), Platform (e.g., linux/amd64, linux/arm64), Status (with icons), Download Counts, and SHA256 Digests.
+2. **Inspection Modes**
+ - **Single Image:** Can inspect a specific image repository (e.g., `my-org/my-repo/my-image`).
+ - **Full Catalog:** If no image name is provided, it automatically fetches the catalog and scans every image in the repository.
+ - **Detailed View:** The `--detailed` flag expands the output to show every individual child digest and its specific download count, rather than just the summary.
+3. **Maintenance (Untagged Images)**
+ - **Detection:** The `--untagged` flag scans for "orphaned" manifest lists that exist but have no version tags associated with them.
+ - **Cleanup:** The `--untagged-delete` flag allows you to programmatically delete these untagged manifest lists to clean up the repository.
+4. **Data Aggregation**
+ - It combines data from two sources:
+ - **Docker Manifests:** To determine architecture/OS platforms and digest relationships.
+ - **Cloudsmith API:** To retrieve processing status (Synced, Failed, In Progress) and download statistics.
+
+#### Query repository for images
+
+
+#### Query a specific image and view detailed results.
+
+
+
+#### Query untagged images
+
+
+
+## Prerequisites
+
+1. **Python Environment**
+ Ensure you have Python 3 installed and the required library:
+ ```bash
+ pip install rich
+ ```
+
+2. **Cloudsmith API Key**
+ Configure the Cloudsmith environment variable with your PAT or Service Account Token.
+ ```bash
+ export CLOUDSMITH_API_KEY=
+ ```
+
+## How to use
+
+1. **Basic Usage**
+ Run the script targeting your Organization and Repository.
+
+ - Scan a specific image:
+ ```bash
+ python3 multiarch.py my-org my-repo my-image
+ ```
+
+ - Scan ALL images in the repository:
+ (Omit the image name)
+
+2. **Advanced Flags**
+ | Flag | Description |
+ |-----------------------|--------------------------------------------------------------|
+ | `--detailed` | Shows every child digest (arch/os) and individual download counts. |
+ | `--untagged` | Finds manifest lists that have no tags (orphaned). |
+ | `--untagged-delete` | Deletes any untagged manifest lists found. |
+
+3. **Examples**
+ - Get a summary of all tags for my-image:
+ ```bash
+ python3 multiarch.py my-org my-repo my-image
+ ```
+
+ - See full breakdown (platforms & digests) for all images:
+ ```bash
+ python3 multiarch.py my-org my-repo --detailed
+ ```
+
+ - Delete untagged manifest lists:
+ ```bash
+ python3 multiarch.py my-org my-repo my-image --untagged-delete
+ ```
+
+
+
+
+
+
+
diff --git a/Docker/Cloudsmith Docker Sleuth/example-detailed.gif b/Docker/Cloudsmith Docker Sleuth/example-detailed.gif
new file mode 100644
index 0000000..ebfb21e
Binary files /dev/null and b/Docker/Cloudsmith Docker Sleuth/example-detailed.gif differ
diff --git a/Docker/Cloudsmith Docker Sleuth/example-untagged.gif b/Docker/Cloudsmith Docker Sleuth/example-untagged.gif
new file mode 100644
index 0000000..b971fab
Binary files /dev/null and b/Docker/Cloudsmith Docker Sleuth/example-untagged.gif differ
diff --git a/Docker/Cloudsmith Docker Sleuth/example.gif b/Docker/Cloudsmith Docker Sleuth/example.gif
new file mode 100644
index 0000000..14d8fbe
Binary files /dev/null and b/Docker/Cloudsmith Docker Sleuth/example.gif differ
diff --git a/Docker/Cloudsmith Docker Sleuth/multiarch.py b/Docker/Cloudsmith Docker Sleuth/multiarch.py
new file mode 100755
index 0000000..cabecd3
--- /dev/null
+++ b/Docker/Cloudsmith Docker Sleuth/multiarch.py
@@ -0,0 +1,418 @@
+#!/usr/bin/env python3
+
+import sys
+import os
+import json
+import argparse
+import urllib.request
+import urllib.error
+from urllib.parse import urlencode
+import concurrent.futures
+
+# Try to import rich
+try:
+ from rich.console import Console
+ from rich.table import Table
+ from rich import box
+ from rich.text import Text
+except ImportError:
+ print("Error: This script requires the 'rich' library.")
+ print("Please install it using: pip install rich")
+ sys.exit(1)
+
+# --- Configuration & Constants ---
+
+console = Console()
+
+# API Config
+CLOUDSMITH_URL = os.environ.get("CLOUDSMITH_URL", "https://docker.cloudsmith.io")
+API_KEY = os.environ.get("CLOUDSMITH_API_KEY")
+AUTH_HEADER = {"Authorization": f"Bearer {API_KEY}"} if API_KEY else {}
+
+# --- Helper Functions ---
+
+def make_request(url, headers=None, method='GET', data=None):
+ """Performs an HTTP request and returns parsed JSON."""
+ if headers is None:
+ headers = {}
+
+ final_headers = {**AUTH_HEADER, **headers}
+
+ req = urllib.request.Request(url, headers=final_headers, method=method)
+ if data:
+ req.data = data.encode('utf-8')
+
+ try:
+ with urllib.request.urlopen(req) as response:
+ return json.loads(response.read().decode('utf-8'))
+ except urllib.error.HTTPError as e:
+ return None
+ except Exception as e:
+ # Avoid printing to stderr in threads to prevent garbled output
+ return None
+
+def find_key_recursive(obj, key):
+ """Recursively searches for a key in a dictionary/list and returns a list of values."""
+ results = []
+ if isinstance(obj, dict):
+ for k, v in obj.items():
+ if k == key:
+ results.append(v)
+ elif isinstance(v, (dict, list)):
+ results.extend(find_key_recursive(v, key))
+ elif isinstance(obj, list):
+ for item in obj:
+ results.extend(find_key_recursive(item, key))
+ return results
+
+def format_status(status_str):
+ """Returns a rich-formatted status string."""
+ if status_str == "Completed": return f"[green]{status_str}[/green] β
"
+ if status_str == "In Progress": return f"[yellow]{status_str}[/yellow] β³"
+ if status_str == "Quarantined": return f"[red]{status_str}[/red] β οΈ"
+ if status_str == "Failed": return f"[bold red]{status_str}[/bold red] β"
+ return status_str
+
+# --- Core Logic ---
+
+def get_digest_data(workspace, repo, img, digest, ntag_display, platform="unknown"):
+ """Fetches data for a specific digest (child image) and returns row data."""
+
+ # 1. Fetch Manifest to get Architecture (Only if unknown)
+ if platform == "unknown":
+ manifest_url = f"{CLOUDSMITH_URL}/v2/{workspace}/{repo}/{img}/manifests/{digest}"
+ manifest_json = make_request(manifest_url, {"Accept": "application/vnd.oci.image.manifest.v1+json", "Cache-Control": "no-cache"})
+
+ if manifest_json:
+ if 'manifests' in manifest_json:
+ found = False
+ for m in manifest_json['manifests']:
+ if m.get('digest') == digest:
+ p = m.get('platform', {})
+ platform = f"{p.get('os', '')}/{p.get('architecture', '')}"
+ found = True
+ break
+ if not found:
+ archs = find_key_recursive(manifest_json, 'architecture')
+ if archs: platform = archs[0]
+ else:
+ archs = find_key_recursive(manifest_json, 'architecture')
+ if archs: platform = archs[0]
+
+ # 2. Get Package Data from API
+ version = digest.replace("sha256:", "")
+ api_url = f"https://api.cloudsmith.io/v1/packages/{workspace}/{repo}/?query=version:{version}"
+ pkg_details = make_request(api_url, {"Cache-Control": "no-cache"})
+
+ status_display = ""
+ dl = 0
+
+ if pkg_details:
+ statuses = set(find_key_recursive(pkg_details, 'status_str'))
+ status_parts = [format_status(s) for s in statuses]
+ status_display = " ".join(status_parts)
+
+ downloads = find_key_recursive(pkg_details, 'downloads')
+ if len(downloads) >= 2:
+ dl = downloads[0]
+ elif len(downloads) > 0:
+ dl = downloads[0]
+
+ # Return tuple of (Row Columns List, Download Count)
+ row_data = [
+ f" ββ {ntag_display}",
+ "image",
+ platform,
+ status_display,
+ str(dl),
+ f"[dim]{digest}[/dim]"
+ ]
+ return row_data, dl
+
+def fetch_tag_data(workspace, repo, img, ntag, detailed=False):
+ """Fetches the manifest list for a tag and returns rows for the table."""
+
+ manifest_url = f"{CLOUDSMITH_URL}/v2/{workspace}/{repo}/{img}/manifests/{ntag}"
+ manifest_json = make_request(manifest_url, {"Accept": "application/vnd.oci.image.manifest.v1+json", "Cache-Control": "no-cache"})
+
+ if not manifest_json:
+ return []
+
+ # Parse out digests and platforms
+ children = []
+ if 'manifests' in manifest_json:
+ for m in manifest_json['manifests']:
+ d = m.get('digest')
+ p = m.get('platform', {})
+ os_name = p.get('os', 'linux')
+ arch = p.get('architecture', 'unknown')
+ plat = f"{os_name}/{arch}"
+
+ if d and arch.lower() != 'unknown':
+ children.append({'digest': d, 'platform': plat})
+ else:
+ # Fallback
+ digests = list(set(find_key_recursive(manifest_json, 'digest')))
+ for d in digests:
+ children.append({'digest': d, 'platform': 'unknown'})
+
+ if not children:
+ return []
+
+ # Process children
+ children_rows = []
+ total_downloads = 0
+
+ for child in children:
+ row, dl = get_digest_data(workspace, repo, img, child['digest'], ntag, platform=child['platform'])
+ children_rows.append(row)
+ total_downloads += dl
+
+ # Fetch parent package info
+ api_url = f"https://api.cloudsmith.io/v1/packages/{workspace}/{repo}/?query=version:{ntag}"
+ pkg_details = make_request(api_url, {"Cache-Control": "no-cache"})
+
+ parent_status = "Unknown"
+ index_digest = ""
+
+ if pkg_details and len(pkg_details) > 0:
+ parent_status = pkg_details[0].get('status_str', 'Unknown')
+ ver = pkg_details[0].get('version', '')
+ if ver and not ver.startswith('sha256:'):
+ index_digest = f"sha256:{ver}"
+ else:
+ index_digest = ver
+
+ status_display = format_status(parent_status)
+
+ rows = []
+ # Parent Row
+ rows.append([
+ f"[bold cyan]{ntag}[/bold cyan]",
+ "[magenta]manifest/list[/magenta]",
+ "multi",
+ status_display,
+ str(total_downloads),
+ f"[dim]{index_digest}[/dim]"
+ ])
+
+ # Children Rows
+ if detailed:
+ rows.extend(children_rows)
+ rows.append("SECTION")
+
+ return rows
+
+def fetch_untagged_data(pkg, workspace, repo, img, detailed=False):
+ digest = pkg.get('version')
+ if digest and not digest.startswith('sha256:'):
+ digest = f"sha256:{digest}"
+
+ status = pkg.get('status_str')
+ downloads = pkg.get('downloads', 0)
+ slug = pkg.get('slug')
+
+ # Fetch manifest to get platforms
+ manifest_url = f"{CLOUDSMITH_URL}/v2/{workspace}/{repo}/{img}/manifests/{digest}"
+ manifest_json = make_request(manifest_url, {"Accept": "application/vnd.oci.image.manifest.v1+json", "Cache-Control": "no-cache"})
+
+ child_digests = []
+ platform_str = "unknown"
+
+ if manifest_json:
+ archs = set()
+ if 'manifests' in manifest_json:
+ for m in manifest_json['manifests']:
+ p = m.get('platform', {})
+ os_name = p.get('os', 'linux')
+ arch = p.get('architecture', 'unknown')
+ plat = f"{os_name}/{arch}"
+ archs.add(plat)
+
+ if arch.lower() != 'unknown':
+ child_digests.append({'digest': m['digest'], 'platform': plat})
+ else:
+ archs.add("unknown")
+
+ platform_str = " ".join(sorted(list(archs)))
+
+ status_display = format_status(status)
+
+ rows = []
+ rows.append([
+ "(untagged)",
+ "manifest/list",
+ platform_str,
+ status_display,
+ str(downloads),
+ digest
+ ])
+
+ if detailed:
+ for child in child_digests:
+ row, _ = get_digest_data(workspace, repo, img, child['digest'], "(untagged)", platform=child['platform'])
+ rows.append(row)
+ rows.append("SECTION")
+
+ return rows, slug
+
+def get_untagged_images(workspace, repo, img, delete=False, detailed=False):
+ console.print("[bold]Searching for untagged manifest lists...[/bold]")
+ api_url = f"https://api.cloudsmith.io/v1/packages/{workspace}/{repo}/"
+ query = urlencode({'query': f"name:{img}"})
+ full_url = f"{api_url}?{query}"
+
+ packages = make_request(full_url, {"Cache-Control": "no-cache"})
+
+ untagged_pkgs = []
+ if packages:
+ for p in packages:
+ if p.get('type_display') == 'manifest/list':
+ tags = p.get('tags', {})
+ if not tags.get('version'):
+ untagged_pkgs.append(p)
+
+ if not untagged_pkgs:
+ console.print("[yellow]No untagged manifest lists found.[/yellow]")
+ return
+
+ # Create Table
+ table = Table(title="Untagged Manifest Lists", box=box.ROUNDED)
+ table.add_column("Tag", style="cyan")
+ table.add_column("Type", style="magenta")
+ table.add_column("Platform")
+ table.add_column("Status")
+ table.add_column("Downloads", justify="right")
+ table.add_column("Digest", style="dim")
+
+ packages_to_delete = []
+
+ with console.status("[bold green]Fetching untagged data...[/bold green]"):
+ with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
+ # Submit all tasks
+ futures = {executor.submit(fetch_untagged_data, pkg, workspace, repo, img, detailed): i for i, pkg in enumerate(untagged_pkgs)}
+
+ results = {}
+ for future in concurrent.futures.as_completed(futures):
+ index = futures[future]
+ try:
+ results[index] = future.result()
+ except Exception as e:
+ console.print(f"[red]Error processing untagged image: {e}[/red]")
+
+ # Add to table in original order
+ for i in range(len(untagged_pkgs)):
+ if i in results:
+ rows, slug = results[i]
+ packages_to_delete.append(slug)
+ for row in rows:
+ if row == "SECTION":
+ table.add_section()
+ else:
+ table.add_row(*row)
+
+ console.print(table)
+
+ if delete:
+ console.print("\n[bold red]Deleting untagged packages...[/bold red]")
+ for slug in packages_to_delete:
+ console.print(f" Deleting package: {slug}...", end=" ")
+ del_url = f"https://api.cloudsmith.io/v1/packages/{workspace}/{repo}/{slug}/"
+ req = urllib.request.Request(del_url, headers=AUTH_HEADER, method='DELETE')
+ try:
+ with urllib.request.urlopen(req):
+ console.print("[green]Deleted.[/green]")
+ except Exception as e:
+ console.print(f"[red]Failed: {e}[/red]")
+
+def main():
+ parser = argparse.ArgumentParser(description="Docker Multi-Arch Inspector")
+ parser.add_argument("org", help="Cloudsmith Organization/User")
+ parser.add_argument("repo", help="Cloudsmith Repository")
+ parser.add_argument("img", nargs="?", help="Image Name (Optional - if omitted, scans all images)")
+ parser.add_argument("--untagged", action="store_true", help="Find untagged manifest lists")
+ parser.add_argument("--untagged-delete", action="store_true", help="Delete untagged manifest lists")
+ parser.add_argument("--detailed", action="store_true", help="Show detailed breakdown of digests")
+
+ args = parser.parse_args()
+
+ images_to_scan = []
+
+ if args.img:
+ images_to_scan.append(args.img)
+ else:
+ console.print(f"[bold]Fetching catalog for {args.org}/{args.repo}...[/bold]")
+ catalog_url = f"{CLOUDSMITH_URL}/v2/{args.org}/{args.repo}/_catalog"
+ catalog_json = make_request(catalog_url, {"Accept": "application/json", "Cache-Control": "no-cache"})
+
+ if catalog_json and 'repositories' in catalog_json:
+ images_to_scan = catalog_json['repositories']
+ else:
+ console.print("[red]Failed to fetch catalog or no images found.[/red]")
+ sys.exit(1)
+
+ for img_name in images_to_scan:
+ console.print(f"\nDocker Image: [bold blue]{args.org}/{args.repo}/{img_name}[/bold blue]")
+
+ if args.untagged or args.untagged_delete:
+ get_untagged_images(args.org, args.repo, img_name, delete=args.untagged_delete, detailed=args.detailed)
+ else:
+ # Get Tags
+ tags_url = f"{CLOUDSMITH_URL}/v2/{args.org}/{args.repo}/{img_name}/tags/list"
+ tags_json = make_request(tags_url, {"Accept": "application/vnd.oci.image.manifest.v1+json", "Cache-Control": "no-cache"})
+
+ tags = []
+ if tags_json:
+ raw_tags = find_key_recursive(tags_json, 'tags')
+ flat_tags = []
+ for item in raw_tags:
+ if isinstance(item, list):
+ flat_tags.extend(item)
+ else:
+ flat_tags.append(item)
+
+ tags = sorted(list(set(flat_tags)))
+
+ if not tags:
+ console.print(f"[yellow]No tags found for {img_name}.[/yellow]")
+ continue
+
+ console.print(f"Found matching tags: [bold]{len(tags)}[/bold]")
+
+ # Create Main Table
+ table = Table(title=f"Image Analysis: {img_name}", box=box.ROUNDED)
+ table.add_column("Tag", style="cyan")
+ table.add_column("Type", style="magenta")
+ table.add_column("Platform")
+ table.add_column("Status")
+ table.add_column("Downloads", justify="right")
+ table.add_column("Digest", style="dim")
+
+ with console.status(f"[bold green]Fetching data for {img_name}...[/bold green]"):
+ with concurrent.futures.ThreadPoolExecutor(max_workers=10) as executor:
+ # Submit all tasks
+ future_to_tag = {executor.submit(fetch_tag_data, args.org, args.repo, img_name, t, args.detailed): t for t in tags}
+
+ results = {}
+ for future in concurrent.futures.as_completed(future_to_tag):
+ tag = future_to_tag[future]
+ try:
+ results[tag] = future.result()
+ except Exception as exc:
+ console.print(f"[red]Tag {tag} generated an exception: {exc}[/red]")
+
+ # Add to table in sorted order
+ for t in tags:
+ if t in results:
+ rows = results[t]
+ for row in rows:
+ if row == "SECTION":
+ table.add_section()
+ else:
+ table.add_row(*row)
+
+ # Print the final table
+ console.print(table)
+
+if __name__ == "__main__":
+ main()
\ No newline at end of file
diff --git a/README.md b/README.md
index eb6c7b9..c5fca33 100644
--- a/README.md
+++ b/README.md
@@ -1,66 +1,6 @@
-# π Cloudsmith CENG Template
+# π Cloudsmith Support Engineering
-A reusable template repository maintained by the **Customer Engineering (CENG)** team at Cloudsmith.
-This repo is intended to accelerate the development of examples, scripts, integrations, and demo workflows that help customers use Cloudsmith more effectively.
-
----
-
-## π¦ Whatβs Inside
-
-- GitHub Issue Forms for bugs and feature requests
-- CI/CD example workflow (Python-based)
-- Contribution and pull request templates
-- Environment variable and code linting examples
-- Directory structure for `src/` and `tests/`
-
----
-
-## π Structure
-
-```
-.
-βββ .github/ # GitHub-specific automation and templates
-β βββ ISSUE_TEMPLATE/ # Issue forms using GitHub Issue Forms
-β β βββ bug_report.yml # Form for reporting bugs
-β β βββ feature_request.yml # Form for suggesting features
-β βββ workflows/ # GitHub Actions workflows (e.g., CI pipelines)
-β βββ PULL_REQUEST_TEMPLATE.md # Template used when creating pull requests
-β βββ CODEOWNERS # Defines reviewers for specific paths
-βββ src/ # Scripts, API integrations, or example tools
-βββ tests/ # Tests for scripts and tools in src/
-βββ .env.example # Sample environment config (e.g., API keys)
-βββ .gitignore # Ignore rules for Git-tracked files
-βββ .editorconfig # Code style config to ensure consistency across IDEs
-βββ CHANGELOG.md # Log of project changes and version history
-βββ CONTRIBUTING.md # Guidelines and checklists for contributors
-βββ LICENSE # Licensing information (Apache 2.0)
-βββ README.md # This file
-```
-
----
-
-## π Getting Started
-
-1. Clone the template:
- ```bash
- git clone https://github.com/cloudsmith-examples/ceng-template.git
- cd ceng-template
- ```
-
-2. Install any dependencies or activate your environment.
-
-3. Start building your example in the `src/` directory.
-
-4. Use the `.env.example` as a guide for credentials if needed.
-
----
-
-## π§© Use Cases
-
-- Building and testing Cloudsmith integrations for CI/CD platforms
-- Creating reproducible customer issue examples
-- Building Cloudsmith CLI or API automations
-- Prototyping workflows for CI/CD platforms
+A collection of useful resources for assisting with various components of Cloudsmith.
---