iterate-ch/cyberduck
Cyberduck is a libre FTP, SFTP, WebDAV, Amazon S3, Backblaze B2, Microsoft Azure & OneDrive and OpenStack Swift file transfer client for Mac and Windows.
Mixed signals — read the receipts
weakest axiscopyleft license (GPL-3.0) — review compatibility
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit today
- ✓3 active contributors
- ✓GPL-3.0 licensed
Show all 8 evidence items →Show less
- ✓CI configured
- ✓Tests present
- ⚠Small team — 3 contributors active in recent commits
- ⚠Concentrated ownership — top contributor handles 62% of recent commits
- ⚠GPL-3.0 is copyleft — check downstream compatibility
What would change the summary?
- →Use as dependency Concerns → Mixed if: relicense under MIT/Apache-2.0 (rare for established libs)
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Forkable" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/iterate-ch/cyberduck)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/iterate-ch/cyberduck on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: iterate-ch/cyberduck
Generated by RepoPilot · 2026-05-09 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/iterate-ch/cyberduck shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
WAIT — Mixed signals — read the receipts
- Last commit today
- 3 active contributors
- GPL-3.0 licensed
- CI configured
- Tests present
- ⚠ Small team — 3 contributors active in recent commits
- ⚠ Concentrated ownership — top contributor handles 62% of recent commits
- ⚠ GPL-3.0 is copyleft — check downstream compatibility
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live iterate-ch/cyberduck
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/iterate-ch/cyberduck.
What it runs against: a local clone of iterate-ch/cyberduck — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in iterate-ch/cyberduck | Confirms the artifact applies here, not a fork |
| 2 | License is still GPL-3.0 | Catches relicense before you depend on it |
| 3 | Default branch master exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 30 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of iterate-ch/cyberduck. If you don't
# have one yet, run these first:
#
# git clone https://github.com/iterate-ch/cyberduck.git
# cd cyberduck
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of iterate-ch/cyberduck and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "iterate-ch/cyberduck(\\.git)?\\b" \\
&& ok "origin remote is iterate-ch/cyberduck" \\
|| miss "origin remote is not iterate-ch/cyberduck (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(GPL-3\\.0)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"GPL-3\\.0\"" package.json 2>/dev/null) \\
&& ok "license is GPL-3.0" \\
|| miss "license drift — was GPL-3.0 at generation time"
# 3. Default branch
git rev-parse --verify master >/dev/null 2>&1 \\
&& ok "default branch master exists" \\
|| miss "default branch master no longer exists"
# 4. Critical files exist
test -f "README.md" \\
&& ok "README.md" \\
|| miss "missing critical file: README.md"
test -f "pom.xml" \\
&& ok "pom.xml" \\
|| miss "missing critical file: pom.xml"
test -f "azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java" \\
&& ok "azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java" \\
|| miss "missing critical file: azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java"
test -f "azure/src/main/java/ch/cyberduck/core/azure/AzureProtocol.java" \\
&& ok "azure/src/main/java/ch/cyberduck/core/azure/AzureProtocol.java" \\
|| miss "missing critical file: azure/src/main/java/ch/cyberduck/core/azure/AzureProtocol.java"
test -f ".github/workflows/build.yml" \\
&& ok ".github/workflows/build.yml" \\
|| miss "missing critical file: .github/workflows/build.yml"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 30 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~0d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/iterate-ch/cyberduck"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
Cyberduck is a multi-protocol file transfer client supporting FTP, SFTP, WebDAV, Amazon S3, Backblaze B2, Microsoft Azure, OneDrive, and OpenStack Swift with native Mac and Windows GUI applications plus a cross-platform CLI (duck) for Linux, macOS, and Windows. It solves the problem of managing files across dozens of heterogeneous cloud storage and legacy protocols through a single unified interface. Multi-module Maven monorepo: core/ contains protocol-agnostic abstractions, azure/, s3/, swift/, etc. implement protocol-specific backends under ch/cyberduck/core/{protocol}/, CLI lives in duck/ module, native UI in separate Xcode/MSBuild projects (Cyberduck.xcodeproj, Cyberduck.sln). Build configuration centralized in pom.xml parent with shared properties in Directory.Build.props (C# side).
👥Who it's for
System administrators, DevOps engineers, and end users who need to manage files across multiple cloud providers (AWS S3, Azure Blob Storage, OneDrive) and legacy protocols (FTP, SFTP, WebDAV) without switching between specialized tools. Also used as a core library in Mountain Duck for cross-platform file system mounting.
🌱Maturity & risk
Production-ready and actively maintained. The codebase is substantial (22.8MB Java, 1.8MB C#) with CI/CD workflows visible (.github/workflows/build.yml, ci.yml, deploy.yml), multi-language localization support (20+ languages via Transifex), and a GPL v3 license indicating long-term community commitment. Last commit data suggests ongoing development.
Moderate complexity risk: the monorepo spans Java (primary), C#, Objective-C, and native code requiring familiarity with multiple toolchains (Maven, MSBuild, Xcode). The broad protocol coverage (8+ backends) means protocol-specific bugs can cascade; Azure module alone depends on azure-storage-blob 12.33.4 with transitive dependencies. Single maintainer risk is mitigated by iterate GmbH's commercial backing (Mountain Duck product).
Active areas of work
Version 9.5.0-SNAPSHOT in development (visible in pom.xml). GitHub Actions workflows indicate continuous integration on build.yml, CI testing, and automated Transifex localization sync. The codebase shows active protocol maintenance (Azure Storage Blob v12.33.4, S3 SDK updates likely). No specific breaking changes evident in snippet, but snapshot version suggests feature development in progress.
🚀Get running
git clone https://github.com/iterate-ch/cyberduck.git && cd cyberduck && mvn clean install -DskipTests. For Java module development: mvn -pl core clean install. For Windows C# build: msbuild Cyberduck.sln. For native macOS build: xcodebuild -project Cyberduck.xcodeproj.
Daily commands: Java CLI (duck): ./duck --help after mvn install or use binary release. GUI: Run compiled Cyberduck.app (macOS) or Cyberduck.exe (Windows) post-build. Development GUI: mvn -pl osx package (macOS) or msbuild /p:Configuration=Release (Windows). Maven enforces compilation via mvn clean compile.
🗺️Map of the codebase
README.md— Entry point documentation explaining Cyberduck as a multi-protocol file transfer client; essential for understanding project scope and supported protocols.pom.xml— Maven root POM defining build configuration, dependency management, and module organization across all protocol implementations.azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java— Core Azure protocol session implementation; demonstrates the Session abstraction pattern used across all protocol modules.azure/src/main/java/ch/cyberduck/core/azure/AzureProtocol.java— Protocol registration and configuration; shows how new cloud providers are integrated into Cyberduck's plugin architecture..github/workflows/build.yml— CI/CD pipeline definition; critical for understanding how multi-platform builds (Mac/Windows) and test execution are orchestrated.Cyberduck.xcodeproj/project.pbxproj— macOS native client Xcode project configuration; entry point for GUI development on Apple platforms.Cyberduck.sln— Windows .NET client Visual Studio solution; entry point for GUI development on Windows platform.
🛠️How to make changes
Add Support for a New Cloud Storage Protocol
- Create new Maven module following Azure's structure: e.g.,
newprovider/pom.xmlinheriting from parent (pom.xml) - Implement protocol-specific Session class extending base session:
newprovider/src/main/java/ch/cyberduck/core/newprovider/NewProviderSession.java(azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java) - Create Protocol registration class:
newprovider/src/main/java/ch/cyberduck/core/newprovider/NewProviderProtocol.java(azure/src/main/java/ch/cyberduck/core/azure/AzureProtocol.java) - Implement core feature classes for each operation (ReadFeature, WriteFeature, DeleteFeature, ListService, etc.) (
azure/src/main/java/ch/cyberduck/core/azure/AzureReadFeature.java) - Create ExceptionMappingService to translate provider-specific errors to Cyberduck exceptions (
azure/src/main/java/ch/cyberduck/core/azure/AzureExceptionMappingService.java) - Add protocol profile template:
newprovider/src/test/resources/NewProvider.cyberduckprofile(azure/src/test/resources/Azure (Shared Access Signature Token).cyberduckprofile) - Register new module in root pom.xml
<modules>section and add CI/CD workflow for build.yml (.github/workflows/build.yml)
Add a New File Operation Feature (e.g., Sync)
- Define feature interface in core module (shared across all protocols) (
azure/src/main/java/ch/cyberduck/core/azure/AzureReadFeature.java) - Implement feature for Azure:
azure/src/main/java/ch/cyberduck/core/azure/AzureSyncFeature.java(azure/src/main/java/ch/cyberduck/core/azure/AzureUploadFeature.java) - Implement same feature for other protocol modules (S3, B2, etc.) following the same pattern (
backblaze/src) - Create comprehensive unit tests:
azure/src/test/java/ch/cyberduck/core/azure/AzureSyncFeatureTest.java(azure/src/test/java/ch/cyberduck/core/azure/AbstractAzureTest.java) - Register feature in protocol's feature provider and wire into Session (
azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java)
Add Encryption Support for a Protocol
- Create cryptomator integration test class:
azure/src/test/java/ch/cyberduck/core/cryptomator/AzureEncryptedListServiceTest.java(azure/src/test/java/ch/cyberduck/core/cryptomator/AzureListServiceTest.java) - Implement Cryptomator-wrapped feature classes in protocol module (e.g., AzureEncryptedReadFeature wrapper) (
azure/src/main/java/ch/cyberduck/core/azure/AzureReadFeature.java) - Register encrypted feature variants in Session's feature provider based on vault configuration (
azure/src/main/java/ch/cyberduck/core/azure/AzureSession.java) - Add integration tests verifying read/write/list operations with encryption transparency (
azure/src/test/java/ch/cyberduck/core/cryptomator/CryptoAzureSingleTransferWorkerTest.java)
🔧Why these technologies
- Java (core backend) — Cross-platform protocol implementation; single code
🪤Traps & gotchas
Maven profiles likely needed: check .mvn/maven.config and .mvn/jvm.config for compiler/memory settings. C# builds require Visual Studio 2019+ or MSBuild 16.x. macOS builds require Xcode 12+. Protocol credentials (AWS, Azure, OneDrive OAuth) must be provided at runtime; tests likely mock these. Transifex integration in .github/workflows/transifex.yml implies CI may reject commits with untranslated strings. Azure module explicitly excludes azure-core-http-netty (pom.xml line ~27) to avoid dependency conflicts—do not re-add without understanding impact on netty version resolution across core/.
🏗️Architecture
💡Concepts to learn
- Virtual Filesystem Abstraction Layer — Cyberduck abstracts FTP, S3, Azure, WebDAV, etc. behind common Path/Attributes/Feature interfaces in core/; understanding this polymorphism is essential for adding new protocols
- OAuth 2.0 / OpenID Connect — OneDrive, Azure, and some cloud backends use OAuth for authentication; Cyberduck handles token refresh and credential storage across protocols
- Protocol Polymorphism via Feature Classes — Features like AzureAclPermissionFeature, AzureAttributesFinderFeature implement optional protocol capabilities; this pattern allows graceful degradation when a backend doesn't support ACLs or metadata
- Object Versioning (S3, Azure Blob) — Multiple backends support object version management; Cyberduck models version listings and rollback separately from simple file lists
- Async/Callback-driven I/O — GUI threads cannot block on network operations; Cyberduck uses Java callbacks and thread pools to manage concurrent transfers without freezing UI
- Localization via Transifex — 20+ language support is managed through CI/CD integration with Transifex; translations are synced automatically in build pipeline
- Multi-tenant Cloud Identity (SAS Tokens, Service Principals) — Azure backend supports multiple authentication methods (connection strings, managed identity, SAS tokens); Cyberduck abstracts these into a unified credential model
🔗Related repos
iterate-ch/docs— Official documentation repository maintaining user guides, CLI help, and protocol-specific setup instructions referenced from main READMEiterate-ch/profiles— Connection profile repository containing pre-configured settings for additional cloud providers and protocols available via Preferences → Profilesaws/aws-sdk-java-v2— AWS SDK dependency for S3 backend protocol implementation and credential handlingAzure/azure-sdk-for-java— Azure Storage SDK (v12.33.4+) providing blob, queue, and file share operations for Microsoft Azure backendmountainduck/mountainduck— Commercial companion product using Cyberduck's core libraries for cross-platform file system mounting (mentioned in README as primary enterprise use case)
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive unit tests for Azure storage protocol implementation
The Azure module (azure/src/main/java/ch/cyberduck/core/azure/) has numerous feature classes (AzureReadFeature, AzureWriteFeature, AzureDeleteFeature, etc.) but no visible test files in the provided structure. Given the critical nature of cloud storage operations, this module needs robust test coverage. New contributors can add unit tests for individual Azure feature classes to catch regressions early.
- [ ] Create azure/src/test/java/ch/cyberduck/core/azure/ directory structure
- [ ] Add unit tests for AzureReadFeature.java covering success/failure scenarios
- [ ] Add unit tests for AzureWriteFeature.java and AzureUploadFeature.java
- [ ] Add integration tests for AzureSession.java connection handling
- [ ] Add tests for AzureExceptionMappingService.java to verify proper error translation
Add explicit GitHub Actions workflow for Azure module CI/CD
The repo has workflows for build.yml, ci.yml, and deploy.yml, but there's no specific workflow for testing the Azure module against real Azure storage accounts (using secrets). This would help catch Azure SDK compatibility issues and credential handling bugs before release. A new contributor can create a dedicated Azure test workflow.
- [ ] Create .github/workflows/azure-integration.yml workflow file
- [ ] Configure Azure storage account credentials as GitHub secrets (AZURE_STORAGE_ACCOUNT, AZURE_STORAGE_KEY)
- [ ] Add workflow steps to run azure/pom.xml tests in isolation
- [ ] Include matrix testing for different azure-storage-blob versions (currently 12.33.4)
- [ ] Add workflow dispatch trigger for manual testing and scheduled nightly runs
Refactor Apache HTTP client implementation with proper abstraction layer
The azure/src/main/java/ch/cyberduck/core/azure/apache/ directory contains ApacheHttpClient.java and ApacheHttpResponse.java as Azure-specific HTTP implementations. However, other protocol modules likely have similar HTTP client code. A new contributor should extract these into a reusable HTTP abstraction in the core module to reduce duplication across FTP, S3, WebDAV, and Azure implementations.
- [ ] Audit http/client implementations in other protocol modules (s3/, swift/, etc.)
- [ ] Create core/src/main/java/ch/cyberduck/core/http/ abstraction layer
- [ ] Move ApacheHttpClient.java and ApacheHttpResponse.java to new abstraction
- [ ] Update azure/pom.xml to reference core HTTP module instead of local implementation
- [ ] Add integration tests for the new shared HTTP abstraction in core/src/test/java/
🌿Good first issues
- Add missing unit tests for AzureContainerListService.java in azure/src/test/java/ch/cyberduck/core/azure/—protocol feature implementations lack comprehensive edge-case coverage (null handling, pagination, error states)
- Document protocol-specific configuration options in README or CONFIGURATION.md—currently no central guide explaining how to configure S3 regions, Azure container auth, or SFTP key paths for new developers
- Implement missing WebDAV PROPFIND error handling tests in webdav/src/test/—visible pattern in azure/ and s3/ test suites but webdav module appears under-tested for malformed XML responses
⭐Top contributors
Click to expand
Top contributors
- @dkocher — 62 commits
- @dependabot[bot] — 32 commits
- @ylangisc — 6 commits
📝Recent commits
Click to expand
Recent commits
f5cccaf— Merge pull request #18091 from iterate-ch/bugfix/GH-18090 (dkocher)6cd8f0f— Merge pull request #18092 from iterate-ch/dependabot/maven/log4j-version-2.26.0 (dkocher)607b300— Bump log4j-version from 2.25.4 to 2.26.0 (dependabot[bot])550a45b— Save default connection profile with:to seperate vendor string. (dkocher)6e9c9ff— Merge pull request #18086 from iterate-ch/dependabot/maven/com.azure-azure-storage-blob-12.33.4 (dkocher)616d6f5— Merge pull request #18055 from iterate-ch/dependabot/maven/org.codehaus.mojo-extra-enforcer-rules-1.12.0 (dkocher)482c785— Bump com.azure:azure-storage-blob from 12.33.3 to 12.33.4 (dependabot[bot])68341ec— Merge pull request #18046 from iterate-ch/bugfix/GH-18045 (dkocher)53ac0f2— Merge pull request #18056 from iterate-ch/dependabot/maven/org.apache.maven.plugins-maven-dependency-plugin-3.10.0 (dkocher)faf729f— Merge pull request #18084 from iterate-ch/dependabot/maven/org.apache.maven.plugins-maven-shade-plugin-3.6.2 (dkocher)
🔒Security observations
Cyberduck demonstrates a reasonable security posture with an active vulnerability reporting process and dependency management via Dependabot. Key strengths include GPL licensing transparency, documented security policy, and use of relatively recent dependencies. Areas for improvement include updating the Docker base image to a newer LTS version, documenting the rationale behind dependency exclusions, implementing code signing for releases, and enhancing security documentation with cryptographic practices and dependency audit procedures. As a credential-handling file
- Medium · Azure Storage SDK Dependency Version —
azure/pom.xml - azure-storage-version property. The project uses azure-storage-blob version 12.33.4. While this is a relatively recent version, it's important to verify that this version doesn't have known CVEs. The use of snapshot versions (9.5.0-SNAPSHOT) in the parent POM suggests active development, but dependency versions should be regularly audited. Fix: Regularly check for security advisories for azure-storage-blob using tools like OWASP Dependency-Check or Snyk. Enable Dependabot alerts on GitHub (already present in .github/dependabot.yml) and promptly update to patched versions. - Medium · Exclusion of azure-core-http-netty Transport —
azure/pom.xml - exclusion section. The azure-storage-blob dependency explicitly excludes azure-core-http-netty. This could indicate a deliberate choice to use an alternative HTTP client, but the reasoning should be documented. If this is due to a security issue in netty, the alternative client (presumably OkHttp or another) must also be regularly maintained. Fix: Document why netty is excluded in a code comment. Ensure the alternative HTTP client being used is actively maintained and regularly patched. Verify the explicit HTTP client dependency is included in the POM. - Low · Docker Base Image Update Policy —
Dockerfile. The Dockerfile uses 'ubuntu:focal' which is an older Ubuntu LTS release (20.04, EOL April 2025). While currently supported, this should be upgraded to a more recent LTS version (jammy - 22.04) to receive security patches longer. Fix: Update the base image to 'ubuntu:jammy' or the latest LTS version. Implement automated scanning of the Docker image for vulnerabilities using tools like Trivy or Grype in the CI/CD pipeline. - Low · Missing SECURITY.md Implementation Details —
SECURITY.md and root directory. While SECURITY.md exists and defines a vulnerability reporting process, there's no evidence of a security.txt file (RFC 9110) or additional security documentation about code review processes, dependency audit procedures, or cryptographic practices. Fix: Add a .well-known/security.txt file with contact information. Enhance SECURITY.md with details about code review practices, dependency management, and security testing procedures used in the project. - Low · Test Dependency in Production Scope —
azure/pom.xml - test dependency. The pom.xml includes a 'test' artifact as a dependency with 'test' scope, which is appropriate. However, ensure that no test code or test-only classes are accidentally included in production builds. Fix: Verify build configuration to ensure test artifacts are never included in production releases. Use Maven assembly plugin or similar tools to validate artifact composition in CI/CD. - Low · No Visible Code Signing Configuration —
Build and deployment files (not visible in detail). The repository structure doesn't show obvious code signing or verification mechanisms in the provided files. For a file transfer application that handles credentials and sensitive data, code signing and integrity verification are important. Fix: Implement GPG/code signing for releases. Document the public key for signature verification. Consider implementing binary transparency and SBoM (Software Bill of Materials) generation in the build pipeline. - Low · Limited Visibility into Credential Handling —
azure/src/main/java/ch/cyberduck/core/azure/ - Azure credential handling. As a file transfer client, Cyberduck handles credentials for multiple cloud providers and protocols. While no hardcoded secrets were found in the provided structure, the Azure module implementation details are not fully visible for credential storage validation. Fix: Ensure credentials are never logged. Use secure credential storage mechanisms (credential managers, keychains). Implement credential masking in logs. Document credential handling practices in security documentation.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.