Secure, private and feature-rich CLI password manager

Overview

Kure

PkgGoDev Go Report Card

Kure is a free and open-source password manager for the command-line.

This project aims to offer the most secure and private way of operating with sensitive data on the terminal, as well as providing a feature-rich and interactive interface to make the user experience simple and enjoyable.

Features

  • Cross-Platform: Linux, macOS, BSD and Windows supported.
  • Offline: Data is handled locally, no connection is established with 3rd parties.
  • Secure: Each record is encrypted using AES-GCM 256-bit and a unique password. Furthermore, the user's master password is never stored on disk, it's encrypted and temporarily kept in-memory inside a protected buffer, decrypted when it's required and destroyed immediately after it. The key derivation function used is Argon2 with the id version.
  • Easy-to-use: Extremely intuitive and does not require advanced technical skills.
  • Portable: Both Kure and the database compile to binary files and they can be easily carried around in an external device.
  • Multiple formats: Store entries, cards and files of any type.

Table of contents

Installation

Pre-compiled binaries

Linux, macOS, BSD and Windows pre-compiled binaries can be found here.

Homebrew (Tap)

brew install GGP1/tap/kure

Scoop (Windows)

scoop bucket add GGP1 https://github.com/GGP1/scoop-bucket.git
scoop install GGP1/kure

or

scoop install https://raw.githubusercontent.com/GGP1/scoop-bucket/master/bucket/kure.json

Docker

Use volumes -v <volume-name>:/root/.kure to persist the data on the host machine.

Mount your database and configuration file to the container using bind mounts: -v /path/to/data:./root/.kure. Any write into the bind mount will be propagated back to the Docker host.

docker run -it gastonpalomeque/kure sh

Compìle from source

Requirements: Go

git clone https://github.com/GGP1/kure
cd kure
make install

Configuration

Out-of-the-box Kure needs no configuration. It sets default values, creates the configuration file and the database at:

  • Linux, BSD: $HOME/.kure
  • Darwin: $HOME/.kure or /.kure
  • Windows: %USERPROFILE%/.kure

However, you may want to store the configuration file elsewhere or use a different one, this can be done by setting the path to it in the KURE_CONFIG environment variable.

Moving forward to the configuration file itself, in it we can specify the clipboard and session timeouts, the location of the database (if it doesn't exist it will be automatically created), the argon2 parameters, the editor used and whether or not a keyfile is required. Head over configuration for further details.

Paths inside the file must be absolute.

Formats supported: JSON, TOML, YAML. Samples.

Requirements

  • Linux, BSD: xsel, xclip, wl-clipboard or Termux:API add-on (termux-clipboard-get/set) to write to the clipboard.
  • macOS: none.
  • Windows: none.

Usage

Further information and examples about each command under docs/commands.

Overview

Overview

Documentation

This is a simplified version of the documentation, for further details, examples and demos please visit the wiki.

Database

Kure's database is a mantained fork of Bolt (bbolt), a key-value store that uses a single file and a B+Tree structure. Bolt locks the database file when it's opened, any other simultaneous process attempting to interact with the database will receive a panic.

All collections of key/value pairs are stored in buckets, five of them are used, one for each type of object and one for storing the authentication parameters. Keys within a bucket must be unique, the user will receive an error when trying to create a record with an already used name.

The database will always finish all the remaining transactions before closing the connection.

Data organization

Information isn't really stored inside file folders like we are used to, every record resides at the "root" level but with a path-like key that indicates with which other records it's grouped.

As you may have noticed, the database file isn't encrypted but each one of the records is (and with a unique password).

Under the hood, Kure uses protocol buffers (proto 3) for serializing and structuring data.

Names are case insensitive, every name's Unicode letter is mapped to its lower case, meaning that "Sample" and "saMple" both will be interpreted as "sample". Spaces within folders and objects names are allowed, however, some commands and flags will require the string to be enclosed by double quotes.

Secret generation

Atoll library is used for generating cryptographically secure secrets with a high level of randomness (check the repository documentation for further information).

Master password

Remember: the stronger your master password, the harder it will be for the attacker to get access to your information.

Kure uses the Argon2 (winner of the Password Hashing Competition in 2015) with the id version as the key derivation function, it uses a 32 byte salt along with the master password and three parameters: memory, iterations and threads. The final key is 256-bit long.

When encrypting a record, the salt used by Argon2 is randomly generated and appended to the ciphertext, everytime the record is decrypted, the salt is extracted from the end of the ciphertext and used to derive the key. Every record is encrypted using a unique password, protecting the user against precomputation attacks, such as rainbow tables.

The Argon2id variant with 1 iteration and maximum available memory is recommended as a default setting for all environments. This setting is secure against side-channel attacks and maximizes adversarial costs on dedicated bruteforce hardware.

If one of the devices that will handle the database has 1GB of memory or less, we recommend setting the memory value to the half of that device RAM availability. Otherwise, default values should be fine.

Key file

Key files are a two-factor authentication method for the database, where the user is required not only to provide the correct password but also the path to the key file, which contains a key that is combined with the password to encrypt the records. Using a key file is optional as well as specifying the path to it in the configuration file (if it isn't specified, it will be requested every time you try to access the database).

The key file should be as safe as possible and with a limited access.

Memory security

Kure encrypts and keeps the master key in-memory in a protected buffer. When the key is required for an operation, it's decrypted and sent into the key derivation function. Right after this, the protected buffer is destroyed.

The "master key" is the key that is made of the master password, and optionally, the key file.

This makes it secure even when the user is into a session and the password resides in the memory.

It's important to mention that password comparisons are done in constant time to avoid side-channel attacks and that additional sensitive information is wiped after being used as well. The library used to perform this operations is called memguard. Here are two interesting articles from its author talking about memory security and encrypting secrets in memory.

Encryption

Data encryption is done using a 256-bit key, the symmetric block cipher AES (Advanced Encryption Standard) along with GCM (Galois/Counter Mode) a cipher mode providing an authenticated encryption algorithm designed to ensure data authenticity, integrity and confidentiality.

The national institute of standards and technology (NIST) selected AES as the best algorithm in terms of security, cost, resilience, integrity and surveillance of the algorithm in October 2000.

Names aren't encrypted, why?

Although it might be considered a downside and especially if one of the objectives is to make your information as private as possible, there is an explanation.

Encrypting record names would force Kure to use the exact same key to do it (it would be virtually impossible to get a match otherwise), making the key susceptible to precomputation attacks.

Moreover, the decryption process would be slower, only for the users, preventing them to spend resources on what really matters, the key derivation function.

To sum up, the attacker may (depending on the names) be able to choose which record to attempt a brute-force attack on but using the same key for encryption and "low" argon2 parameters would make it much easier for them to get access to all your data.

Backups

We highly encourage to keep a backup of both the database and the key file (in case it's used) in an external hard drive.

The user can opt to serve the database on a local server (kure backup --http --port 8080) or create a file backup (kure backup --path path/to/file).

Restoration

Important: on interrupt signals the database will finish all the remaining transactions before closing the connection.

The database can be restored using kure restore. The user will be asked to provide new parameters. Every record is decrypted and deleted with the old configuration and re-created with the new one.

Synchronization

Synchronizing the database between devices can be done in many ways, they may introduce new vulnerabilities, use them at your own risk:

  1. remotely access a host via ssh with Kure in it.
  2. transfer the database file manually.
  3. use a file hosting service.

Sessions

The session command is, essentially, a wrapper of the root command and all its subcommands, with the difference that it doesn't exit after executing them. This makes sessions great for executing multiple commands passing the master password only once, as explained in master password, this is completely secure.

Here's a simplified implementation of session.go:

func runSession(cmd *cobra.Command) error {
          ...

    scanner := bufio.NewScanner(os.Stdin)
    go startSession(cmd, scanner)

    if timeout == 0 {
      block := make(chan struct{})
      <-block
    }

    <-time.After(timeout)
    return nil
}

func startSession(cmd *cobra.Command, scanner *bufio.Scanner) {
  for {
      scanner.Scan()
      args := strings.Split(scanner.Text(), " ")
    
          ...

      r := cmd.Root()
      r.SetArgs(args[:])
      if err := r.Execute(); err != nil {
        fmt.Fprintln(os.Stderr, err)
      }
  }
}

To start a session use kure session.

You can set a timeout using the [-t timeout] flag so it will automatically close the session once the time specified has passed. Command documentation.

Interactive prompt

kure it command starts an interactive prompt that behaves depending on the arguments received, it requests the missing information. See its wiki page to see more details.

Import/Export

kure import reads other managers' CSV files and stores the entries encrypting them with the master password previously passed.

kure export takes Kure's entries and formats them depending on the manager selected to generate a CSV file.

Formats supported: CSV.

Password managers supported:

  • 1Password
  • Bitwarden
  • Keepass/X/XC
  • Lastpass

Two-factor authentication

Kure offers storing two-factor authentication codes in the form of time-based one-time password (TOTP), a variant of the HOTP algorithm that specifies the calculation of a one-time password value, based on a representation of the counter as a time factor.

The time-step size used is 30 seconds, a balance between security and usability as specified by RFC6238.

TOTP code can be either 6, 7 or 8 digits long. The hash algorithm used is SHA1.

To add a two-factor authentication code it's necessary to have an already stored entry with the same name, this makes 2FA and entries not tightly coupled but slightly related. It's important to mention that this two are encrypted with a different salt.

Two-factor authentication adds an extra layer of security to your accounts. In case an attacker gets access to the secrets, he will still need the constantly refreshing code to get into the account making it, not impossible, but much more complicated.

Caveats and limitations

  • Kure cannot provide complete protection against a compromised operating system with malware, keyloggers or viruses.
  • There isn't any backdoor or key that can open your database. There is no way of recovering your data if you forget your master password.
  • Sharing keys is not implemented as there is no connection with the internet.
  • Windows: Cygwin/mintty/git-bash aren't supported because they are unable to reach down to the OS API.

Feedback

We would really appreciate your feedback, feel free to leave your comment here.

Contributing

Any contribution is welcome. We appreciate your time and help. Please follow these steps to do it:

Do not hesitate to leave any ideas here.

  1. Fork the repository on Github
  2. Clone your fork - git clone github.com/<your-username>/kure.git
  3. Create your feature branch - git checkout -b <your-branch>
  4. Make changes, update documentation and tests
  5. Run tests - make test-race
  6. Add them to staging - git add .
  7. Commit your changes - git commit -m '<changes>'
  8. Push to the branch - git push origin <your-branch>
  9. Create a Pull request

License

Kure is licensed under the Apache-2.0 license. See LICENSE.

Comments
  • Config permissions issues

    Config permissions issues

    Description

    Hey there! Really like the idea of kure and would love to use it. Unfortunately, when attempting to run kure, it appears that there are some issues with the permissions being set by the config file or even with the permissions schema deeming a config eligible for reading by kure.

    This prevents me from using any subcommands because the config is read before every function call. I cannot even run the help command, so I would consider this fairly high severity.

    It looks as though this was also spotted in your Github action build step here: https://github.com/GGP1/kure/runs/1980446702#step:4:87

    Expected Behavior

    # Desired behavior is the following command
    # followed by no error and a successfully created yaml config
    kure config create
    

    System Details

    # Systems where the error 
    # has been replicated
    systems:
     - name: "Pop OS"
       shell: "zsh"
       prompt: "starship"
    
     - name: "OSX"
       shell: "zsh"
       prompt: "starship"
    

    Possible Issues

    I believe the issue is localized to the /config package in the repository as that is the only place dealing with file permissions for ~/.kure/kure.* files.

    Screenshots

    image image

    opened by brittonhayes 38
  • Out of memory error

    Out of memory error

    Kure is throwing OOM error below even though I have lots of memory.

    $ free -m
                  total        used        free      shared  buff/cache   available
    Mem:           3933        3554         103           0         275        1313
    Swap:          1024         397         626
    
    $ kure ls
    Enter master password: 
    fatal error: runtime: out of memory
    
    runtime stack:
    runtime.throw(0xac392f, 0x16)
            C:/Program Files/Go/src/runtime/panic.go:1117 +0x72
    runtime.sysMap(0xc004000000, 0x40000000, 0xf5c8f0)
            C:/Program Files/Go/src/runtime/mem_linux.go:169 +0xc6
    runtime.(*mheap).sysAlloc(0xf43800, 0x40000000, 0x42bf97, 0xf43808)
            C:/Program Files/Go/src/runtime/malloc.go:729 +0x1e5
    runtime.(*mheap).grow(0xf43800, 0x20000, 0x0)
            C:/Program Files/Go/src/runtime/mheap.go:1346 +0x85
    runtime.(*mheap).allocSpan(0xf43800, 0x20000, 0xc000190100, 0x7f8cc1891668)
            C:/Program Files/Go/src/runtime/mheap.go:1173 +0x609
    runtime.(*mheap).alloc.func1()
            C:/Program Files/Go/src/runtime/mheap.go:910 +0x59
    runtime.systemstack(0x0)
            C:/Program Files/Go/src/runtime/asm_amd64.s:379 +0x66
    runtime.mstart()
            C:/Program Files/Go/src/runtime/proc.go:1246
    
    goroutine 1 [running]:
    runtime.systemstack_switch()
            C:/Program Files/Go/src/runtime/asm_amd64.s:339 fp=0xc0001237e0 sp=0xc0001237d8 pc=0x46a7a0
    runtime.(*mheap).alloc(0xf43800, 0x20000, 0xc000120101, 0x40d42a)
            C:/Program Files/Go/src/runtime/mheap.go:904 +0x85 fp=0xc000123830 sp=0xc0001237e0 pc=0x427c45
    runtime.(*mcache).allocLarge(0x7f8ce86eba68, 0x40000000, 0xc0001b0101, 0x7f8cc1891668)
            C:/Program Files/Go/src/runtime/mcache.go:224 +0x97 fp=0xc000123888 sp=0xc000123830 pc=0x4182b7
    runtime.mallocgc(0x40000000, 0x9f9960, 0x1, 0xc0001be000)
            C:/Program Files/Go/src/runtime/malloc.go:1078 +0x925 fp=0xc000123910 sp=0xc000123888 pc=0x40dee5
    runtime.makeslice(0x9f9960, 0x100000, 0x100000, 0xe3936e4be40b3259)
            C:/Program Files/Go/src/runtime/slice.go:98 +0x6c fp=0xc000123940 sp=0xc000123910 pc=0x44df6c
    golang.org/x/crypto/argon2.initBlocks(0xc0001ba000, 0x800100000, 0x29, 0xc0000feabd, 0x20)
            F:/Gasti/Go/pkg/mod/golang.org/x/[email protected]/argon2/argon2.go:160 +0x59 fp=0xc0001239a0 sp=0xc000123940 pc=0x803239
    golang.org/x/crypto/argon2.deriveKey(0x2, 0x7f8cc188ffd7, 0x29, 0x29, 0xc0000feabd, 0x20, 0x20, 0x0, 0x0, 0x0, ...)
            F:/Gasti/Go/pkg/mod/golang.org/x/[email protected]/argon2/argon2.go:115 +0x1dc fp=0xc000123a90 sp=0xc0001239a0 pc=0x802cfc
    golang.org/x/crypto/argon2.IDKey(...)
            F:/Gasti/Go/pkg/mod/golang.org/x/[email protected]/argon2/argon2.go:99
    github.com/GGP1/kure/crypt.deriveKey(0xc0000feabd, 0x20, 0x20, 0x1, 0x1, 0x4, 0x4, 0x1, 0x0)
            F:/Gasti/Go/src/github.com/GGP1/kure/crypt/crypt.go:123 +0x2a6 fp=0xc000123b68 sp=0xc000123a90 pc=0x809086
    github.com/GGP1/kure/crypt.Decrypt(0xc0000fea81, 0x5c, 0x5c, 0x5c, 0x10000000000001, 0x100000008, 0x0, 0x0)
            F:/Gasti/Go/src/github.com/GGP1/kure/crypt/crypt.go:68 +0x9c fp=0xc000123c30 sp=0xc000123b68 pc=0x808a3c
    github.com/GGP1/kure/auth.Login.func1(0xc000200500, 0xf5a4b0, 0x0, 0x0, 0x0, 0x0)
            F:/Gasti/Go/src/github.com/GGP1/kure/auth/auth.go:63 +0x18f fp=0xc000123ce0 sp=0xc000123c30 pc=0x918baf
    github.com/spf13/cobra.(*Command).execute(0xc000200500, 0xf5a4b0, 0x0, 0x0, 0xc000200500, 0xf5a4b0)
            F:/Gasti/Go/pkg/mod/github.com/spf13/[email protected]/command.go:841 +0x523 fp=0xc000123da0 sp=0xc000123ce0 pc=0x904303
    github.com/spf13/cobra.(*Command).ExecuteC(0xeafc40, 0xaebed0, 0xb7c898, 0xb6ad20)
            F:/Gasti/Go/pkg/mod/github.com/spf13/[email protected]/command.go:960 +0x375 fp=0xc000123e80 sp=0xc000123da0 pc=0x904dd5
    github.com/spf13/cobra.(*Command).Execute(...)
            F:/Gasti/Go/pkg/mod/github.com/spf13/[email protected]/command.go:897
    github.com/GGP1/kure/commands/root.Execute(0xc000152200, 0xc000152200, 0xc000000180)
            F:/Gasti/Go/src/github.com/GGP1/kure/commands/root/root.go:41 +0x3b fp=0xc000123eb0 sp=0xc000123e80 pc=0x98d51b
    main.main()
            F:/Gasti/Go/src/github.com/GGP1/kure/main.go:33 +0x1b3 fp=0xc000123f88 sp=0xc000123eb0 pc=0x98e873
    runtime.main()
            C:/Program Files/Go/src/runtime/proc.go:225 +0x256 fp=0xc000123fe0 sp=0xc000123f88 pc=0x438bd6
    runtime.goexit()
            C:/Program Files/Go/src/runtime/asm_amd64.s:1371 +0x1 fp=0xc000123fe8 sp=0xc000123fe0 pc=0x46c4a1
    
    goroutine 18 [sleep]:
    time.Sleep(0x1dcd6500)
            C:/Program Files/Go/src/runtime/time.go:193 +0xd2
    github.com/awnumar/memguard/core.NewCoffer.func1(0xc0000a0240)
            F:/Gasti/Go/pkg/mod/github.com/awnumar/[email protected]/core/coffer.go:43 +0x2a
    created by github.com/awnumar/memguard/core.NewCoffer
            F:/Gasti/Go/pkg/mod/github.com/awnumar/[email protected]/core/coffer.go:40 +0xd6
    
    goroutine 5 [syscall]:
    os/signal.signal_recv(0x0)
            C:/Program Files/Go/src/runtime/sigqueue.go:168 +0xa5
    os/signal.loop()
            C:/Program Files/Go/src/os/signal/signal_unix.go:23 +0x25
    created by os/signal.Notify.func1.1
            C:/Program Files/Go/src/os/signal/signal.go:151 +0x45
    
    goroutine 20 [chan receive]:
    github.com/GGP1/kure/sig.(*sig).Listen.func1(0xf2ae20, 0xc000152200)
            F:/Gasti/Go/src/github.com/GGP1/kure/sig/sig.go:69 +0x4c
    created by github.com/GGP1/kure/sig.(*sig).Listen
            F:/Gasti/Go/src/github.com/GGP1/kure/sig/sig.go:68 +0xfd
    
    opened by trankchung 5
  • error: invalid length

    error: invalid length

    I'm trying to use a key file and getting error error: invalid length. I tried x509 key file as well as just a simple hash string in a file and the same error.

    opened by ghost 2
  • bhayes/list alias

    bhayes/list alias

    Changes

    - updated gitignore to ignore intellij goland project files

    • Added list alias to ls command

    Description

    This pull request adds the list alias to the ls command so that users can use kure [ls | entries | list] interchangeably.

    Looks like some tests are failing but I don't believe it's related to my changes, considering my chages are so minor.

    opened by brittonhayes 1
  • Ctrl +d in kure session create a loop

    Ctrl +d in kure session create a loop

    Hello, I am testing Kure (really promising) under Linux (Ubuntu 20.04). I have an issue when i try to quit the session with ctrl d, it looks that i create a loop. (the help message over and over). Thanks

    opened by fdurand 1
  • Using nonce for dst in call to Seal

    Using nonce for dst in call to Seal

    Hi,

    On https://github.com/GGP1/kure/blob/ad75a75514bc32646617e335844a4b7758d38deb/crypt/crypt.go#L53 it seems odd to use nonce as dst in AEAD.Seal(). It appears that in Seal sliceForAppend is called which increases the size of dst if it is not large enough for the result. If it increases the size, when it gets to the deriveCounter call, it will take the wrong branch and not use the intended counter calculation, see https://golang.org/src/crypto/cipher/gcm.go?s=3384:3423#L397

    I'd suggest creating a new slice for dst in the call to Seal.

    opened by jcline 1
  • Help see I can't delete items from the list

    Help see I can't delete items from the list

    What version of Kure are you using?

    Screenshot_20220531_213204_com termux

    Does this issue reproduce with the latest release?

    It seems that the latest version is used, and I have never encountered this problem before.

    What operating system and processor architecture are you using?

    android termux arm64

    What did you do?

    I created a new secret and modified it again. It was during the modification that I added one or two spaces after the test. I felt that there were too many spaces, so I deleted one and continued to enter a few characters after. After the update, I can see it in the list, but I can't delete it, I don't know why

    What did you expect to see?

    I want to delete it, but it says there is no record

    What did you see instead?

    Screenshot_20220531_212146_com termux

    opened by xp12047 0
  • it command - No options to select from

    it command - No options to select from

    What version of Kure are you using?

    v0.5.0

    Does this issue reproduce with the latest release?

    Yes

    What did you do?

    kure it -> file -> cat
    # or
    kure it -> file -> mv
    

    What did you expect to see?

    A list of the files names

    What did you see instead?

    error: please provide options to select from

    bug 
    opened by GGP1 0
  • Upgrades

    Upgrades

    • 9159369 Upgraded dependencies
    • af37262 Added warning to restore command's description
    • 220c91c Disabled cobra (now default) completion command
    • 605121e Replaced config separator literal strings with a struct field
    • 1d2eb00 Tree string formatting changes
    • fef48d1 Updated build target tags
    opened by GGP1 0
Releases(v0.7.2)
Owner
Gastón Palomeque
Gastón Palomeque
A CLI password manager written in Go

vlt A CLI password vault written in Go vlt is a command line tool for storing passwords in encrypted files. Files are stored on a per-user basis in $H

Michael Green 1 Oct 23, 2021
Go-file-downloader-ftctl - A file downloader cli built using golang. Makes use of cobra for building the cli and go concurrent feature to download files.

ftctl This is a file downloader cli written in Golang which uses the concurrent feature of go to download files. The cli is built using cobra. How to

Dipto Chakrabarty 2 Jan 2, 2022
Commandline Utility To Create Secure Password Hashes (scrypt / bcrypt / pbkdf2)

passhash Create Secure Password Hashes with different algorithms. I/O format is base64 conforming to RFC 4648 (also known as url safe base64 encoding)

Michael Gebetsroither 15 Jul 25, 2022
The slightly more awesome standard unix password manager for teams

gopass Introduction gopass is a password manager for the command line written in Go. It supports all major operating systems (Linux, MacOS, BSD) as we

Gopass 4.8k Oct 2, 2022
A simple command line functionality to convert your Kaspersky Password Manager exported file to CSV format

A simple command line functionality to convert your Kaspersky Password Manager exported file to CSV format

Vlad Plaiasu 7 Apr 20, 2022
painless task queue manager for shell commands with an intuitive cli interface (execute shell commands in distributed cloud-native queue manager).

EXEQ DOCS STILL IN PROGRESS. Execute shell commands in queues via cli or http interface. Features Simple intuitive tiny cli app. Modular queue backend

Mohammed Al Ashaal 12 Jan 29, 2022
cli tools for list all pages in logseq repo, marked with public or private

logseq-pages A cli tool for list all pages in logseq repo, marked with public or private. When I using logseq to build my knowledge base and publish p

null 3 Jun 14, 2022
A CLI based Downloader utilising Golang's concurrency feature.

Downloader CLI based downloader utilising the concurrency feature of Golang. Takes the download URL of the file from the user. Splits the files into s

Mohammad Warid 0 Nov 6, 2021
A rich tool for parsing flags and values in pure Golang

A rich tool for parsing flags and values in pure Golang. No additional library is required and you can use everywhere.

ALi.w 14 Jan 25, 2022
Terminal UI library with rich, interactive widgets — written in Golang

Rich Interactive Widgets for Terminal UIs This Go package provides commonly needed components for terminal based user interfaces. Among these componen

rivo 7.5k Oct 2, 2022
Mass download all github repositories(public & private) of an organization, ideally in a few seconds.

Git Mass Mass download all github repositories(public & private) of an organization, ideally in a few seconds. Writing this as a simple bash script wo

Nithin Jois 0 Dec 27, 2021
Moldy CLI the best project starter and manager of the world

You don't know how to start your project ... you want to help other people know your tool or language. Use Moldy! the best helper to start your project

Moldy Community 24 Aug 22, 2022
Declarative CLI Version manager. Support Lazy Install and Sharable configuration mechanism named Registry. Switch versions seamlessly

aqua Declarative CLI Version manager. Support Lazy Install and Sharable configuration mechanism named Registry. Switch versions seamlessly. Index Slid

Shunsuke Suzuki 197 Sep 27, 2022
CLI todo manager for iCalendar files.

tdx tdx is a todo manager for iCalendar files. It is designed to work with Vdirsyncer and expects to operate in its storage format. iCalendar-compatib

Gadzhi Kharkharov 9 Jul 25, 2022
A simple CLI tool that outputs the history of connections to Amazon EC2 instances using AWS Session Manager.

ssmh This is a simple CLI tool that outputs the history of connections to Amazon EC2 instances using AWS Session Manager. Installation brew install mi

Yoshihiro Ito 0 Dec 10, 2021
🐉 BLAZINGLY FAST CLI plugin manager for (neo)vim

viper BLAZINGLY FAST CLI plugin manager for (neo)vim. Usage Viper does all the nice and basic things you'd expect from a (neo)vim plugin manager, and

Alexander Goussas 14 Jun 9, 2022
Fast, secure, efficient backup program

Introduction restic is a backup program that is fast, efficient and secure. It supports the three major operating systems (Linux, macOS, Windows) and

The restic backup program 18.1k Sep 25, 2022
Upterm is an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels.

Upterm is an open-source solution for sharing terminal sessions instantly over the public internet via secure tunnels.

Owen Ou 513 Sep 19, 2022