RepoPilotOpen in app →

schollz/croc

Easily and securely send things from one computer to another :crocodile: :package:

Healthy

Healthy across all four use cases

Use as dependencyHealthy

Permissive license, no critical CVEs, actively maintained — safe to depend on.

Fork & modifyHealthy

Has a license, tests, and CI — clean foundation to fork and modify.

Learn fromHealthy

Documented and popular — useful reference codebase to read through.

Deploy as-isHealthy

No critical CVEs, sane security posture — runnable as-is.

  • Last commit 3d ago
  • 23+ active contributors
  • MIT licensed
Show 3 more →
  • CI configured
  • Concentrated ownership — top contributor handles 59% of recent commits
  • No test directory detected

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 "Healthy" badge

Paste into your README — live-updates from the latest cached analysis.

Variant:
RepoPilot: Healthy
[![RepoPilot: Healthy](https://repopilot.app/api/badge/schollz/croc)](https://repopilot.app/r/schollz/croc)

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/schollz/croc on X, Slack, or LinkedIn.

Onboarding doc

Onboarding: schollz/croc

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:

  1. 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.
  2. 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.
  3. Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/schollz/croc 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

GO — Healthy across all four use cases

  • Last commit 3d ago
  • 23+ active contributors
  • MIT licensed
  • CI configured
  • ⚠ Concentrated ownership — top contributor handles 59% of recent commits
  • ⚠ No test directory detected

<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 schollz/croc repo on your machine still matches what RepoPilot saw. If any fail, the artifact is stale — regenerate it at repopilot.app/r/schollz/croc.

What it runs against: a local clone of schollz/croc — 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 schollz/croc | Confirms the artifact applies here, not a fork | | 2 | License is still MIT | Catches relicense before you depend on it | | 3 | Default branch main exists | Catches branch renames | | 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code | | 5 | Last commit ≤ 33 days ago | Catches sudden abandonment since generation |

<details> <summary><b>Run all checks</b> — paste this script from inside your clone of <code>schollz/croc</code></summary>
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of schollz/croc. If you don't
# have one yet, run these first:
#
#   git clone https://github.com/schollz/croc.git
#   cd croc
#
# 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 schollz/croc and re-run."
  exit 2
fi

# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "schollz/croc(\\.git)?\\b" \\
  && ok "origin remote is schollz/croc" \\
  || miss "origin remote is not schollz/croc (artifact may be from a fork)"

# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
   || grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
  && ok "license is MIT" \\
  || miss "license drift — was MIT at generation time"

# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
  && ok "default branch main exists" \\
  || miss "default branch main no longer exists"

# 4. Critical files exist
test -f "main.go" \\
  && ok "main.go" \\
  || miss "missing critical file: main.go"
test -f "src/croc/croc.go" \\
  && ok "src/croc/croc.go" \\
  || miss "missing critical file: src/croc/croc.go"
test -f "src/tcp/tcp.go" \\
  && ok "src/tcp/tcp.go" \\
  || miss "missing critical file: src/tcp/tcp.go"
test -f "src/crypt/crypt.go" \\
  && ok "src/crypt/crypt.go" \\
  || miss "missing critical file: src/crypt/crypt.go"
test -f "src/cli/cli.go" \\
  && ok "src/cli/cli.go" \\
  || miss "missing critical file: src/cli/cli.go"

# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 33 ]; then
  ok "last commit was $days_since_last days ago (artifact saw ~3d)"
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/schollz/croc"
  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).

</details>

TL;DR

croc is a CLI tool for peer-to-peer file transfer between two computers with end-to-end encryption via PAKE (Password-Authenticated Key Exchange), relay-based connection bridging, and automatic cross-platform support (Windows/Linux/macOS). It solves the problem of securely transferring files without requiring port-forwarding, local servers, or prior network configuration—just run croc send file on one computer and croc receive on another using a shared passphrase. Modular monolith structure: src/croc/ contains core transfer logic, src/crypt/ handles PAKE encryption, src/comm/ manages network communication, src/cli/ wraps the CLI interface, with supporting modules for compression, messaging, mnemonic code generation, and disk usage detection. main.go is the entry point; relay functionality is built into the core (src/croc/croc.go handles both sender and receiver roles).

👥Who it's for

System administrators, DevOps engineers, and privacy-conscious users who need to transfer files between machines without setting up infrastructure; also developers building tools that need secure inter-machine communication. Users behind NATs or firewalls who cannot expose ports benefit especially from the relay-based architecture.

🌱Maturity & risk

Production-ready and actively maintained. The codebase is substantial (~280KB Go code), includes a CI/CD pipeline (.github/workflows/ci.yml, release.yml), comprehensive test coverage across core modules (src/croc/croc_test.go, src/crypt/crypt_test.go, etc.), and supports multiple package managers (Homebrew, Scoop, pacman, dnf). The project has reach (Arch, Fedora, NixOS packages) indicating stable, long-term community adoption.

Low risk for a mature project, but worth noting: single maintainer (schollz) creates community dependency risk; dependency surface is reasonable (~20 direct dependencies from go.mod) with well-maintained libraries (golang.org/x/crypto, schollz/pake/v3 for encryption). The relay architecture means availability depends on accessible relay servers—users should understand relay security implications. No obvious breaking changes visible in the structure, but v10 module path suggests past major versions.

Active areas of work

Actively maintained with recent commits visible. The project has automated releases via GitHub Actions (.github/workflows/release.yml), dependency updates via Dependabot (.github/dependabot.yml), and CI validation. The structure supports IPv6-first with IPv4 fallback and proxy support (Tor), indicating ongoing improvements to network resilience.

🚀Get running

git clone https://github.com/schollz/croc.git
cd croc
go build -o croc main.go
./croc send path/to/file  # On sender
./croc --relay example.com:9009 receive  # On receiver

Daily commands:

# Build
go build -o croc main.go

# Run as sender
./croc send myfile.txt

# Run as receiver with custom relay
./croc --relay relay.example.com:9009 receive

# Run relay server (standalone)
./croc relay

🗺️Map of the codebase

  • main.go — Entry point for the CLI application; every contributor must understand the command initialization flow here.
  • src/croc/croc.go — Core croc send/receive logic and the primary abstraction for file transfer; this is the heart of the application.
  • src/tcp/tcp.go — Implements relay server and TCP communication; critical for understanding how data flows between peers.
  • src/crypt/crypt.go — Handles end-to-end encryption using PAKE (Password-Authenticated Key Exchange); security-critical.
  • src/cli/cli.go — CLI argument parsing and user-facing interface; directly shapes how users interact with croc.
  • src/comm/comm.go — Message serialization and communication protocol; enables sender/receiver coordination.
  • src/models/constants.go — Protocol constants and configuration defaults; affects all cross-platform communication.

🧩Components & responsibilities

  • CLI (src/cli/cli.go) (schollz/cli/v2, schollz/progressbar/v3) — Parses arguments, validates input, initiates send/receive workflows, manages user output and progress bars.
    • Failure mode: Invalid arguments or missing required flags; graceful error message to user.
  • Croc Core (src/croc/croc.go) (schollz/pake/v3,) — Orchestrates file selection, encryption key derivation, relay connection, and transfer logic for both send and receive.

🛠️How to make changes

Add a new CLI command

  1. Define the command structure in src/cli/cli.go using schollz/cli/v2 syntax (src/cli/cli.go)
  2. Implement the command handler function, reusing Croc struct initialization patterns (src/cli/cli.go)
  3. Register the command in the App.Commands slice (src/cli/cli.go)
  4. Add tests following the pattern in src/croc/croc_test.go (src/croc/croc_test.go)

Add a new message type for protocol communication

  1. Define the message constant in src/models/constants.go (e.g., MessageType* constants) (src/models/constants.go)
  2. Add the message struct to src/message/message.go (src/message/message.go)
  3. Add marshaling/unmarshaling logic in src/comm/comm.go SendMessage and ReadMessage (src/comm/comm.go)
  4. Handle the new message type in src/croc/croc.go send or receive workflow (src/croc/croc.go)

Add cross-platform support for a system utility

  1. Create a Windows-specific implementation file (e.g., src/diskusage/diskusage_windows.go following the pattern) (src/diskusage/diskusage_windows.go)
  2. Implement the function with build tags (//go:build windows) (src/diskusage/diskusage_windows.go)
  3. Add Unix/Linux equivalent in the main file with build tags (//go:build !windows) (src/diskusage/diskusage.go)
  4. Test with src/*_test.go files verifying both platforms (src/diskusage/diskusage_test.go)

🔧Why these technologies

  • Go 1.25.0 — Cross-platform compilation to single binaries; minimal runtime dependencies enable easy distribution and relay deployment.
  • PAKE (schollz/pake/v3) — Enables symmetric key derivation from a shared pass-phrase without prior key exchange; provides authentication and forward secrecy.
  • xxhash/highwayhash — Fast, non-cryptographic hashing for data integrity verification during transfer without cryptographic overhead.
  • TCP relay (custom in src/tcp) — Allows transfers between computers behind NAT/firewalls by facilitating peer connections through a public intermediate server.
  • gzip compression (src/compress) — Reduces bandwidth for text-heavy payloads; optional and transparent to the user.

⚖️Trade-offs already made

  • Single relay server architecture vs. decentralized P2P

    • Why: Simplicity and NAT-traversal guarantee; any two computers can connect without port-forwarding setup.
    • Consequence: Relay server becomes a single point of availability; users must trust relay operator; relay must handle peak bandwidth.
  • Pass-phrase as key material vs. pre-shared keys

    • Why: Human-friendly, no infrastructure for key distribution; users share a short code out-of-band.
    • Consequence: Lower entropy than 256-bit random keys; vulnerable to brute-force if pass-phrase is weak; PAKE mitigates offline attacks.
  • Symmetric encryption only (no public-key crypto)

    • Why: Reduces binary size, improves performance, simpler key management.
    • Consequence: Requires pass-phrase sharing for each transfer; no persistent identity across transfers; no repudiation protection.
  • Mnemonicode (wordlist encoding) for pass-phrases

    • Why: Improves UX by allowing human-readable code instead of random bytes.
    • Consequence: Slightly lower entropy per character; easier to transcribe but still requires sharing out-of-band.

🚫Non-goals (don't propose these)

  • Does not provide persistent file storage or cloud functionality.
  • Does not handle user authentication or multi-user access control.
  • Does not support real-time file synchronization or version control.
  • Does not provide graphical user interface (CLI-only by design).
  • Does not implement peer discovery beyond local network (relies on manual relay address input).
  • Does not support resumable transfers on connection loss (must retry entire transfer).

🪤Traps & gotchas

PAKE security depends on strong passphrases (short codes are vulnerable to brute force); relay servers see encrypted traffic but not contents, however users must trust relay availability. The --relay flag defaults to a public relay (implied in docs) but no default is hardcoded in code—verify relay endpoint configuration in src/croc/croc.go. File resumption uses kalafut/imohash for fast identity checks, but hash collisions on partial files are theoretically possible with weak passphrases. Windows disk usage detection uses diskusage_windows.go via platform-specific build tags—test on Windows explicitly.

🏗️Architecture

💡Concepts to learn

  • PAKE (Password-Authenticated Key Exchange) — croc's entire security model depends on PAKE via schollz/pake/v3; understanding how passphrases become encryption keys without pre-shared infrastructure is essential to evaluating croc's threat model
  • AES-GCM (Authenticated Encryption) — Used in src/crypt/crypt.go to encrypt transferred data; GCM provides both confidentiality and integrity, preventing tampering even by relay servers
  • Relay-based P2P NAT Traversal — croc's key differentiator: instead of requiring port-forwarding, uses an intermediary relay server to bridge connections across NATs; understanding this pattern explains why croc works 'anywhere'
  • Fast Content-Addressing with imohash — croc uses kalafut/imohash in transfer validation and resume; enables partial file integrity checks without hashing the entire file, critical for resuming large transfers efficiently
  • Mnemonic Code (BIP39-style wordlists)src/mnemonicode/ converts random bytes to human-readable word phrases; users exchange these passphrases instead of random hex strings, improving UX but reducing entropy per word
  • Connection Pooling & Message Framingsrc/comm/comm.go implements multiplexing of files over a single encrypted connection; understanding this prevents naive parallelization bugs that could break encryption boundaries
  • Resumable Transfers with Seek Points — croc supports resuming interrupted transfers by storing seek offsets; requires understanding of file fragmentation and hash validation across partial chunks
  • magic-wormhole/magic-wormhole — Python-based P2P file transfer with PAKE, same security model but older; croc is the modern Go alternative with better relay support
  • sftpgo/sftpgo — SFTP server in Go for file transfer, but requires explicit server setup; croc eliminates that overhead with peer-to-peer
  • restic/restic — Go-based backup tool using similar encryption and hashing patterns; shares golang.org/x/crypto stack and resume logic
  • schollz/pake — Maintained by same author (schollz); Go implementation of PAKE that croc depends on—understanding this repo helps understand croc's key exchange
  • syncthing/syncthing — Go continuous file sync tool; uses different P2P discovery and encryption but similar relay-based NAT traversal pattern

🪄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 integration tests for src/tcp/tcp.go relay functionality

The tcp package handles core relay server logic but only has tcp_test.go with likely basic coverage. Given that croc's primary value proposition is secure file transfer through relays, integration tests validating end-to-end relay scenarios (connection establishment, message routing, disconnection handling, concurrent transfers) would significantly improve reliability. This is critical infrastructure that deserves thorough testing.

  • [ ] Expand src/tcp/tcp_test.go with integration tests for relay scenarios
  • [ ] Add tests for concurrent client connections to the relay in src/tcp/tcp_test.go
  • [ ] Test relay timeout and connection cleanup in src/tcp/tcp_test.go
  • [ ] Validate message routing between sender/receiver pairs through the relay

Add unit tests for src/diskusage/diskusage.go cross-platform implementations

The diskusage package has platform-specific implementations (diskusage.go and diskusage_windows.go) but diskusage_test.go likely doesn't test both paths thoroughly. A new contributor could add dedicated test cases for Windows-specific disk usage logic, mock filesystem scenarios, and validate that disk space checking works correctly on both platforms before attempting transfers.

  • [ ] Add unit tests in src/diskusage/diskusage_test.go for Windows-specific disk queries
  • [ ] Create mock filesystem tests for low-disk-space scenarios
  • [ ] Test error handling when disk usage cannot be determined
  • [ ] Ensure test coverage for both Unix and Windows code paths

Implement missing GitHub Actions workflow for Docker image builds and registry pushes

The repo has a Dockerfile and Docker entrypoint script (croc-entrypoint.sh) but no dedicated CI workflow for building and publishing Docker images. Unlike the existing release.yml and deploy.yml, there's no automated Docker image building to Docker Hub or GHCR on releases. This would make the containerized distribution seamless and catch Docker build regressions early.

  • [ ] Create .github/workflows/docker.yml to build Docker images on tags
  • [ ] Configure Docker image push to GitHub Container Registry (GHCR) and/or Docker Hub
  • [ ] Add build matrix for multiple architectures (linux/amd64, linux/arm64) using buildx
  • [ ] Integrate with existing release.yml workflow or trigger on git tags matching version pattern

🌿Good first issues

  • Add integration tests for relay server failover: src/croc/croc_test.go has unit tests but no test covering relay unavailability and fallback to alternate relay. Create a test that spins up two mock relays, fails the first, and verifies seamless reconnect.
  • Document the PAKE passphrase strength requirements: README has no guidance on passphrase length/entropy; add a security FAQ section explaining why 3-word mnemonics (from src/mnemonicode/wordlist.go) are weak for untrusted networks and recommend 5+ words or custom passphrases.
  • Extend src/diskusage/diskusage.go to report free space warnings during send: currently only detects available space on receiver, but large transfers on full disks fail silently. Add pre-transfer validation logging to CLI output.

Top contributors

Click to expand

📝Recent commits

Click to expand
  • f662ab7 — chore: update deps and bump (schollz)
  • 0a819a8 — fix: honor --exclude and --git when --zip is used (#1097) (costajohnt)
  • 11bbae1 — fix: Tell user minimum length of custom code (#1094) (Tyarel8)
  • 1b7e260 — fix: remove builds (schollz)
  • 9a3d42a — fix: progressbar width (schollz)
  • b1a3595 — bump: version (schollz)
  • 0ad7e51 — chore: bump actions (schollz)
  • 44e9da1 — chore: update dependencies (schollz)
  • 1022652 — chore: bump version (schollz)
  • 6d51c7e — fix: Zip Slip traversal and bound network message allocation size limits (schollz)

🔒Security observations

  • High · Outdated Go Version in Docker Build — Dockerfile (line 1). The Dockerfile uses golang:1.24-alpine for building, but the go.mod specifies 'go 1.25.0'. This version mismatch could lead to incompatibilities, missing security patches, or unexpected behavior during the build process. Fix: Update the builder stage to use golang:1.25-alpine or later to match go.mod requirements. Ensure the Go version is regularly updated to receive security patches.
  • Medium · Missing SBOM and Supply Chain Security — go.mod, go.sum, CI/CD workflows. No evidence of dependency pinning strategies, SBOM generation, or supply chain security practices (e.g., go.sum verification, dependency scanning). The repository relies on semantic versioning without strict hash verification mechanisms visible. Fix: Implement go.sum verification in CI/CD, enable GitHub's dependency scanning, and consider using tools like Trivy or Snyk for regular vulnerability scanning of dependencies.
  • Medium · Insecure Network Exposure in Docker — Dockerfile (EXPOSE directives). The Dockerfile exposes multiple TCP ports (9009-9013) without documenting security boundaries or authentication mechanisms. If the relay service is exposed to untrusted networks, it could be exploited. Fix: Document network security requirements in README. Implement TLS/mutual TLS for relay communications. Use firewall rules to restrict port access. Consider requiring authentication tokens for relay access.
  • Medium · Weak Container User Configuration — Dockerfile (USER directive). The container runs as 'nobody' user, which is appropriate, but there's no explicit capability dropping or seccomp profile defined. This could increase the attack surface if other vulnerabilities exist. Fix: Add explicit security contexts: disable unnecessary Linux capabilities using 'drop ALL' and add back only required ones. Define seccomp profiles. Use read-only root filesystem where possible.
  • Medium · Health Check Implementation Vulnerability — Dockerfile (HEALTHCHECK directive). The HEALTHCHECK uses 'nc' (netcat) for TCP connectivity testing. While functional, it doesn't verify application health or authenticate the connection, potentially allowing unauthorized access detection. Fix: Implement an HTTP health endpoint with authentication, or verify response integrity. Ensure health checks don't expose sensitive information.
  • Low · Missing .gitignore Security Review — .gitignore. While .gitignore exists, without viewing its contents, it's unclear if sensitive files (keys, credentials, temporary test data) are properly excluded from version control. Fix: Review .gitignore to ensure it includes: .key, .pem, .env, config.local., credentials/*, and any temporary test files. Add pre-commit hooks to prevent accidental secrets commits.
  • Low · Cryptographic Dependency Review Needed — go.mod (golang.org/x/crypto, schollz/pake/v3). The project uses golang.org/x/crypto v0.50.0 and custom PAKE implementation (schollz/pake/v3). While these are well-maintained, custom crypto implementations require careful auditing. Fix: Ensure PAKE implementation has been independently audited. Keep golang.org/x/crypto updated. Document cryptographic algorithms used (key derivation, encryption, hashing).
  • Low · Missing Security Headers Documentation — Repository root. No visible documentation of security practices, threat model, or security guidelines for contributors. No SECURITY.md file for responsible disclosure. Fix: Create SECURITY.md with: vulnerability reporting process, security contact, supported versions, and responsible disclosure policy. Add security section to README.
  • Low · Minimal Alpine Base Image Best Practices — Dockerfile (line 11). While using Alpine is good for reducing attack surface, the image uses 'alpine:latest' without specifying a version tag, risking unexpected breaking changes. Fix: Pin Alpine version: use 'alpine:3.19' or 'alpine:3.20' instead of 'alpine:latest'. Regularly update pinned versions during maintenance cycles.

LLM-derived; treat as a starting point, not a security audit.


Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.

Healthy signals · schollz/croc — RepoPilot