Go library and CLIs for working with container registries

Overview

go-containerregistry

GitHub Actions Build Status GoDoc Go Report Card Code Coverage

Introduction

This is a golang library for working with container registries. It's largely based on the Python library of the same name.

The following diagram shows the main types that this library handles. OCI image representation

Philosophy

The overarching design philosophy of this library is to define interfaces that present an immutable view of resources (e.g. Image, Layer, ImageIndex), which can be backed by a variety of medium (e.g. registry, tarball, daemon, ...).

To complement these immutable views, we support functional mutations that produce new immutable views of the resulting resource (e.g. mutate). The end goal is to provide a set of versatile primives that can compose to do extraordinarily powerful things efficiently and easily.

Both the resource views and mutations may be lazy, eager, memoizing, etc, and most are optimized for common paths based on the tooling we have seen in the wild (e.g. writing new images from disk to the registry as a compressed tarball).

Experiments

Over time, we will add new functionality under experimental environment variables listed here.

Env Var Value(s) What is does
GGCR_EXPERIMENT_ESTARGZ "1" When enabled this experiment will direct tarball.LayerFromOpener to emit estargz compatible layers, which enable them to be lazily loaded by an appropriately configured containerd.

v1.Image

Sources

Sinks

v1.ImageIndex

Sources

Sinks

v1.Layer

Sources

Sinks

Overview

mutate

The simplest use for these libraries is to read from one source and write to another.

For example,

  • crane pull is remote.Image -> tarball.Write,
  • crane push is tarball.Image -> remote.Write,
  • crane cp is remote.Image -> remote.Write.

However, often you actually want to change something about an image. This is the purpose of the mutate package, which exposes some commonly useful things to change about an image.

partial

If you're trying to use this library with a different source or sink than it already supports, it can be somewhat cumbersome. The Image and Layer interfaces are pretty wide, with a lot of redundant information. This is somewhat by design, because we want to expose this information as efficiently as possible where we can, but again it is a pain to implement yourself.

The purpose of the partial package is to make implementing a v1.Image much easier, by filling in all the derived accessors for you if you implement a minimal subset of v1.Image.

transport

You might think our abstractions are bad and you just want to authenticate and send requests to a registry.

This is the purpose of the transport and authn packages.

Tools

This repo hosts some tools built on top of the library.

crane

crane is a tool for interacting with remote images and registries.

gcrane

gcrane is a GCR-specific variant of crane that has richer output for the ls subcommand and some basic garbage collection support.

k8schain

k8schain implements the authentication semantics use by kubelets in a way that is easily consumable by this library.

k8schain is not a standalone tool, but it's linked here for visibility.

Emeritus: ko

This tool was originally developed in this repo but has since been moved to its own repo.

Comments
  • add FindManifests

    add FindManifests

    Add FindManifests utility, that allows one to pass a v1.ImageIndex and a match.Matcher, and get back the v1.Descriptor entries in the index that match.

    This is a spin-out from #823 and will include the salient original comments below.

    We expect to have several more such utilities that build on Matcher in this PR and/or others before it is done.

    opened by deitch 37
  • match package with matcher and utils to filter v1.Descriptors; v1.Platform.Equals utility

    match package with matcher and utils to filter v1.Descriptors; v1.Platform.Equals utility

    Starts to address #821

    • creates a ManifestMatcher and utilities that can be used to find manifests that match the provided matcher
    • provides convenience matcher utilities to match by annotation, media-types, name (specific annotation), platform
    • provides a FindManifests that takes a v1.ImageIndex and returns the manifests in it that match. This is useful in its own right, but will be even more useful later for tree walking.

    Some questions and follow-ons:

    • is this the right location for it? partial was suggested but seems, well, off. This is a utilities package, but mostly seems to have internal utils, although it still works better than partial. I think this could handle being renamed to util since v1/v1util is a mouthful.
    • while this is really simple, it doesn't provide a good option for depth. E.g. we might want in the future to be able to walk down and filter based on depth. I don't think that matters much now because (a) this is just the manifests, while the walker can handle depth; (b) this is simple and clean; (b) we haven't proven we have a real use case for infinite depth. Theoretically, and index can include an index can include (ad infinitum), but in practice we only ever see index->manifest or, in the case of v1.layout, index->index->manifest. That can be handled separately.

    Once this is good, we can start to add the next parts.

    cc @jonjohnsonjr

    opened by deitch 29
  • add download progress option for v1.tarball

    add download progress option for v1.tarball

    Initial implementation of download progress, per the discussion here with @jonjohnsonjr .

    This only does it for v1.tarball; it still will need to be added to legacy.tarball and v1.layout. I also have given it zero testing. The goal is to have a basis for discussion.

    I chose to change the calls to Write/MultiWrite/MultiWriteRef rather than entirely new funcs because:

    • it would create an over-proliferation of functions and be very messy
    • you always can pass in nil to a channel arg if you don't want it (which is what I did for almost all consumers
    • with go modules, versioning of consumers is easy, so breaking changes on a new commit is not a big deal.
    opened by deitch 28
  • Use hamilton instead of autorest for Azure Container Registry authentication

    Use hamilton instead of autorest for Azure Container Registry authentication

    Hi!

    Thank you for all the hard work you are doing. :1st_place_medal:

    Right now, autorest from Microsoft is used to provide authentication to Azure Container Registry. There's a much smaller project used by the folks over at Hashicorp (used by terraform, azurerm provider, azuread provider) that's much more ... Go. And smaller!

    I've been testing it out and it seems to be working. Will need a bit of polish but I thought I'd bring up the question here and see what you think about it.

    The project is called hamilton and can be found here: https://github.com/manicminer/hamilton

    My idea is that we would provide the Azure authentication and ACR token exchange in hamilton and add the helper to go-containerregistry (or a separate repository if that's preferred). I think it would be counter productive to remove autorest from the project to add a new one (github.com/docker/docker-credential-helpers/credentials) directly after.

    We would have to do the following to complete this task:

    • [ ] Move usage of autorest from hamilton to separate module: https://github.com/manicminer/hamilton/issues/138
    • [ ] Add Azure Container Registry token exchange support: https://github.com/manicminer/hamilton/issues/140
    • [ ] Decide where the helper should live (go-containerregistry or separate repository)
    • [x] Create the helper
    • [ ] Switch go-containerregistry from using https://github.com/chrismellard/docker-credential-acr-env to the new helper
    • [ ] Profit???

    What are your thoughts on this?

    question 
    opened by simongottschlag 22
  • v1/layout.WriteIndex ignores platform

    v1/layout.WriteIndex ignores platform

    We don't check the platform option when calling WriteIndex() see here:

    func (l Path) WriteIndex(ii v1.ImageIndex) error {
    	// Always just write oci-layout file, since it's small.
    	if err := l.WriteFile("oci-layout", []byte(layoutFile), os.ModePerm); err != nil {
    		return err
    	}
    
    	h, err := ii.Digest()
    	if err != nil {
    		return err
    	}
    
    	indexFile := filepath.Join("blobs", h.Algorithm, h.Hex)
    	return l.writeIndexToFile(indexFile, ii)
    
    }
    

    This predates #815, as it was the same for writeIndex(). We do pass it to AppendIndex:

    func (l Path) AppendIndex(ii v1.ImageIndex, options ...Option) error {
    	if err := l.WriteIndex(ii); err != nil {
    		return err
    	}
    

    where one Option is WithPlatform, but we don't actually pass it through to WriteIndex.

    Any objection to a PR to fix it?

    lifecycle/stale 
    opened by deitch 20
  • question: does crane copy support multiarch image built with docker buildx?

    question: does crane copy support multiarch image built with docker buildx?

    I would like to use crane to make the deployment to different registries easier. I have one gitlab repo, with one pipeline building a multiarch build to the Gitlab registry.

    docker buildx build --platform "linux/amd64,linux/arm64" --build-arg REGISTRY=$TARGET_REGISTRY -t $TARGET_REGISTRY_WITH_NAMESPACE/$IMAGE_NAME:$TARGET_IMAGE_TAG --push .

    and then, I would like to push this multarch image to AWS ECR registry (actually a job used twice with 2 different target registries).

    - crane auth login $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD
    - aws ecr get-login-password --region $AWS_REGION | crane auth login --username AWS --password-stdin $TARGET_REGISTRY
    - crane cp $CI_REGISTRY_IMAGE/$IMAGE_NAME:$IMAGE_TAG $TARGET_REGISTRY_WITH_NAMESPACE/$IMAGE_NAME:$TARGET_IMAGE_TAG
    

    the auth to the 2 registries (gitlab and aws) seems to be ok, but the crane cp always results with a 400:

    2022/03/15 15:28:40 failed to copy index: HEAD <aws-registry>/v2/<aws-namespace>/manifests/sha256:fwed95...: unsupported status code 400

    Any idea why this 400? Could be more a question for AWS support.

    But at the first place, it is supposed to work ? Does crane cp support copying a multi arch image?

    question lifecycle/stale 
    opened by ericbl 19
  • crane auth login fails when docker login works

    crane auth login fails when docker login works

    Steps to reproduce on macOS catalina bash. For what its worth I'm behind an enterprise proxy:

    $ echo "acctid.dkr.ecr.us-east-2.amazonaws.com" | crane auth get | jq .password | sed 's/"//g'

    long string password is output

    $ crane auth login acctid.dkr.ecr.us-east-2.amazonaws.com -u AWS -p stringfromabove $ crane pull acctid.dkr.ecr.us-east-2.amazonaws.com/reponame:tag tarball.tar

    Error: 2020/12/07 13:27:15 GET https://acctid.dkr.ecr.us-east-2.amazonaws.com/v2/repo-name/manifests/tag-name: unexpected status code 401 Unauthorized: Not Authorized

    $ docker login acctid.dkr.ecr.us-east-2.amazonaws.com -u AWS -p longstringfromabove warning about --password via cli followed by Login Succeeded docker pull succeeds

    Config.json:

    $ vim ~/.docker/config.json 
    {
            "auths": {
                    "acctid-that-I-want-to-pull-from.dkr.ecr.us-east-2.amazonaws.com": {},
                    "different-actid.dkr.ecr.us-east-2.amazonaws.com": {},
                    "jfrog.company.com": {},
                    "jfrogdev.company.com": {}
            },
            "HttpHeaders": {
                    "User-Agent": "Docker-Client/19.03.13 (darwin)"
            },
            "credsStore": "desktop",
            "experimental": "disabled",
            "stackOrchestrator": "swarm"
    }
    

    I also tried adding a

    "credHelpers": {
                    "acct-id.dkr.ecr.us-east-1.amazonaws.com": "ecr-login"
            },
    

    and setting the credsStore to ecr-login. But that didn't help my crane pull either. Running a docker pull with the ecr credHelpers set did work.

    My AWS Environment Variables are set, as is the certificate path location.

    opened by kumprj 19
  • how do I check if a layout contains all of the blobs?

    how do I check if a layout contains all of the blobs?

    Is it possible to somehow try to "resolve", or walk, my local v1 layout from an index that is there and see if all parts are there?

    Use case: let's say I have an image as follows. I am using part of docker.io/library/alpine:3.11

    9a839e63dad54c3a6d1834e29692c8492d93f90c59c978c1ed79109ea4fb9a54 - index
    |
    |- 39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01 - manifest linux/amd64
        |- f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a - config
        |-cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08 - layer0
    |- ad295e950e71627e9d0d14cdc533f4031d42edae31ab57a841c5b9588eacc280 - manifest linux/arm64
        |- c20d2a9ab6869161e3ea6d8cb52d00be9adac2cc733d3fbc3955b9268bfd7fc5 - config
        |- 29e5d40040c18c692ed73df24511071725b74956ca1a61fe6056a651d86a13bd - layer0
    

    For the above, I have all of the parts from root index through manifests, configs, and layers for linux/amd64 and linux/arm64.

    If my local layout directory has some of those, but not linux/arm64 parts, then it might look like this:

    9a839e63dad54c3a6d1834e29692c8492d93f90c59c978c1ed79109ea4fb9a54 - index
    |
    |- 39eda93d15866957feaee28f8fc5adb545276a64147445c64992ef69804dbf01 - manifest linux/amd64
        |- f70734b6a266dcb5f44c383274821207885b549b75c8e119404917a61335981a - config
        |-cbdbe7a5bc2a134ca8ec91be58565ec07d037386d1f1d8385412d224deafca08 - layer0
    

    How do I check if all of the parts are there without going to docker.io? I can do the following:

    		desc, err := remote.Get("docker.io/library/alpine:3.11")
    		ii, err := desc.ImageIndex()
    		err = p.AppendIndex(ii)
    

    and it will go to docker.io, get the index, and then download any missing parts.

    However, it should be possible to somehow try to "resolve" my local index and see if all parts are there.

    As usual, happy to open a PR on it.

    opened by deitch 19
  • Calculate digest from tarball

    Calculate digest from tarball

    Our build system produces tarballs and K8s deployment configurations, later to be deployed to multiple environments. We would like to get the image's digest at build time so we could reference it in the configuration, rather than relying on a tag, which is not stable.

    Could Crane calculate the digest from a tarball? From what I gather, crane digest only works with a remote image.

    lifecycle/frozen 
    opened by aelij 18
  • Allow Reference also for daemon write

    Allow Reference also for daemon write

    I thought this was going to be a simple one-liner, like before:

    -func Write(tag name.Tag, img v1.Image) (string, error) {
    +func Write(ref name.Reference, img v1.Image) (string, error) {
    

    But I was wrong, since I actually wanted to keep the tag too...

    Closes #702

    lifecycle/frozen 
    opened by afbjorklund 18
  • extract v1.tarball manifest creation from writing, make open

    extract v1.tarball manifest creation from writing, make open

    Addresses #680 . It doesn't change how anything works, but makes it possible to get the tarball manifest.json without actually writing the tarball.

    I tried to extract it as a separate func, but there was so much duplication to what is in MultiRefWrite() that it just made sense to pull the code out of there into a separate func that always returns the manifest. If a *tar.Writer is passed, then it also writes via the writer.

    I also provided three separate convenience functions to parallel the three separate Write()/MultiWrite()/MultiRefWrite()

    This is a work in progress, so looking for thoughts.

    opened by deitch 18
  • gcrane: configured gcloud credentials not used for a service account

    gcrane: configured gcloud credentials not used for a service account

    Describe the bug

    I am using a gitlab pipeline to copy an image from project1 to project2 (I redacted the names of the projects and of the Git tags)

    The IAM credentials on project2 includes "Artifact registry writer" role

    The IAM credentials on project1 includes "Artifact registry reader" role

    The docker image is google/cloud-sdk:latest

    The debug message clearly states that credHelpers is configured for europe-west1-docker.pkg.dev buth then there is an error message No matching credentials were found for "europe-west1-docker.pkg.dev"

    Maybe there is something in the gcrane CLI that is not using the service account configured with gcloud CLI ?

    To Reproduce

        - curl -L https://github.com/google/go-containerregistry/releases/latest/download/go-containerregistry_Linux_x86_64.tar.gz -o go-containerregistry.tar.gz
        - tar -zxvf go-containerregistry.tar.gz && chmod +x gcrane
        - gcloud auth activate-service-account --key-file /tmp/gcloud-service-key.json
        - gcloud auth configure-docker europe-west1-docker.pkg.dev
        - echo ----debug---- && cat /root/.docker/config.json
        - ./gcrane cp europe-west1-docker.pkg.dev/project1/apps/xxx:$SRC_TAG europe-west1-docker.pkg.dev/project2/xxx:$SRC_TAG 
    
    $ gcloud auth activate-service-account --key-file /tmp/gcloud-service-key.json
    Activated service account credentials for: [[email protected]]
    $ gcloud auth configure-docker europe-west1-docker.pkg.dev
    Adding credentials for: europe-west1-docker.pkg.dev
    After update, the following will be written to your Docker config file located 
    at [/root/.docker/config.json]:
     {
      "credHelpers": {
        "europe-west1-docker.pkg.dev": "gcloud"
      }
    }
    Do you want to continue (Y/n)?  
    Docker configuration file updated.
    $ echo ----debug---- && cat /root/.docker/config.json
    ----debug----
    {
      "credHelpers": {
        "europe-west1-docker.pkg.dev": "gcloud"
      }
    }$ ./gcrane cp europe-west1-docker.pkg.dev/project1/apps/xxx:$SRC_TAG europe-west1-docker.pkg.dev/project2/xxx:$SRC_TAG
    2022/11/28 10:06:26 Copying from europe-west1-docker.pkg.dev/project1/apps/xxx:redacted to europe-west1-docker.pkg.dev/project2/xxx:redacted
    2022/11/28 10:06:27 No matching credentials were found for "europe-west1-docker.pkg.dev"
    Error: fetching "europe-west1-docker.pkg.dev/project1/apps/xxx:redacted": GET https://europe-west1-docker.pkg.dev/v2/token?scope=repository%3Aproject1%2Fapps%2Fxxx%3Apull&service=: UNAUTHORIZED: failed authentication
    

    Expected behavior

    The gcrane should use the credentials that were configured with gcloud

    Edit : I added a debug command to show the content of the docker config

    bug 
    opened by christopheblin 1
  • question: catalog does not support harbor-registry

    question: catalog does not support harbor-registry

    GET /v2/ HTTP/1.1 Host: 192.168.1.11:8090 User-Agent: Go-http-client/1.1 Accept-Encoding: gzip

    HTTP/1.1 401 Unauthorized Server: nginx Date: Tue, 22 Nov 2022 06:01:52 GMT Content-Type: application/json; charset=utf-8 Content-Length: 76 Connection: keep-alive Docker-Distribution-Api-Version: registry/2.0 Set-Cookie: sid=0029ac0cfac12142604b6ccdf92eb536; Path=/; HttpOnly Www-Authenticate: Bearer realm="http://192.168.1.11:8090/service/token",service="harbor-registry" X-Request-Id: b3340d7e-3515-403d-9398-70a2810b0f4b

    {"errors":[{"code":"UNAUTHORIZED","message":"unauthorized: unauthorized"}]}

    GET /service/token?scope=registry%3Acatalog%3A%2A&service=harbor-registry HTTP/1.1 Host: 192.168.1.11:8090 User-Agent: go-containerregistry/v0.12.1 Authorization: Basic YWRtaW46SGFyYm9yMTIzNDU= Accept-Encoding: gzip

    HTTP/1.1 200 OK Server: nginx Date: Tue, 22 Nov 2022 03:09:30 GMT Content-Type: application/json; charset=utf-8 Content-Length: 938 Connection: keep-alive Content-Encoding: gzip Set-Cookie: sid=44ea6920e7a6dbe6d9bbfc5a652fb62e; Path=/; HttpOnly X-Request-Id: 74aabfa7-7cc4-460b-9ab4-6cd56319bc4b X-Frame-Options: DENY Content-Security-Policy: frame-ancestors 'none'

    [REDACTED]

    GET /v2/_catalog?n=1000 HTTP/1.1 Host: 192.168.1.11:8090 User-Agent: go-containerregistry/v0.12.1 Authorization: Bearer [REDACTED] Accept-Encoding: gzip

    HTTP/1.1 401 Unauthorized Server: nginx Date: Tue, 22 Nov 2022 03:09:30 GMT Content-Type: application/json; charset=utf-8 Content-Length: 108 Connection: keep-alive Docker-Distribution-Api-Version: registry/2.0 Set-Cookie: sid=7dad7e728ad00037fb4acaa8f5ca6a97; Path=/; HttpOnly Www-Authenticate: Basic realm="harbor" X-Request-Id: f40053bd-cfaa-4616-9050-ff48c9e15445

    {"errors":[{"code":"UNAUTHORIZED","message":"unauthorized to list catalog: unauthorized to list catalog"}]}

    question 
    opened by testwill 5
  • Add support for zstd compression

    Add support for zstd compression

    This PR adds support for zstandard compression to the tarball layer implementation. It adds the application/vnd.oci.image.layer.v1.tar+zstd media type, a LayerCompression type and some extra logic in the tarball package. Moreover, this PR modifies pkg/v1/partial/compressed.go so that it is able to unpack zstd compressed layers.

    When creating a tarball layer, one can specify the compression algorithm using WithCompression and the compression level with WithCompressionLevel. By default it will still use gzip compression. The changes should be fully backwards compatible.

    To give some more context: We are adding zstd support to Northflank CI/CD & Images. We have built support for multiple build engines including Buildkit, Kaniko and CNBPs. Buildkit already supports zstd, but Kaniko does not. Adding zstd support to go-containerregistry will in turn allow Kaniko to build images with zstd compression which outperformed gzip in both performance and compression ratio in our tests.

    opened by LFrobeen 11
  • Do not force user agent when providing a custom transport

    Do not force user agent when providing a custom transport

    If a user provides their own transport, ggcr will not add its user agent header. However, the user agent will still be injected because in order for the previously mentioned insertion to be skipped, the user must call transport.NewWithContext() to get a *transport.Wrapper, and transport.NewWithContext() will inject the user agent unless the transport is already a *userAgentTransport, which would mean the user agent was already injected. If a user is supplying their own transport, they should be given full control over its headers.

    opened by hasheddan 5
  • question: Does the library support extracting image layer compressed using bzip (.tar.bz2)

    question: Does the library support extracting image layer compressed using bzip (.tar.bz2)

    Hello,

    I archived my files into a bzipped tarball and then pushed it as an OCI image using oras:

    tar -cjf test-image.tar.bz2 my-files/
    oras push [OCI-REGISTRY] test-image.tar.bz2
    

    Then I used the library to extract the image: https://github.com/google/go-containerregistry/blob/v0.12.0/pkg/v1/mutate/mutate.go#L222. I couldn't get anything extracted.

    I dug into the code and found out it uses the gzip library to uncompress the image: https://github.com/google/go-containerregistry/blob/v0.12.0/pkg/v1/partial/compressed.go#L48.

    I'm wondering if there's any plan to support uncompressing the .tar.bz2 format?

    FYI @mathieu-benoit

    question 
    opened by nan-yu 5
Releases(v0.12.1)
Owner
Google
Google ❤️ Open Source
Google
Libraries and CLIs for my personal all-in-one productivity system including components like bookmarks, notes, todos, projects, etc.

bntp.go Libraries and CLIs for my personal all-in-one productivity system including components like bookmarks, notes, todos, projects, etc. Neovim int

Jonas Mühlmann 13 Sep 13, 2022
top in container - Running the original top command in a container

Running the original top command in a container will not get information of the container, many metrics like uptime, users, load average, tasks, cpu, memory, are about the host in fact. topic(top in container) will retrieve those metrics from container instead, and shows the status of the container, not the host.

silenceshell 130 Nov 25, 2022
CLI tool and library for generating a Software Bill of Materials from container images and filesystems

A CLI tool and Go library for generating a Software Bill of Materials (SBOM) from container images and filesystems. Exceptional for vulnerability dete

Anchore, Inc. 3.4k Nov 24, 2022
espnwrapper to track real time scores for your fav match... in a terminal while working.

An espncricinfo wrapper written in go to track scores in real time and in the cmd/cli you can find the Command Line Interface wrapped over this wrapper.

Vishal Sharma 5 Mar 13, 2022
Command line tool makeing working with remote files esier.

Command line tool makeing working with remote files esier.

Techiecaro 2 Jul 27, 2022
Golang-based simple file server to serve files of the current working directory

fileserve Golang-based simple file server to serve static files of the current working directory File sharing in LAN or home network Web application t

Frank Hübner 2 Jan 9, 2022
A CLI tool for working with CloudWatch logs. It performs functions that I need at work.

CloudWatch Logs Utility A simple utility for working with CloudWatch Logs. AWS should probably build this themselves, but since they won't, I am here

J. Alexander Curtis 0 Dec 31, 2021
An os/exec like interface for running a command in a container, and being able to easily interact with stdin, stdout, and other adjustments

dockerexec An "os/exec" like interface for running a command in a container, and being able to easily interact with stdin, stdout, and other adjustmen

Segev Finer 2 Jul 14, 2022
Top-like interface for container metrics

Top-like interface for container metrics ctop provides a concise and condensed overview of real-time metrics for multiple containers: as well as a sin

bradley 13.7k Nov 27, 2022
wy : a set of command-line tools to test your container-based platform

wy wy (Abbreviation of Would You) is a set of command-line tools to test your container-based platform. ToC: Commands Deployment Monitoring Contributi

Yusuke Kuoka 2 Apr 30, 2022
Option container for golang

Option Option provides an Option container which can be used to force some addit

Nik Polakov 4 Dec 21, 2021
A tiny Go library + client for downloading Youtube videos. The library is capable of fetching Youtube video metadata, in addition to downloading videos.

A tiny Go library + client (command line Youtube video downloader) for downloading Youtube videos. The library is capable of fetching Youtube video metadata, in addition to downloading videos. If ffmpeg is available, client can extract MP3 audio from downloaded video files.

Kunal Diwan 3 Oct 14, 2022
A Go library and common interface for running local and remote commands

go-runcmd go-runcmd is a Go library and common interface for running local and remote commands providing the Runner interface which helps to abstract

AUCloud 1 Nov 25, 2021
A Simple and Clear CLI library. Dependency free.

A Simple and Clear CLI library. Dependency free. Features Nested Subcommands Uses the standard library flag package Auto-generated help Custom banners

Lea Anthony 136 Nov 24, 2022
Golang library with POSIX-compliant command-line UI (CLI) and Hierarchical-configuration. Better substitute for stdlib flag.

cmdr cmdr is a POSIX-compliant, command-line UI (CLI) library in Golang. It is a getopt-like parser of command-line options, be compatible with the ge

hz 116 Oct 28, 2022
A command-line tool and library for generating regular expressions from user-provided test cases

Table of Contents What does this tool do? Do I still need to learn to write regexes then? Current features How to install? 4.1 The command-line tool 4

Peter M. Stahl 5.7k Nov 27, 2022
A golang library for building interactive prompts with full support for windows and posix terminals.

Survey A library for building interactive prompts on terminals supporting ANSI escape sequences. package main import ( "fmt" "github.com/Alec

Alec Aivazis 3.4k Nov 23, 2022
Small, fast library to create ANSI colored strings and codes. [go, golang]

ansi Package ansi is a small, fast library to create ANSI colored strings and codes. Install Get it go get -u github.com/mgutz/ansi Example import "gi

Mario Gutierrez 377 Nov 24, 2022
Integrated console application library, using Go structs as commands, with menus, completions, hints, history, Vim mode, $EDITOR usage, and more ...

Gonsole - Integrated Console Application library This package rests on a readline console library, (giving advanced completion, hint, input and histor

null 18 Nov 20, 2022