radicle-tui

Crates.ioradicle-tui
lib.rsradicle-tui
version0.7.0
created_at2024-06-10 10:32:26.84168+00
updated_at2026-01-22 13:17:18.689435+00
descriptionRadicle terminal user interface
homepagehttps://radicle.xyz
repositoryhttps://app.radicle.xyz/nodes/seed.radicle.xyz/rad:z39mP9rQAaGmERfUMPULfPUi473tY
max_upload_size
id1266934
size1,259,741
erikli (erak)

documentation

README

Screenshot

radicle-tui

radicle-tui provides various terminal user interfaces for interacting with the Radicle code forge. It also exposes the application framework they were built with.

Table of Contents

  1. Getting Started
  2. Build with radicle-tui
  3. Contributing
  4. Contact
  5. License

Getting started

Installation

Requirements

  • Linux or Unix based operating system.
  • Git 2.34 or later
  • OpenSSH 9.1 or later with ssh-agent

From source

Note: Requires the Rust toolchain.

You can install the binary from source, by running the following commands from inside this repository:

cargo install --path . --force --locked

Or directly from our seed node:

cargo install --force --locked --git https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git

This will install rad-tui. All available commands can be shown by running rad-tui --help.

Usage

This crate provides a binary called rad-tui which can be used as a drop-in replacement for rad. It maps known commands and operations to internal ones, running the corresponding app, e.g.

rad-tui patch

runs the patch list app and calls rad with the operation and id selected. Commands or operations not known to rad-tui will be forwarded to rad, e.g. the following just calls rad node:

rad-tui node

The default forwarding behaviour can be overridden with a flag, e.g.

rad-tui help --no-forward

runs the internal help command instead of forwarding to rad help.

Using a shell alias

In order to make the CLI integration opaque, a shell alias can be used:

alias rad="rad-tui"

CLI integration via JSON

The apps are designed to be modular and could also be integrated with existing CLI tooling. The binary is can be called and its output collected and processed, e.g.

rad-tui patch list --json

runs the patch list app and return a JSON object specifying the operation and id selected:

{ "operation": "show", "ids": ["546443226b300484a97a2b2d7c7000af6e8169ba"], args:[] }

Other installation methods

Nix

There is a flake.nix present in the repository. This means that for development, it should be as simple as using direnv and having the following .envrc file:

# .envrc
use flake

For using the binary in a NixOS, in your flake.nix you can add one of the following to the inputs set:

inputs = {
    # Replace <Tag> with the specific tag to build
    radicle-tui = {
        url = "git+https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git?tag=<Tag>";
    }
}
inputs = {
    # Replace <Commit SHA> with the specific commit to build
    rad-tui = {
        url = "git+https://seed.radicle.xyz/z39mP9rQAaGmERfUMPULfPUi473tY.git?rev=<Commit SHA>";
    }
}

Then in your home.nix you can add:

home.packages = [
  inputs.radicle-tui.packages.${system}.default
];

Build with radicle-tui

The library portion of this crate is a framework that is the foundation for all radicle-tui binaries. Although it evolved from the work on Radicle-specific applications and is far from being complete, it can serve as a general purpose framework to build applications on top already.

Find out more about the framework.

Note: The framework is under heavy development and is missing some common low-level widgets. These will be added where needed by the radicle-tui binaries.

Example

use anyhow::Result;

use ratatui::layout::Position;
use ratatui::{Frame, Viewport};

use radicle_tui as tui;

use tui::event::Key;
use tui::store;
use tui::task::EmptyProcessors;
use tui::ui::theme::Theme;
use tui::ui::widget::{Borders, Window};
use tui::ui::{Context, Show};
use tui::{Channel, Exit};

#[derive(Clone, Debug)]
struct App {
    hello: String,
}

#[derive(Clone, Debug)]
enum Message {
    Quit,
}

impl store::Update<Message> for App {
    type Return = ();

    fn update(&mut self, message: Message) -> Option<tui::Exit<()>> {
        match message {
            Message::Quit => Some(Exit { value: None }),
        }
    }
}

impl Show<Message> for App {
    fn show(&self, ctx: &Context<Message>, frame: &mut Frame) -> Result<()> {
        Window::default().show(ctx, Theme::default(), |ui| {
            ui.text_view(
                frame,
                self.hello.clone(),
                &mut Position::default(),
                Some(Borders::None),
            );

            if ui.has_input(|key| key == Key::Char('q')) {
                ui.send_message(Message::Quit);
            }
        });

        Ok(())
    }
}

#[tokio::main]
pub async fn main() -> Result<()> {
    let app = App {
        hello: "Hello World!".to_string(),
    };

    tui::im(
        app,
        Viewport::default(),
        Channel::default(),
        EmptyProcessors::new(),
    )
    .await?;

    Ok(())
}

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have any suggestions that would make this better, please clone the repo and open a patch. You can also simply open an issue with the label "enhancement".

License

radicle-tui is distributed under the terms of both the MIT license and the Apache License (Version 2.0).

See LICENSE-APACHE and LICENSE-MIT for details.

Contact

Please get in touch on Zulip.

Acknowledgments

Parts of this project rely on or were heavily inspired by some great open source projects. So we'd like to thank:

Commit count: 0

cargo fmt