TermPair lets developers securely share and control terminals in real timeπŸ”’

Overview

View and control remote terminals from your browser with end-to-end encryption

Documentation: https://cs01.github.io/termpair

Source Code: https://github.com/cs01/termpair

Try It: https://grassfedcode.com/termpair

PyPI version

What is TermPair?

TermPair lets developers securely share and control terminals in real time.

Usage

Start the TermPair server with termpair serve, or use the one already running at https://grassfedcode.com/termpair.

> termpair serve --port 8000
INFO:     Started server process [25289]
INFO:     Waiting for application startup.
INFO:     Application startup complete.
INFO:     Uvicorn running on http://localhost:8000 (Press CTRL+C to quit)
INFO:     ('127.0.0.1', 51924) - "WebSocket /connect_to_terminal" [accepted]

Then share your terminal by running termpair share:

> termpair share --port 8000
--------------------------------------------------------------------------------
Connection established with end-to-end encryption πŸ”’
Sharing '/bin/bash' at

http://localhost:8000/?terminal_id=fd96c0f84adc6be776872950e19caecc#GyMlK2LLTqvoyTNzJ+qwLg==

Type 'exit' or close terminal to stop sharing.
--------------------------------------------------------------------------------

You can share that URL with whoever you want. Note that anyone that has it can view and possibly control your terminal.

The server multicasts terminal output to all browsers that connect to the session.

Security

TermPair uses 128 bit end-to-end encryption for all terminal input and output.

The browser must be running in a secure context. This typically means running on localhost, or with secure http traffic (https).

How it Works

TermPair consists of three pieces:

  1. terminal client
  2. server
  3. browser client(s)

First, the termpair server is started (termpair serve). The server acts as a router that blindly forwards encrypted data between TermPair terminal clients and connected browsers.

It listens for termpair websocket connections from unix terminal clients, and maintains a mapping to any connected browsers.

Before the TermPair client sends terminal output to the server, it encrypts it using a secret key so the server cannot read it. The server forwards that data to connected browsers. When the browsers receive the data, they use the secret key to decrypt and display the terminal output. The browser obtains the secret key via a part of the url that is not sent to the server.

Likewise, when a browser sends input to the terminal, it is encrypted in the browser, forwarded from the server to the terminal, then decrypted in the terminal by TermPair, and finally written to the terminal's input.

Run With Latest Version

Use pipx to run the latest version without installing:

Serve:

> pipx run termpair serve

Then share:

> pipx run termpair share --open-browser

Note: pipx caches installations for a few days. To ignore the cache and force a fresh installation, use pipx run --no-cache termpair ....

Installation

You can install using pipx or pip:

> pipx install termpair

or

> pip install termpair

CLI API

> termpair --help
usage: termpair [-h] [--version] {share,serve} ...

View and control remote terminals from your browser

positional arguments:
  {share,serve}

optional arguments:
  -h, --help     show this help message and exit
  --version

To start the TermPair server:

> termpair serve --help
usage: termpair serve [-h] [--port PORT] [--host HOST] [--certfile CERTFILE]
                      [--keyfile KEYFILE]

Run termpair server to route messages between unix terminals and browsers. Run
this before connecting any clients. It is recommended to encrypt communication
by using SSL/TLS. To generate an SSL certificate and private key, run `openssl
req -newkey rsa:2048 -nodes -keyout host.key -x509 -days 365 -out host.crt`.
To skip questions and use defaults, add the `-batch` flag. You can ignore
warnings about self-signed certificates since you know you just made it. Then
use them, pass the '--certfile' and '--keyfile' arguments.

optional arguments:
  -h, --help            show this help message and exit
  --port PORT, -p PORT  Port to run the server on (default: 8000)
  --host HOST           Host to run the server on (0.0.0.0 exposes publicly)
                        (default: localhost)
  --certfile CERTFILE, -c CERTFILE
                        Path to SSL certificate file (commonly .crt extension)
                        (default: None)
  --keyfile KEYFILE, -k KEYFILE
                        Path to SSL private key .key file (commonly .key
                        extension) (default: None)

To share a terminal using the TermPair client:

> termpair share --help
usage: termpair share [-h] [--cmd CMD] [--port PORT] [--host HOST]
                      [--no-browser-control] [--open-browser]

Share your terminal session with one or more browsers. A termpair server must
be running before using this command.

optional arguments:
  -h, --help            show this help message and exit
  --cmd CMD             The command to run in this TermPair session. Defaults
                        to the SHELL environment variable (default: /bin/bash)
  --port PORT, -p PORT  port server is running on (default: None)
  --host HOST           host server is running on (default: http://localhost)
  --no-browser-control, -n
                        Do not allow browsers to control your terminal
                        remotely (default: False)
  --open-browser, -b    Open a browser tab to the terminal after you start
                        sharing (default: False)

System Requirements

Python: 3.6+

Operating System:

  • To view/control from the browser: All operating systems are supported.
  • To run the server, termpair serve: Tested on Linux. Should work on macOS. Might work on Windows.
  • To share your terminal, termpair share: Tested on Linux. Should work on macOS. Probably doesn't work on Windows.
Comments
  • Add contributing guidelines

    Add contributing guidelines

    Just cloned the repo and set it up so I thought I'd write down the process I took in a CONTRIBUTING.md so that it can be used by other people as well. :-)

    opened by florimondmanca 8
  • Secret encryption  key is not valid

    Secret encryption key is not valid

    Describe the bug I follow the instruction to run the programe , but at the last step , it says : secret encryption key is not valid ... could you give me some advise?

    image

    opened by dualven 5
  • --version commandline parsing error

    --version commandline parsing error

    Thanks for TermPair, it's an amazing project!

    Describe the bug

    $ termpair --version
    usage: termpair [-h] [--version] {share,serve} ...
    termpair: error: the following arguments are required: command
    

    termpair doesn't parse correctly --version expecting other arguments and options

    I've installed the latest version with pip, with python 3.9

    good first issue 
    opened by antenore 5
  • Cryptographic suggestions

    Cryptographic suggestions

    Termpair looks awesome and personally I am excited to start using it! I came to it via a thread on HN ... https://news.ycombinator.com/item?id=27338479 . That thread also includes some dissection of the cryptography in TermPair, some of the thoughts there are good, and some are off base. This issue is a summary of my own observations/suggestions in case they are interesting and useful:

    1. Termpair could use a key agreement protocol. Termpair is designed to avoid revealing keys to the server by encoding the key in the anchor fragment of the URL, which a server never sees. This is clever, but a server could still MITM by serving its own malicious HTML. It's actually very possible for two endpoints to share a key in a MITM proof way ... use a key agreement protocol such as ECDH. It's somewhat magical, but they can exchange material and agree a key without anyone in the middle ever being able to figure out what it is. There's some details to get right, like it's useful to have the ECDH be signed and verified by the parties involved, but it's all pretty straightforward.

    2. Keystroke timing is a practical attack. One of the perils of interactive terminal type applications is that human keystrokes can be timed and this timing can reveal what keys are being pressed. It's important to make sure that when a terminal is line-buffered, that the keys aren't sent one by one, but that the whole buffered line is encrypted and sent in one pass. Password inputs (like ssh and sudo) are expected to use line-buffering to mitigate keystroke timing issues. Additionally, it's a good idea to pad a line-buffered input up to a fixed size - this avoid leaking the length of the password entered.

    3. AES-GCM can safely use counters as nonces. This came from the HN thread, but they have a point; it's ok, and actually better to use the message count as the nonce for AES-GCM and it avoids the small odds of collisions occurring.

    4. It's good to use different keys in different directions. It's also a good idea to use a different encryption key in the direction of A to B than from B to A. These keys can be derived from a shared secret using HKDF.

    Some of these may be bewildering, but I'm happy to answer questions. Again, Termpair looks awesome and I don't mean these suggestions as some kind of ding!

    opened by colmmacc 5
  • Improve error message if server is not running

    Improve error message if server is not running

    Traceback (most recent call last): File "/Users/david/.local/bin/termpair", line 8, in sys.exit(main()) File "/Users/david/.local/pipx/venvs/termpair/lib/python3.9/site-packages/termpair/main.py", line 109, in main asyncio.get_event_loop().run_until_complete( File "/usr/local/Cellar/[email protected]/3.9.5/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete return future.result() File "/Users/david/.local/pipx/venvs/termpair/lib/python3.9/site-packages/termpair/share.py", line 231, in broadcast_terminal async with websockets.connect(ws_endpoint, ssl=ssl_context) as ws: File "/Users/david/.local/pipx/venvs/termpair/lib/python3.9/site-packages/websockets/client.py", line 517, in aenter return await self File "/Users/david/.local/pipx/venvs/termpair/lib/python3.9/site-packages/websockets/client.py", line 535, in await_impl transport, protocol = await self._create_connection() File "/usr/local/Cellar/[email protected]/3.9.5/Frameworks/Python.framework/Versions/3.9/lib/python3.9/asyncio/base_events.py", line 1064, in create_connection raise OSError('Multiple exceptions: {}'.format( OSError: Multiple exceptions: [Errno 61] Connect call failed ('::1', 8000, 0, 0), [Errno 61] Connect call failed ('127.0.0.1', 8000)

    opened by wenchengxucool 4
  • allow frontend to be served statically

    allow frontend to be served statically

    This implements a static frontend as suggested in #36.

    background

    Currently, the browser contains decrypted data and the encryption key. If the browser's JavaScript were modified to be malicious and a malicious server were created, it would be hard to detect.

    this pr

    This PR allows the backend to accept cross origin requests, and the frontend to be served statically on GitHub pages, Vercel, or a local static server, which can be manually built. The static page still routes the terminal traffic through a (potentially) untrusted server, but that is okay since the traffic is encrypted before going over the wire.

    Changes

    • Accept cross origin requests on backend
    • Create script to publish built frontend to https://cs01.github.io/termpair/connect/
    • Make UI to define url of TermPair server where encrypted terminal data should be sent via websocket
    • Also added UI to let regular server specify Terminal ID on the landing page instead of requiring it in the URL
    • Update docs
    opened by cs01 3
  • Unable to connect to session if not served by localhost

    Unable to connect to session if not served by localhost

    Hi,

    if I start the server with termpair serve --host 192.168.x.x --port 8000 it successfully binds to the correct interface.

    The shared session is successful initiated with termpair share --host "http://192.168.x.x/" --port 8000

    Browser opens session and server sends HTTP 200 ok (304 for png & js) for every request but the session is always in "connection-pending" state.

    If served/shared using localhost instead, it works without issue.

    Do I miss something here? Any help appreciated.

    opened by 0xphk 3
  • when i close the terminal ,the termpair still runs in backround ,but it is useless in this case; how could i run it in backgroud?

    when i close the terminal ,the termpair still runs in backround ,but it is useless in this case; how could i run it in backgroud?

    termpair share --host https://10.60.100.192 --port 8000 then it is ok to be used ,

    but when I close the terminal , the link like this: https://10.60.100.192:8000/?terminal_id=02453c7728c8cf7a49dc2cbc8df6c109#ATM+7fg7q2hxT3GRtNdeyQ== will lose the effect .

    opened by dualven 2
  • Trying to run termpair on LAN with SSL

    Trying to run termpair on LAN with SSL

    Describe the bug Trying to launch termpair on on LAN (192.168.31.234 on my domestic network), not localhost (127.0.0.1) finishes with message on browser, that i can not use non-secure connection:

    termpair serve -p 8000 --host 192.168.31.234

    and on sharing window:

    termpair share -p 8000 --host 192.168.31.234

    When opening browser with link (which is HTTP) I get from sharing terminal I see next message:

    image

    I decided to run it on LAN, with --keyfile and --certificate options to make secure connection (it is going to set up "HTTPS", right?). So I created SSL certificate with openssl library. The key, certificate are located in /etc/httpd/httpscertificate/ folder . But when I try command:

    termpair serve -p 8000 --host 192.168.31.234 --certfile /etc/httpd/httpscertificate/192.168.31.234.crt --keyfile /etc/httpd/httpscertificate/192.168.31.234.key

    I receive an error:

    TermPair encountered an error. If you think this is a bug, it can be reported at https://github.com/cs01/termpair/issues

    Traceback (most recent call last): File "/home/ooolledj/.local/lib/python3.8/site-packages/termpair/main.py", line 140, in main run_command(args) File "/home/ooolledj/.local/lib/python3.8/site-packages/termpair/main.py", line 124, in run_command uvicorn.run( File "/home/ooolledj/.local/lib/python3.8/site-packages/uvicorn/main.py", line 393, in run server.run() File "/home/ooolledj/.local/lib/python3.8/site-packages/uvicorn/server.py", line 50, in run loop.run_until_complete(self.serve(sockets=sockets)) File "uvloop/loop.pyx", line 1494, in uvloop.loop.Loop.run_until_complete File "/home/ooolledj/.local/lib/python3.8/site-packages/uvicorn/server.py", line 57, in serve config.load() File "/home/ooolledj/.local/lib/python3.8/site-packages/uvicorn/config.py", line 284, in load self.ssl = create_ssl_context( File "/home/ooolledj/.local/lib/python3.8/site-packages/uvicorn/config.py", line 115, in create_ssl_context ctx.load_cert_chain(certfile, keyfile, get_password) PermissionError: [Errno 13] Permission denied

    Sudo command does not help with it

    sudo: termpair: command not found

    I created RSA key and SSL certificate with this guide: https://www.rosehosting.com/blog/how-to-generate-a-self-signed-ssl-certificate-on-linux/ Then I just set path to files them with --keyfile and --certfile options in termpair serve.

    Expected behavior It should accept my .key and .crt files and run termpair on LAN ip-address, which with I can use termpair share for example on my mobile phone and see and type commands

    I FOUND THE SOLUTION. UPDATE: I thought it happens because i can not input certificate password and it does not let me use It. Truly, while writing report I tried to change access to .key file:

    sudo chmod a+r /etc/httpd/httpscertificate/192.168.31.234.key

    After that all my termpair commands with serve, share and --keyfile, --certfile options run perfectly (you can see HTTPS connection is established):

    bkm

    Now the question: how can I protect my .key file from unauthorized access and still be available to run termpair on HTTPS without using chmod a+r on .key file?

    opened by OOOlledj 2
  • Is there an option for read-only sessions?

    Is there an option for read-only sessions?

    The web interface has a green light indicating that you can type, which implies there's an alternative, but I can't find a way to control that. Is there an option along the lines of termpair share --readonly that I just haven't found?

    Perhaps a useful related feature could start the session in read only mode, but a viewer could enter a password to enable typing? termpair share --readonly --password=$foo?

    opened by DaelonSuzuka 2
  • Bump eventsource from 1.1.0 to 1.1.1 in /termpair/frontend_src

    Bump eventsource from 1.1.0 to 1.1.1 in /termpair/frontend_src

    Bumps eventsource from 1.1.0 to 1.1.1.

    Changelog

    Sourced from eventsource's changelog.

    1.1.1

    • Do not include authorization and cookie headers on redirect to different origin (#273 Espen Hovlandsdal)
    Commits

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
    • @dependabot use these labels will set the current labels as the default for future PRs for this repo and language
    • @dependabot use these reviewers will set the current reviewers as the default for future PRs for this repo and language
    • @dependabot use these assignees will set the current assignees as the default for future PRs for this repo and language
    • @dependabot use this milestone will set the current milestone as the default for future PRs for this repo and language

    You can disable automated security fix PRs for this repo from the Security Alerts page.

    dependencies javascript 
    opened by dependabot[bot] 1
  • About ModuleNotFoundError in windows

    About ModuleNotFoundError in windows

    When I'm using this project in windows ,I found that it cannot work because of there is no module "termios" supported in Windows and I have no idea on how to fix the problem. Is there anyone can make a fix on Windows? It's really helpful on changing it to useful on Windows.Thanks!!!

    help wanted 
    opened by MoonTracer732 2
Releases(v0.3.1.5)
  • v0.3.1.5(Jun 22, 2022)

    What's Changed

    • Bump tmpl from 1.0.4 to 1.0.5 in /termpair/frontend_src by @dependabot in https://github.com/cs01/termpair/pull/91
    • Bump follow-redirects from 1.14.2 to 1.14.7 in /termpair/frontend_src by @dependabot in https://github.com/cs01/termpair/pull/93
    • fix python 3.10 bug by updating dependencies by @cs01 in https://github.com/cs01/termpair/pull/104
    • update pex build command by @cs01 in https://github.com/cs01/termpair/pull/105
    • add pre commit file and run pre-commit run --all-files by @cs01 in https://github.com/cs01/termpair/pull/106

    Full Changelog: https://github.com/cs01/termpair/compare/v0.3.1.4...v0.3.1.5

    Source code(tar.gz)
    Source code(zip)
    termpair_linux.zip(23.06 MB)
    termpair_mac.zip(9.70 MB)
  • v0.3.1.4(Sep 1, 2021)

  • v0.3.1.3(Aug 31, 2021)

  • v0.3.1.2(Aug 23, 2021)

  • v0.3.1.1(Aug 23, 2021)

  • v0.3.1.0(Aug 14, 2021)

  • v0.3.0.0(Aug 10, 2021)

    Breaking API Changes In this version, TermPair clients from previous versions cannot connect to this TermPair server

    • Use new key sharing scheme: Different keys used in different directions; keys rotated
    • [bugfix] Terminal dimensions in browser match upon initial connection, instead of after resizing
    • Allow static site to route terminal traffic through other server. If static site is detected, user can enter the terminal id and server url in the browser UI.
    • Allow Terminal ID and initial encryption key to be entered on landing page
    • Add additional random string to each encrypted message
    • Display version in webpage
    • Add troubleshooting instructions to webpage
    • Rename --no-browser-control argument of termpair share to --read-only
    Source code(tar.gz)
    Source code(zip)
    termpair-linux(20.89 MB)
    termpair-mac(8.08 MB)
  • v0.2.0.0(Jul 20, 2021)

    0.2.0.0

    • Add ability to copy+paste using keystrokes (copy with ctrl+shift+c or ctrl+shift+x, and paste with ctrl+shift+v)
    • Add a status bar to the bottom of the page
    • Show terminal dimensions in bottom status bar
    • Add toasts to notify user of various events
    • Fix bug where connected browsers do not have their websocket connection closed when terminal closes, which makes it look like the terminal is still connected when it is not.
    • Improve error messages, in particular if there is no server running
    • Fixed bug where websocket connection is briefly accepted regardless of whether a valid terminal id is provided to /terminal/{terminal_id}. Instead of returning a JSON object with the TermPair version, a 404 error is now returned.
    • [dev] migrate codebase to typescript
    • [dev] use React functional component instead of class component for main application
    Source code(tar.gz)
    Source code(zip)
  • v0.1.1.1(Jun 2, 2021)

  • 0.1.1.0(Jun 2, 2021)

    0.1.1.0

    • Ensure error message is printed to browser's terminal if site is not served in a secure context (#39)
    • Make default TermPair terminal client port 8000 to match default server port (#38)
    • Always display port to connect to in browser's connection instructions
    Source code(tar.gz)
    Source code(zip)
  • 0.0.1.3(Feb 12, 2020)

  • 0.0.1.2(Feb 12, 2020)

Owner
Chad Smith
Creator of gdbgui, pipx, and various tools. Occasional blogger https://medium.com/@grassfedcode
Chad Smith
Simple command line tool to train and deploy your machine learning models with AWS SageMaker

metamaker Simple command line tool to train and deploy your machine learning models with AWS SageMaker Features metamaker enables you to: Build a dock

Yasuhiro Yamaguchi 5 Jan 09, 2022
gcptree - Like the unix tree command but for GCP Org Heirarchy

gcptree Like the unix tree command but for GCP Org Heirarchy. For a note on coloring, the org node is green, folders and blue, and projects that are n

Ryan Canty 25 Sep 06, 2022
split-manga-pages: a command line utility written in Python that converts your double-page layout manga to single-page layout.

split-manga-pages split-manga-pages is a command line utility written in Python that converts your double-page layout manga (or any images in double p

Christoffer Aakre 3 May 24, 2022
A command line tool to hide and reveal information inside images (works for both PNGs and JPGs)

Imgrerite A command line tool to hide and reveal information inside images (works for both PNGs and JPGs) Dependencies Python 3 Git Most of the Linux

Jigyasu 10 Jul 27, 2022
A tool to manage the study of courses at the university.

todo-cli A tool to manage the study of courses at the university

Quentin 6 Aug 01, 2022
A collection of command-line interface games written in python

Command Line Interface Python Games Collection of some starter python game projects for beginners How to play these games Clone this repository git cl

Paras Gupta 7 Jun 06, 2022
Pyrdle - Play Wordle in the CLI. Write an algorithm to play Wordle for you. Ruin all of the fun you've been having

Pyrdle - Play Wordle in the CLI. Write an algorithm to play Wordle for you. Ruin all of the fun you've been having

Charles Tapley Hoyt 11 Feb 11, 2022
pypyr task-runner cli & api for automation pipelines.

pypyr task-runner cli & api for automation pipelines. Automate anything by combining commands, different scripts in different languages & applications into one pipeline process.

pypyr 471 Dec 15, 2022
ddgr is a cmdline utility to search DuckDuckGo (html version) from the terminal

ddgr is a cmdline utility to search DuckDuckGo (html version) from the terminal. While googler is extremely popular among cmdline users, in many forums the need of a similar utility for privacy-aware

PiΓ±a Colada 2.5k Dec 25, 2022
A CLI tool to disable and enable security standards controls in AWS Security Hub

Security Hub Controls CLI A CLI tool to disable and enable security standards controls in AWS Security Hub. It is designed to work together with AWS S

AWS Samples 4 Nov 14, 2022
dotfilery, configuration, environment settings, automation, etc.

β”Œβ”¬β”β”Œβ”€β”β”Œβ”€β”β”Œβ”€β”β”¬ β”¬β”Œβ”¬β”β”¬ β”¬β”¬β”Œβ”€β” β”‚β”‚β”‚β”œβ”€ β”‚ β”¬β”œβ”€β”€β”‚ β”‚ β”‚ β”œβ”€β”€β”‚β”‚ :: bits & bobs, dots & things. β”΄ β”΄β””β”€β”˜β””β”€β”˜β”΄ β”΄β”΄β”€β”˜β”΄ β”΄ β”΄ β”΄β”΄β””β”€β”˜ @megalithic πŸš€ Instal

Seth Messer 89 Dec 25, 2022
Chat with Rem in Terminal!

Chat with Rem in Terminal!

bariscodefx 1 Dec 19, 2021
Random scripts and other bits for interacting with the SpaceX Starlink user terminal hardware

starlink-grpc-tools This repository has a handful of tools for interacting with the gRPC service implemented on the Starlink user terminal (AKA "the d

270 Dec 29, 2022
Gamma ion pump QPC ethernet Python library & CLI utility

Unofficial Gamma ion pump ethernet control CLI utility and library This is a mini Python 3 library and utility that exposes some of the functions of t

2 Jul 18, 2022
Quo is a Python based toolkit for writing Command-Line Interface(CLI) applications.

Quo is a Python based toolkit for writing Command-Line Interface(CLI) applications. Quo is making headway towards composing speedy and orderly CLI applications while forestalling any disappointments

Secretum Inc. 16 Oct 15, 2022
A Bot Which Send Automatically Commands To Karuta Hub to Gain it's Currency

A Bot Which Send Automatically Commands To Karuta Hub to Gain it's Currency

HarshalWaykole 1 Feb 09, 2022
Get latest astronomy job and rumor news in your command line

astrojobs Tired of checking the AAS job register and astro rumor mill for job news? Get the latest updates in the command line! astrojobs automaticall

Philip Mocz 19 Jul 20, 2022
Generate an ASCII Art from keyword put in the cli

ascii-art-generator-cli Generate an ASCII Art from keyword put in the cli Install git clone https://github.com/Nathanlauga/ascii-art-generator-cli cd

Nathan Lauga 1 Nov 14, 2021
ctree - command line christmas tree

ctree ctree - command line christmas tree It is small python script that prints a christmas tree in terminal. It is colourful and always gives you a d

15 Aug 15, 2022
A simple command line tool written in python to manage a to-do list

A simple command line tool written in python to manage a to-do list Dependencies: python Commands: todolist (-a | --add) [(-p | --priority)] [(-l | --

edwloef 0 Nov 02, 2021