Skip to content
 
 

Latest commit

 

History

143 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Astera-org/tusc.sh

Test

Software License

This is the Astera Institute fork of adhocore/tusc.sh with macOS / bash 3.2 portability, no jq dependency, progress / resume visibility, directory upload, and a Lima-based Linux test harness. Upstream's original copyright is preserved in LICENSE.

tusc is tus 1.0.0 client protocol implementation for bash.

tusc lets you upload big files to servers supporting tus protocol right from your terminal.

If anything goes wrong, you can rerun the command to resume upload from where it was left off.

Fun Fact: Git LFS also supports tus.io protocol.

Installation

curl -fsSLo ~/tusc https://raw.githubusercontent.com/Astera-org/tusc.sh/main/tusc.sh
# for global binary
chmod +x ~/tusc && sudo ln -s ~/tusc /usr/local/bin/tusc
# OR, for user binary
chmod +x ~/tusc && mv ~/tusc ~/.local/bin/tusc

tusc --update will pull the latest tusc.sh from this same fork.

This fork runs on stock macOS using the system /bin/bash (3.2) — no Homebrew bash, no GNU coreutils, no jq required.

System Requirements

  • bash ≥ 3.2 (macOS stock bash is fine)
  • awk
  • base64
  • curl
  • grep, tr
  • mktemp
  • realpath (macOS 12.3+ ships it in /usr/bin; Linux ships it in coreutils)
  • shasum (macOS) or sha1sum/sha256sum (Linux)
  • stat, tail, seq, sleep

Donot worry, in a typical UNIX flavored system these are likely to be there already.

Resume-state cache

tusc.sh keeps a small per-user cache so that interrupting an upload (Ctrl-C, network drop, server restart) and re-running the same command resumes from where it left off instead of starting over. Two kinds of entries get stored:

File Holds Why
ck.<sha1-of-path:mtime>.<algo> The file's sha1/sha256/… hex digest Skip re-hashing multi-GB files each run
loc.<checksum>.<sha1-of-host+base-path> The TUS upload URL returned by POST Lets the next run HEAD it and resume

Touching or rewriting the file changes its mtime, which invalidates the checksum entry — so the cache never serves stale hashes.

Location

Default: ${TMPDIR:-/tmp}/tusc.<uid>/ — under the OS temp dir, mode 0700, scoped per Unix uid. Survives across invocations within a session; the OS will reclaim it on reboot/cleanup.

Override with the TUSDIR environment variable:

# Cache that survives reboots
TUSDIR=~/.cache/tusc ./tusc.sh -H ... -f ...

# Fully isolated, single-run cache
TUSDIR=$(mktemp -d) ./tusc.sh -H ... -f ...

When to wipe it

rm -rf "${TMPDIR:-/tmp}/tusc.$(id -u)"
  • the file changed but mtime didn't (unusual — touch the file instead),
  • you want to force a brand-new TUS upload rather than resuming an existing one,
  • you suspect the cached resume URL points at an upload the server has since deleted (in that case tusc.sh will detect the 404 on HEAD and POST a new upload anyway, so this is mostly defensive).

Usage and Examples

  tusc.sh v2.0.0 | (c) Jitendra Adhikari | https://github.com/adhocore
  tusc.sh is bash implementation of tus-client (https://tus.io).
  With contributions from Astera Institute (https://astera.org).

  Usage:
    tusc.sh <--options>
    tusc.sh <host> <file> [algo]

  Options:
    -a --algo      The algorigthm for key &/or checksum.
                   (Eg: sha1, sha256)
    -b --base-path The tus-server base path (Default: '/files/').
    -c --creds     File with credentials; user and pass in shell syntax:
                     USER="my_user"
                     PASS="my_pass"
    -C --no-color  Donot color the output (Useful for parsing output).
    -f --file      The file to upload (or directory, with -d).
    -R --restart   Ignore the cached upload URL; start a fresh upload.
       --retries N Retry a PATCH up to N times on transient failures
                   (transport error or 5xx). Default 'inf' (never give up
                   on transient errors). Pass 0 to fail immediately.
       --chunk-size SIZE  Split the upload into PATCHes of SIZE bytes
                   (accepts K/M/G suffix). Default 50M. Smaller chunks
                   survive flaky LBs and idle-timeouts better.
    -N --name      Override the filename sent in Upload-Metadata.
                   (May contain slashes; server gets the literal value.)
       --remote-path PATH  Destination directory prefix for Upload-Metadata.filename.
                   Composes with -N and -d; the source basename / -N value /
                   dir-mode relpath is appended under PATH. Leading and
                   trailing slashes are stripped (e.g. videos/2024).
    -d --dir       Treat --file as a directory; upload every file under it,
                   preserving the relative path in Upload-Metadata.filename.
    -h --help      Show help information and usage.
    -H --host      The tus-server host where file is uploaded.
    -L --locate    Locate the uploaded file in tus-server.
    -u --update    Update tusc to latest version.
       --version   Print the current tusc version.

  Environment:
    DEBUG=1        Show the script's request trace on stderr. Also enables
                   curl -v unless basic-auth creds are in use (-v leaks the
                   Authorization header).
    TUSC_DEBUG_UNSAFE=1  Re-enable curl -v when DEBUG=1 + creds. Use only for
                   debugging against trusted endpoints — exposes Authorization.
    TUSDIR         Cache dir for resume state and file checksums.
                   (Default: $TMPDIR/tusc.<uid>/. Delete to force a fresh upload.)
    TUSC_NOCACHE=1 Always re-hash the file; ignore the checksum cache.
    TUSC_USER      Basic-auth username (alternative to --creds file).
    TUSC_PASS      Basic-auth password (paired with TUSC_USER).

  Examples:
    tusc.sh --help                           # shows this help
    tusc.sh --update                         # updates itself
    tusc.sh --version                        # prints current version of itself
    tusc.sh    0:1080    ww.mp4              # uploads ww.mp4 to http://0.0.0.0:1080/files/
    tusc.sh -H 0:1080 -f ww.mp4              # same as above
    tusc.sh -H 0:1080 -f ww.mp4 -a sha256    # same as above but uses sha256 algo for key/checksum
    tusc.sh -H 0:1080 -f ww.mp4 -b /store/   # uploads ww.mp4 to http://0.0.0.0:1080/store/

If you want to parse the output of tusc, pass in -C (no color). Eg:

# Locate the URL of a file and download it
wget $(tusc -H 0:1080 -f ww.mp4 -L -C | cut -c 6-999) -O ww.mp4.1

Authentication

If your tusd server requires special header or token for auth, just pass in [curl args]:

tusc -H 0:1080 -f ww.mp4 -b /store/ -- -H "'Authorization: Bearer <token>'" -H "'x-key: value'"

In fact you can pass in anything after -- as extra curl parameter.

Preview

See tusc in action with debug mode where the upload is aborted frequently with Ctrl+C interrupt.

Screen Preview

Debugging

To print the debugging information pass in DEBUG=1 env like so:

DEBUG=1 tusc 0:1080 ww.mp4

To print the lines of script as they are executed, create a debug file:

touch ~/.tus.dbg

To revert the above step, just remove the debug file:

rm ~/.tus.dbg

Trying Out

To get hands on in local machine, you can install tusd server.

Then,

# run tusd server (http://0.0.0.0:1080)
tusd -dir ~/.tusd-data > /dev/null 2>&1 &
# start uploading large files
DEBUG=1 tusc --host 0:1080 --file /full/path/to/large/file

# for tusd v2 (http://0.0.0.0:8080)
tusd -upload-dir ~/.tusd-data > /dev/null 2>&1 &
DEBUG=1 tusc --host 0:8080 --file /full/path/to/large/file

While upload is in progress, you can force abort it using Ctrl+C.

Then resume upload again:

DEBUG=1 tusc --host 0:1080 --file /full/path/to/large/file

It should start from where it last stopped.

You can check the uploaded files like so:

ls -al ~/.tusd-data

Testing

End-to-end tests live in test/. The runner downloads a tusd binary into test/.cache/ (override with TUSC_CACHE_DIR=...), uploads a 5 MiB fixture, fetches it back, and compares SHA-256s.

Locally (macOS or Linux)

bash test/test.sh

Linux from a macOS host, via Lima

Lima (brew install lima) spins up an Ubuntu 24.04 VM, installs curl/tar, mounts the repo read-only at /repo, and runs the test inside the VM.

bash test/run-lima.sh            # leave the VM running for repeat runs
bash test/run-lima.sh --clean    # tear the VM down when done

The same test/test.sh runs in GitHub Actions on both ubuntu-latest and macos-latest.

Contributors

  • adhocore - Lead Developer
  • tonk - Credential support
  • Wouter van Hilst - Chunked upload
  • Astera Institute - macOS / bash 3.2 portability, removal of jq dependency, Lima-based test harness

Tooling

The macOS portability work, jq removal, and Lima-based test harness in this fork were drafted with the help of Claude Code (Anthropic) and reviewed by a human before landing.

License

Released under the MIT License. Original work © 2018 Jitendra Adhikari; fork changes © 2026 Astera Institute. The original copyright notice is preserved in LICENSE as required.

About

tus 1.0.0 client protocol implementation for bash. Resumable large file upload to Tus sever from terminal using bash script

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages