kurv 0.1.0

A process manager to daemonize commands and programs. Inspired by pm2, but lightweight and not as featureful.
Documentation
<p align="center"><img src=".github/icon-logo-h64.svg" height="128"></p>

<br>
<br>
<br>

<p align="center">๐ค๐ฎ๐ซ๐ฏ is a process manager, mainly for Node.js and Python applications. It's written in <code>Rust</code>. It daemonizes your apps so that they can run in the background. It also restarts them if they crash.
</p>

<p align="center"><img align="center" alt="Crates.io Version" src="https://img.shields.io/crates/v/kurv?style=flat-square&color=%2318181b&link=https%3A%2F%2Fcrates.io%2Fcrates%2Fkurv"></p>

<p align="center"><a href="https://kurv.lucode.dev" target="_blank">Docs</a> โ€ข <a href="https://crates.io/crates/kurv" target="_blank">Crate</a> โ€ข <a href="https://github.com/lucas-labs/kurv/tree/master?tab=readme-ov-file#readme" target="_blank">Readme</a></p>

<br>
<br>
<br>

## Why ๐ค๐ฎ๐ซ๐ฏ?

So, why the name ๐ค๐ฎ๐ซ๐ฏ? Well, it means "basket" in many languages I don't speak, like Norwegian (but it sounded cool ๐Ÿ˜„). Think of ๐ค๐ฎ๐ซ๐ฏ as a basket for your apps. In kurv, we call each deployed app as an `egg`. So, let's go and collect some eggs ๐Ÿฅš in your basket ๐Ÿงบ.

## Installation

> [!NOTE]
> ๐ค๐ฎ๐ซ๐ฏ can run either as a server or as a CLI client, using the same binary.
>
> The server is responsible for managing the eggs, while the client is used to interact with the server and tell it what to do or ask it for information.

### Download binaries

Download the latest release [from GitHub](https://github.com/lucas-labs/kurv/releases).

### crates.io

You can also install it from [crates.io](https://crates.io/crates/kurv) using `cargo`:

```bash
cargo install kurv
```

## Usage

![kurv usage](.github/kurv.gif)

### Start the server

To get the server rolling, type:

```bash
kurv server
```

> [!IMPORTANT]
>
> -   ๐ค๐ฎ๐ซ๐ฏ will create a file called `.kurv` where it will store the current
>     state of the server. The file will be created in the same directory where
>     the binary is located or in the path specified by the `KURV_HOME_KEY`
>     environment variable.
>
> -   since ๐ค๐ฎ๐ซ๐ฏ can be used both as a server and as a client, if you want
>     to run it as a server, you need to set the `KURV_SERVER` environment
>     to `true`. This is just a safety measure to prevent you from running
>     the server when you actually want to run the client.
>     To bypass this, you can use the `--force` flag (`kurv server --force`)

### Collect some ๐Ÿฅš

To deploy/start/daemonize an app (collect an egg), do:

```bash
kurv collect <egg-cfg-path>
```

The path should point to a YAML file that contains the configuration for the egg.

It should look something like this:

```yaml title="myegg.kurv"
name: fastapi # the name of the egg / should be unique
command: poetry # the command/program to run
args: # the arguments to pass to the command
    - run
    - serve
cwd: /home/user/my-fastapi-app # the working directory in which the command will be run
env: # the environment variables to pass to the command
    FASTAPI_PORT: 8080
```

This will run the command `poetry run serve` in `/home/user/my-fastapi-app` with the environment variable `FASTAPI_PORT` set to `8080`.

If for some reason, the command/program crashes or exits, ๐ค๐ฎ๐ซ๐ฏ will revive it!

### Show me my eggs

If you want a summary of the current state of your eggs, run:

```zsh
$ kurv list

๐Ÿฅš eggs snapshot

โ•ญโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”ฌโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฎ
โ”‚ # โ”‚ pid   โ”‚ name      โ”‚ status  โ”‚ โ†บ โ”‚ uptime โ”‚
โ”œโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”ผโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ค
โ”‚ 1 โ”‚ 35824 โ”‚ fastapi   โ”‚ running โ”‚ 0 โ”‚   1s   โ”‚
โ”‚ 2 โ”‚ 0     โ”‚ fastapi-2 โ”‚ stopped โ”‚ 0 โ”‚   -    โ”‚
โ•ฐโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”ดโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ•ฏ
```

For details on a specific egg:

```sh
$ kurv egg <egg:name|id|pid>
```

This will show you the egg's configuration, process details, etc.

### Stop an egg

To halt an egg without removing it:

```sh
$ kurv stop <egg:name|id|pid>
```

This will stop the process but keep its configuration in the basket in case
you want to start it again later.

### Remove an egg

To actually remove an egg, run:

```sh
$ kurv remove <egg:name|id|pid>
```

It will stop the process and remove the egg from the basket.

### Restart

If you need the process to be restarted, run:

```sh
$ kurv restart <egg:name|id|pid>
```

### ๐Ÿ”Œ Plugins

Want to extend ๐ค๐ฎ๐ซ๐ฏ with your own tools? Kurv support plugins! They're special eggs that ๐ค๐ฎ๐ซ๐ฏ automatically discovers and manages.

#### How it works

1. Drop an executable starting with `kurv-` in `<KURV_HOME>/plugins/`
2. Make it respond to `--kurv-cfg` with JSON config, same as an egg config
3. Restart ๐ค๐ฎ๐ซ๐ฏ server
4. That's it! The plugin is now running ๐ŸŽ‰

**View your plugins:**

```sh
$ kurv plugins # list all plugins
```

Plugins can be started, stopped, and restarted just like regular eggs, but they can't be removed (stop kurv and delete the executable instead).

### To do list

๐ค๐ฎ๐ซ๐ฏ is still under development. Here are some of the things I'm planning to add:

-   [ ] Simple password protection
-   [ ] Scheduled egg runs: allow eggs to not be long-running processes, but instead run at
        specific times or intervals (cron-like). This might be implemented as a plugin "kurv-cron".
-   [ ] Remotely manage eggs
-   [ ] SSL support
-   [ ] More tests

#### Plugins / extensions

Since ๐ค๐ฎ๐ซ๐ฏ is a process manager, we can easily extend its functionality by adding
plugin eggs (simple eggs managed by ๐ค๐ฎ๐ซ๐ฏ itself that provide additional functionality).

Here are some ideas I have for plugins:

-   [ ] Web UI
-   [ ] Log Viewer (`kurv tail <egg>` (livestream) and `kurv logs <egg> --lines N` (last N lines))
-   [ ] Log Rotation

##### Plugin system improvements
-   [ ] Command-based plugins: allow plugins to register custom commands that can be run
        using `kurv <plugin-command> [args...]` (requires ability to register not-long-running
        eggs that run a command and exit, instead of being daemonized)

### Inspiration

#### pm2

Inspired by the robust process manager, [pm2](https://pm2.keymetrics.io/), my goal with ๐ค๐ฎ๐ซ๐ฏ was to create a lightweight alternative. Not that pm2 is a resource hog, but I found myself in a server with extremely limited resources. Plus, I was itching for an excuse to dive into Rust, and voila, ๐ค๐ฎ๐ซ๐ฏ was born.

#### eggsecutor

Derived from [eggsecutor](https://github.com/lucas-labs/kurv), ๐ค๐ฎ๐ซ๐ฏ adopted the whimsical term
"eggs" to represent deployed applications.

#### pueue

Insights from [pueue](https://github.com/Nukesor/pueue) were instrumental in helping me understand
how to manage processes in Rust.

<br><br>

---

With ๐Ÿง‰ from Argentina ๐Ÿ‡ฆ๐Ÿ‡ท