Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion .github/pull_request_template.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,9 @@ harness output: the summary lines and any failures, not the whole log

## UI changes

Before and after screenshots, light and dark, on every affected platform. UI uses `design/` tokens, SF Symbols, and the system font only.
Before and after screenshots, light and dark, on every affected platform.

- [ ] Tokens, SF Symbols and the system font only
- [ ] Both themes checked
- [ ] `scripts/verify-contrast.sh` and `scripts/verify-design.sh` pass
- [ ] Screenshots recaptured if the UI changed (`scripts/capture-screenshots.sh`)
6 changes: 4 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ jobs:
out swift '^(app|CrocKit)/|^\.swift-format$|^\.xcode-version$|^scripts/format-swift\.sh$|^\.github/workflows/(ci|reusable-swift-format)\.yml$'
out go '^crocmobile/|^\.github/workflows/(ci|reusable-go)\.yml$'
out build '^(app|CrocKit|crocmobile)/|^scripts/build-xcframework\.sh$|^\.xcode-version$|^\.github/workflows/ci\.yml$'
out design '^design/|^scripts/(lib|verify-contrast)\.sh$|^\.github/workflows/ci\.yml$'
out design '^design/|^app/.*\.swift$|^app/CrocApp/Assets\.xcassets/|^web/landing/.*\.(css|html)$|^web/docs/src/css/|^scripts/(lib|verify-contrast|verify-design)\.sh$|^\.github/workflows/ci\.yml$'
out interop '^(crocmobile|CrocKit)/|^scripts/(lib|verify-interop)\.sh$|^scripts/croc-v10\.version$|^\.github/workflows/ci\.yml$'
} | tee -a "$GITHUB_OUTPUT"

Expand All @@ -83,7 +83,7 @@ jobs:
uses: ./.github/workflows/reusable-go.yml

contrast:
name: contrast
name: design checks

needs: changes

Expand All @@ -100,6 +100,8 @@ jobs:

- run: scripts/verify-contrast.sh

- run: scripts/verify-design.sh

# The interop harness against a relay on localhost, never the public relays:
# those rate-limit a shared runner address and make the run flaky. The
# public-pool scenario stays a local run (docs/BUILDING.md).
Expand Down
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ build/
/_site/
/dist/

# Copied from design/tokens.css at build time
# Copied from design/ and web/landing/ at build time
web/landing/tokens.css
web/docs/src/css/tokens.css
web/docs/static/img/mascot.webp

# Local tooling
*.log
Expand Down
25 changes: 25 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,31 @@

Native SwiftUI GUI for the croc file-transfer CLI.

## Design

Anything a user sees (app views, the landing page, the docs site, release artwork, store copy, UI strings) follows `design/`. Start at `design/AGENTS.md`. Run `scripts/verify-contrast.sh` and `scripts/verify-design.sh` after touching any of it; CI runs both.

## Skills

Load these before the matching work, every time:

| Work | Skills |
| --- | --- |
| Anything design-related, on any surface: `design/`, views, stylesheets, artwork, UI copy | `apple-design` |
| SwiftUI views, app UI, Liquid Glass, animation | `swiftui-expert-skill`, `mobile-ios-design` |
| App Store submission, listing copy, review notes, entitlements, privacy | `apple-appstore-reviewer` |

If one is missing, install it (user-level, all from [skills.sh](https://skills.sh) sources) before starting, then reload skills:

```bash
npx skills add emilkowalski/skills --skill apple-design -g -y
npx skills add avdlee/swiftui-agent-skill --skill swiftui-expert-skill -g -y
npx skills add wshobson/agents --skill mobile-ios-design -g -y
npx skills add github/awesome-copilot --skill apple-appstore-reviewer -g -y
```

Check what is installed with `npx skills ls -g`. When a skill's advice conflicts with this repo (`design/`, a directory's `AGENTS.md`), the repo wins.

## Editing AGENTS.md files

Every `AGENTS.md` in this repo (root or in sub-dirs) is written and updated through the `claude-md-management:claude-md-improver` skill, or the closest equivalent your agent has. Run it on the file you change: audit it against the real state of its directory, then apply targeted edits. Keep each file short, current and specific to its directory. Don't restate what the code or another doc already says.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,14 @@ extra sections where a release needs them, and the project follows

## [Unreleased]

### Changed

- Buttons are easier to read in light mode: text labels now use the darker green, and destructive labels are no longer drawn in red text.
- The screen that asks you to accept a transfer shows a Receiving header, the encryption badge and the file list as rows. Its Cancel button is gone: Decline answers the other device, leaving the screen gives no answer, and Home shows a banner to return to a request that is still waiting.
- Send as Link now says Sending and Receiving like every other transfer, and copying the code shows "Copied".
- On iPhone, a light haptic marks a finished, failed or incoming transfer and a copied or scanned code. Cancelling or declining yourself stays silent.
- Settings labels use title case, and "Auto-accept incoming files" is now "Auto-Accept Transfers".

## [1.0.0] - 2026-10-15

CrocApp 1.0 is on three channels: the iOS and iPadOS App Store, the Mac App Store, and a notarized disk image for Mac. The App Store listings are linked from crocapp.dev. The other device needs croc 11 or newer.
Expand Down
9 changes: 9 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,15 @@ govulncheck ./...

Anything visual, in the app, the web or elsewhere, follows [`design/AGENTS.md`](design/AGENTS.md). In short, fixed design principles (brandbook), like: design tokens instead of raw hex, px, pt, or durations; SF Symbols only; system font only; a light and a dark value for every surface.

Two scripts enforce it, and CI runs both on any change to `design/`, app Swift or color sets, or web CSS. Run them yourself after touching a value:

```bash
scripts/verify-contrast.sh # every contrast ratio in design/colors.md, recomputed from tokens.css
scripts/verify-design.sh # tokens.css = DesignTokens.swift = color sets, and no hex, px or raw system colors in app or web code
```

A failure means your change or `design/` is wrong. Fix one of them, never the check.

UI pull requests need **before and after screenshots in both light and dark**, and on both platforms if both are affected.

## AI-assisted contributions
Expand Down
34 changes: 17 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@

<p align="center">
<a href="https://github.com/bakirgdev/CrocApp/actions/workflows/ci.yml"><img src="https://github.com/bakirgdev/CrocApp/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
<a href="https://github.com/bakirgdev/CrocApp/releases/latest"><img src="https://img.shields.io/github/v/release/bakirgdev/CrocApp" alt="Latest release"></a>
<img src="https://img.shields.io/badge/platform-iOS%2026%20%7C%20iPadOS%2026%20%7C%20macOS%2026-blue" alt="Platforms">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-green" alt="MIT License"></a>
<a href="https://github.com/bakirgdev/CrocApp/releases/latest"><img src="https://img.shields.io/github/v/release/bakirgdev/CrocApp?color=555" alt="Latest release"></a>
<img src="https://img.shields.io/badge/platform-iOS%2026%20%7C%20iPadOS%2026%20%7C%20macOS%2026-555" alt="Platforms">
<a href="LICENSE"><img src="https://img.shields.io/badge/license-MIT-1E9E6A" alt="MIT License"></a>
<a href="https://crocapp.dev"><img src="https://img.shields.io/badge/site-crocapp.dev-1E9E6A" alt="Website"></a>
</p>

## What it is

CrocApp sends files, folders, and text between two devices anywhere in the world, encrypted end to end, using a short code phrase like `apple-house-car`. No account, no cloud upload, no shared network needed.
CrocApp sends files, folders, and text between two devices anywhere in the world, end-to-end encrypted, using a short code phrase like `apple-house-car`. No account and no shared network needed.

It is a graphical front end for [croc](https://github.com/schollz/croc), the command-line file-transfer tool by [Zack Scholl](https://github.com/schollz). CrocApp embeds croc's Go library rather than shelling out to the binary, so **a code phrase from the croc CLI works in the app, and the reverse**.

Expand All @@ -38,7 +38,7 @@ The disk image is Developer ID signed, notarized, and updates itself through Spa
```mermaid
flowchart LR
S["Sender<br/>CrocApp or croc CLI"]
R["Receiver<br/>CrocApp or croc CLI"]
R["Other device<br/>CrocApp or croc CLI"]
L(["Direct path<br/>same network"])
X(["Relay<br/>ciphertext only"])

Expand All @@ -51,9 +51,9 @@ flowchart LR

1. The sender picks files, a folder, or text.
2. CrocApp shows a code phrase. Say it, message it, or show it as a QR code.
3. The receiver enters the phrase, previews the file list, and accepts.
3. The other device enters the phrase, previews the file list, and accepts.

Both sides run PAKE over the code phrase to derive a session key, so the phrase never crosses the network in the clear and the relay never learns the key. CrocApp tries the local network and the relay at once; on the same network the transfer goes direct.
Both devices run PAKE over the code phrase to derive a session key, so the phrase never crosses the network in the clear and the relay never learns the key. CrocApp tries the local network and the relay at once; on the same network the transfer goes direct.

## Screenshots

Expand Down Expand Up @@ -87,12 +87,12 @@ Both sides run PAKE over the code phrase to derive a session key, so the phrase

## Security and privacy

Transfers are end-to-end encrypted, the code phrase authenticates both sides, and the relay only ever sees ciphertext.
Transfers are end-to-end encrypted, the code phrase authenticates both devices (PAKE), and the relay only ever sees ciphertext.

> [!WARNING]
> Neither croc nor CrocApp has had a formal third-party security audit.

- No telemetry, analytics, ads, or accounts. The [privacy policy](https://crocapp.dev/privacy/) lists every server the app can contact.
- No accounts, analytics, ads, or tracking. The [privacy policy](https://crocapp.dev/privacy/) lists every server the app can contact.
- Transfer history stays on the device.
- You can use your own croc relay instead of the default public ones.
- Report vulnerabilities privately through [GitHub Security Advisories](https://github.com/bakirgdev/CrocApp/security/advisories/new), never in a public issue. See [`SECURITY.md`](SECURITY.md).
Expand All @@ -112,9 +112,9 @@ Transfers are end-to-end encrypted, the code phrase authenticates both sides, an
| Show QR on send, scan QR on receive | `--qrcode` |
| Choose output folder; Files-visible by default on iOS | `--out` |
| Keep Both or Replace when a file already exists; resume with Replace | `--rename`, `--overwrite` |
| Preview the incoming file list, then accept or decline | interactive prompt |
| Preview the file list, then accept or decline | interactive prompt |
| Live progress, speed, cancel; Live Activity on iOS | |
| LAN and relay raced automatically | croc default |
| Local network and relay raced automatically | croc default |
| Local transfer history | |

</details>
Expand All @@ -129,7 +129,7 @@ Transfers are end-to-end encrypted, the code phrase authenticates both sides, an
| Disable compression | `--no-compress` |
| Zip a folder before sending | `--zip` |
| Exclude patterns, respect `.gitignore` | `--exclude --git` |
| Auto-accept incoming, off by default | `--yes` |
| Auto-accept transfers, off by default | `--yes` |
| Require confirmation on both sides | `--ask` |
| Connection: Automatic or Relay only | `--transport auto\|relay` |

Expand All @@ -142,7 +142,7 @@ Transfers are end-to-end encrypted, the code phrase authenticates both sides, an
|---|---|
| SOCKS5 proxy | `--socks5` |
| HTTP proxy | `--connect` |
| Upload speed limit | `--throttleUpload` |
| Send speed limit | `--throttleUpload` |
| Encryption curve | `--curve` |
| File hash algorithm | `--hash` |
| Sender IP, direct connect | `--ip` |
Expand All @@ -161,9 +161,9 @@ Transfers are end-to-end encrypted, the code phrase authenticates both sides, an
| Menu bar quick send and Open at login (macOS) |
| Receive links: `crocapp://`, `crocapp.dev/r/` and `getcroc.com/?code=` open Receive with the code filled in |
| Shortcuts and Siri actions: Send Files, Send Text, Receive |
| Trust UI: end-to-end badge, "how it works", active-relay indicator |
| Trust UI: end-to-end badge, **How It Works**, active-relay indicator |
| Share Link and a QR code that opens CrocApp or a page that explains how to receive |
| Send as link: encrypted upload for a receiver who is not online, with expiry and revoke |
| Send as Link: files encrypted on your device, for someone who is not online, with expiry and revoke |
| iPad File menu: Show Receive Folder in Files |

</details>
Expand Down Expand Up @@ -201,7 +201,7 @@ Free and MIT-licensed, and it stays that way. Donations are welcome but optional
<details>
<summary><strong>Will there be a Windows, Linux, or Android version?</strong></summary>

Not plannet, yet. If you really want to se CrocApp be born on other platforms, you can show your interest via [issues](https://github.com/bakirgdev/CrocApp/issues)
Not planned yet. If you want to see CrocApp on other platforms, show your interest in an [issue](https://github.com/bakirgdev/CrocApp/issues).

</details>

Expand All @@ -221,4 +221,4 @@ Starring the repo, reporting bugs, and telling others about CrocApp help just as
## Credits and license

- [croc](https://github.com/schollz/croc) by [Zack Scholl](https://github.com/schollz), the transfer engine that makes this possible. MIT.
- CrocApp by [Bakir Gracic](https://github.com/bakirgdev). [MIT](LICENSE).
- CrocApp by [Bakir Gracić](https://github.com/bakirgdev). [MIT](LICENSE).
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,9 @@ Steps to check a release (notarization, build attestation, checksums, update sig

## What CrocApp claims

Transfers are end-to-end encrypted, the code phrase authenticates both sides, and the relay only ever sees ciphertext. That is the whole claim.
Transfers are end-to-end encrypted, the code phrase authenticates both devices (PAKE), and the relay only ever sees ciphertext. CrocApp makes no stronger claim.

> [!WARNING]
> There has been **no formal third-party security audit** of croc, and CrocApp does not claim one. Do not describe CrocApp as audited, certified, or zero-knowledge-verified.

Supporting facts (no telemetry, no accounts, local history, your own relay, dependency scanning) are on the [security and privacy page](https://crocapp.dev/docs/security-and-privacy/).
Supporting facts (no accounts, analytics, ads or tracking, history that stays on the device, your own relay, dependency scanning) are on the [security and privacy page](https://crocapp.dev/docs/security-and-privacy/).
8 changes: 4 additions & 4 deletions app/CrocApp.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,7 @@
"INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace[sdk=macosx*]" = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan QR transfer codes.";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan the QR code for a code phrase.";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "CrocApp uses the local network to discover nearby devices for direct, faster transfers.";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
Expand Down Expand Up @@ -614,7 +614,7 @@
"INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace[sdk=iphonesimulator*]" = YES;
"INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace[sdk=macosx*]" = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan QR transfer codes.";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan the QR code for a code phrase.";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "CrocApp uses the local network to discover nearby devices for direct, faster transfers.";
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphoneos*]" = YES;
"INFOPLIST_KEY_UIApplicationSceneManifest_Generation[sdk=iphonesimulator*]" = YES;
Expand Down Expand Up @@ -718,7 +718,7 @@
INFOPLIST_FILE = "Config/CrocApp-Direct-Info.plist";
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan QR transfer codes.";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan the QR code for a code phrase.";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "CrocApp uses the local network to discover nearby devices for direct, faster transfers.";
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 26.0;
Expand Down Expand Up @@ -756,7 +756,7 @@
INFOPLIST_FILE = "Config/CrocApp-Direct-Info.plist";
INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES;
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.utilities";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan QR transfer codes.";
INFOPLIST_KEY_NSCameraUsageDescription = "CrocApp uses the camera to scan the QR code for a code phrase.";
INFOPLIST_KEY_NSLocalNetworkUsageDescription = "CrocApp uses the local network to discover nearby devices for direct, faster transfers.";
LD_RUNPATH_SEARCH_PATHS = "@executable_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 26.0;
Expand Down
38 changes: 38 additions & 0 deletions app/CrocApp/Assets.xcassets/ColorAccentTint.colorset/Contents.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.120",
"blue" : "0.416",
"green" : "0.620",
"red" : "0.118"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "0.160",
"blue" : "0.522",
"green" : "0.773",
"red" : "0.176"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Loading