feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use crate::app_event::AppEvent;
|
|
|
|
|
|
use crate::chatwidget::ChatWidget;
|
|
|
|
|
|
use crate::git_warning_screen::GitWarningOutcome;
|
|
|
|
|
|
use crate::git_warning_screen::GitWarningScreen;
|
2025-04-25 12:01:52 -07:00
|
|
|
|
use crate::scroll_event_helper::ScrollEventHelper;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use crate::tui;
|
2025-04-27 21:47:50 -07:00
|
|
|
|
use codex_core::config::Config;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use codex_core::protocol::Event;
|
|
|
|
|
|
use codex_core::protocol::Op;
|
|
|
|
|
|
use color_eyre::eyre::Result;
|
|
|
|
|
|
use crossterm::event::KeyCode;
|
|
|
|
|
|
use crossterm::event::KeyEvent;
|
2025-04-25 12:01:52 -07:00
|
|
|
|
use crossterm::event::MouseEvent;
|
|
|
|
|
|
use crossterm::event::MouseEventKind;
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
use std::sync::mpsc::channel;
|
|
|
|
|
|
use std::sync::mpsc::Receiver;
|
|
|
|
|
|
use std::sync::mpsc::Sender;
|
|
|
|
|
|
|
|
|
|
|
|
/// Top‑level application state – which full‑screen view is currently active.
|
|
|
|
|
|
enum AppState {
|
|
|
|
|
|
/// The main chat UI is visible.
|
|
|
|
|
|
Chat,
|
|
|
|
|
|
/// The start‑up warning that recommends running codex inside a Git repo.
|
|
|
|
|
|
GitWarning { screen: GitWarningScreen },
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) struct App<'a> {
|
|
|
|
|
|
app_event_tx: Sender<AppEvent>,
|
|
|
|
|
|
app_event_rx: Receiver<AppEvent>,
|
|
|
|
|
|
chat_widget: ChatWidget<'a>,
|
|
|
|
|
|
app_state: AppState,
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl App<'_> {
|
|
|
|
|
|
pub(crate) fn new(
|
2025-04-27 21:47:50 -07:00
|
|
|
|
config: Config,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
initial_prompt: Option<String>,
|
|
|
|
|
|
show_git_warning: bool,
|
|
|
|
|
|
initial_images: Vec<std::path::PathBuf>,
|
|
|
|
|
|
) -> Self {
|
|
|
|
|
|
let (app_event_tx, app_event_rx) = channel();
|
2025-04-25 12:01:52 -07:00
|
|
|
|
let scroll_event_helper = ScrollEventHelper::new(app_event_tx.clone());
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
|
|
|
|
|
|
// Spawn a dedicated thread for reading the crossterm event loop and
|
|
|
|
|
|
// re-publishing the events as AppEvents, as appropriate.
|
|
|
|
|
|
{
|
|
|
|
|
|
let app_event_tx = app_event_tx.clone();
|
|
|
|
|
|
std::thread::spawn(move || {
|
|
|
|
|
|
while let Ok(event) = crossterm::event::read() {
|
|
|
|
|
|
let app_event = match event {
|
|
|
|
|
|
crossterm::event::Event::Key(key_event) => AppEvent::KeyEvent(key_event),
|
|
|
|
|
|
crossterm::event::Event::Resize(_, _) => AppEvent::Redraw,
|
2025-04-25 12:01:52 -07:00
|
|
|
|
crossterm::event::Event::Mouse(MouseEvent {
|
|
|
|
|
|
kind: MouseEventKind::ScrollUp,
|
|
|
|
|
|
..
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
scroll_event_helper.scroll_up();
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
crossterm::event::Event::Mouse(MouseEvent {
|
|
|
|
|
|
kind: MouseEventKind::ScrollDown,
|
|
|
|
|
|
..
|
|
|
|
|
|
}) => {
|
|
|
|
|
|
scroll_event_helper.scroll_down();
|
|
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
continue;
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
if let Err(e) = app_event_tx.send(app_event) {
|
|
|
|
|
|
tracing::error!("failed to send event: {e}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
let chat_widget = ChatWidget::new(
|
2025-04-27 21:47:50 -07:00
|
|
|
|
config,
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
app_event_tx.clone(),
|
|
|
|
|
|
initial_prompt.clone(),
|
|
|
|
|
|
initial_images,
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
let app_state = if show_git_warning {
|
|
|
|
|
|
AppState::GitWarning {
|
|
|
|
|
|
screen: GitWarningScreen::new(),
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
AppState::Chat
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
Self {
|
|
|
|
|
|
app_event_tx,
|
|
|
|
|
|
app_event_rx,
|
|
|
|
|
|
chat_widget,
|
|
|
|
|
|
app_state,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Clone of the internal event sender so external tasks (e.g. log bridge)
|
|
|
|
|
|
/// can inject `AppEvent`s.
|
|
|
|
|
|
pub fn event_sender(&self) -> Sender<AppEvent> {
|
|
|
|
|
|
self.app_event_tx.clone()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn run(&mut self, terminal: &mut tui::Tui) -> Result<()> {
|
|
|
|
|
|
// Insert an event to trigger the first render.
|
|
|
|
|
|
let app_event_tx = self.app_event_tx.clone();
|
|
|
|
|
|
app_event_tx.send(AppEvent::Redraw).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
while let Ok(event) = self.app_event_rx.recv() {
|
|
|
|
|
|
match event {
|
|
|
|
|
|
AppEvent::Redraw => {
|
|
|
|
|
|
self.draw_next_frame(terminal)?;
|
|
|
|
|
|
}
|
|
|
|
|
|
AppEvent::KeyEvent(key_event) => {
|
|
|
|
|
|
match key_event {
|
|
|
|
|
|
KeyEvent {
|
|
|
|
|
|
code: KeyCode::Char('c'),
|
|
|
|
|
|
modifiers: crossterm::event::KeyModifiers::CONTROL,
|
|
|
|
|
|
..
|
|
|
|
|
|
} => {
|
|
|
|
|
|
self.chat_widget.submit_op(Op::Interrupt);
|
|
|
|
|
|
}
|
|
|
|
|
|
KeyEvent {
|
|
|
|
|
|
code: KeyCode::Char('d'),
|
|
|
|
|
|
modifiers: crossterm::event::KeyModifiers::CONTROL,
|
|
|
|
|
|
..
|
|
|
|
|
|
} => {
|
|
|
|
|
|
self.app_event_tx.send(AppEvent::ExitRequest).unwrap();
|
|
|
|
|
|
}
|
|
|
|
|
|
_ => {
|
|
|
|
|
|
self.dispatch_key_event(key_event);
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
}
|
2025-04-25 12:01:52 -07:00
|
|
|
|
AppEvent::Scroll(scroll_delta) => {
|
|
|
|
|
|
self.dispatch_scroll_event(scroll_delta);
|
|
|
|
|
|
}
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
AppEvent::CodexEvent(event) => {
|
|
|
|
|
|
self.dispatch_codex_event(event);
|
|
|
|
|
|
}
|
|
|
|
|
|
AppEvent::ExitRequest => {
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
AppEvent::CodexOp(op) => {
|
|
|
|
|
|
if matches!(self.app_state, AppState::Chat) {
|
|
|
|
|
|
self.chat_widget.submit_op(op);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
AppEvent::LatestLog(line) => {
|
|
|
|
|
|
if matches!(self.app_state, AppState::Chat) {
|
|
|
|
|
|
let _ = self.chat_widget.update_latest_log(line);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
terminal.clear()?;
|
|
|
|
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn draw_next_frame(&mut self, terminal: &mut tui::Tui) -> Result<()> {
|
|
|
|
|
|
match &mut self.app_state {
|
|
|
|
|
|
AppState::Chat => {
|
|
|
|
|
|
terminal.draw(|frame| frame.render_widget_ref(&self.chat_widget, frame.area()))?;
|
|
|
|
|
|
}
|
|
|
|
|
|
AppState::GitWarning { screen } => {
|
|
|
|
|
|
terminal.draw(|frame| frame.render_widget_ref(&*screen, frame.area()))?;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
Ok(())
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/// Dispatch a KeyEvent to the current view and let it decide what to do
|
|
|
|
|
|
/// with it.
|
|
|
|
|
|
fn dispatch_key_event(&mut self, key_event: KeyEvent) {
|
|
|
|
|
|
match &mut self.app_state {
|
|
|
|
|
|
AppState::Chat => {
|
|
|
|
|
|
if let Err(e) = self.chat_widget.handle_key_event(key_event) {
|
|
|
|
|
|
tracing::error!("SendError: {e}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
AppState::GitWarning { screen } => match screen.handle_key_event(key_event) {
|
|
|
|
|
|
GitWarningOutcome::Continue => {
|
|
|
|
|
|
self.app_state = AppState::Chat;
|
|
|
|
|
|
let _ = self.app_event_tx.send(AppEvent::Redraw);
|
|
|
|
|
|
}
|
|
|
|
|
|
GitWarningOutcome::Quit => {
|
|
|
|
|
|
let _ = self.app_event_tx.send(AppEvent::ExitRequest);
|
|
|
|
|
|
}
|
|
|
|
|
|
GitWarningOutcome::None => {
|
|
|
|
|
|
// do nothing
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-25 12:01:52 -07:00
|
|
|
|
fn dispatch_scroll_event(&mut self, scroll_delta: i32) {
|
|
|
|
|
|
if matches!(self.app_state, AppState::Chat) {
|
|
|
|
|
|
if let Err(e) = self.chat_widget.handle_scroll_delta(scroll_delta) {
|
|
|
|
|
|
tracing::error!("SendError: {e}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
feat: initial import of Rust implementation of Codex CLI in codex-rs/ (#629)
As stated in `codex-rs/README.md`:
Today, Codex CLI is written in TypeScript and requires Node.js 22+ to
run it. For a number of users, this runtime requirement inhibits
adoption: they would be better served by a standalone executable. As
maintainers, we want Codex to run efficiently in a wide range of
environments with minimal overhead. We also want to take advantage of
operating system-specific APIs to provide better sandboxing, where
possible.
To that end, we are moving forward with a Rust implementation of Codex
CLI contained in this folder, which has the following benefits:
- The CLI compiles to small, standalone, platform-specific binaries.
- Can make direct, native calls to
[seccomp](https://man7.org/linux/man-pages/man2/seccomp.2.html) and
[landlock](https://man7.org/linux/man-pages/man7/landlock.7.html) in
order to support sandboxing on Linux.
- No runtime garbage collection, resulting in lower memory consumption
and better, more predictable performance.
Currently, the Rust implementation is materially behind the TypeScript
implementation in functionality, so continue to use the TypeScript
implmentation for the time being. We will publish native executables via
GitHub Releases as soon as we feel the Rust version is usable.
2025-04-24 13:31:40 -07:00
|
|
|
|
fn dispatch_codex_event(&mut self, event: Event) {
|
|
|
|
|
|
if matches!(self.app_state, AppState::Chat) {
|
|
|
|
|
|
if let Err(e) = self.chat_widget.handle_codex_event(event) {
|
|
|
|
|
|
tracing::error!("SendError: {e}");
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|