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
|
|
|
|
//! A live status indicator that shows the *latest* log line emitted by the
|
|
|
|
|
|
//! application while the agent is processing a long‑running task.
|
|
|
|
|
|
|
|
|
|
|
|
use std::time::Duration;
|
2025-08-06 21:20:09 -07:00
|
|
|
|
use std::time::Instant;
|
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
|
|
|
|
|
2025-08-12 15:43:07 -07:00
|
|
|
|
use codex_core::protocol::Op;
|
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 ratatui::buffer::Buffer;
|
|
|
|
|
|
use ratatui::layout::Rect;
|
2025-08-25 14:38:38 -07:00
|
|
|
|
use ratatui::style::Stylize;
|
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 ratatui::text::Line;
|
|
|
|
|
|
use ratatui::widgets::Paragraph;
|
|
|
|
|
|
use ratatui::widgets::WidgetRef;
|
|
|
|
|
|
|
|
|
|
|
|
use crate::app_event::AppEvent;
|
2025-05-15 14:50:30 -07:00
|
|
|
|
use crate::app_event_sender::AppEventSender;
|
2025-09-04 10:55:50 -07:00
|
|
|
|
use crate::key_hint;
|
2025-08-14 16:59:47 -04:00
|
|
|
|
use crate::shimmer::shimmer_spans;
|
2025-08-20 13:47:24 -07:00
|
|
|
|
use crate::tui::FrameRequester;
|
2025-08-25 14:38:38 -07:00
|
|
|
|
use textwrap::Options as TwOptions;
|
|
|
|
|
|
use textwrap::WordSplitter;
|
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
|
|
|
|
|
|
|
|
|
|
pub(crate) struct StatusIndicatorWidget {
|
2025-08-20 16:58:56 -07:00
|
|
|
|
/// Animated header text (defaults to "Working").
|
|
|
|
|
|
header: String,
|
2025-08-25 14:38:38 -07:00
|
|
|
|
/// Queued user messages to display under the status line.
|
|
|
|
|
|
queued_messages: Vec<String>,
|
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
|
|
|
|
|
2025-09-04 12:37:43 -07:00
|
|
|
|
elapsed_running: Duration,
|
|
|
|
|
|
last_resume_at: Instant,
|
|
|
|
|
|
is_paused: bool,
|
2025-08-12 15:43:07 -07:00
|
|
|
|
app_event_tx: AppEventSender,
|
2025-08-20 13:47:24 -07:00
|
|
|
|
frame_requester: FrameRequester,
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl StatusIndicatorWidget {
|
2025-08-20 13:47:24 -07:00
|
|
|
|
pub(crate) fn new(app_event_tx: AppEventSender, frame_requester: FrameRequester) -> Self {
|
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
|
|
|
|
Self {
|
2025-08-20 16:58:56 -07:00
|
|
|
|
header: String::from("Working"),
|
2025-08-25 14:38:38 -07:00
|
|
|
|
queued_messages: Vec::new(),
|
2025-09-04 12:37:43 -07:00
|
|
|
|
elapsed_running: Duration::ZERO,
|
|
|
|
|
|
last_resume_at: Instant::now(),
|
|
|
|
|
|
is_paused: false,
|
2025-08-04 21:23:22 -07:00
|
|
|
|
|
2025-08-12 15:43:07 -07:00
|
|
|
|
app_event_tx,
|
2025-08-20 13:47:24 -07:00
|
|
|
|
frame_requester,
|
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
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 14:38:38 -07:00
|
|
|
|
pub fn desired_height(&self, width: u16) -> u16 {
|
|
|
|
|
|
// Status line + wrapped queued messages (up to 3 lines per message)
|
|
|
|
|
|
// + optional ellipsis line per truncated message + 1 spacer line
|
|
|
|
|
|
let inner_width = width.max(1) as usize;
|
|
|
|
|
|
let mut total: u16 = 1; // status line
|
|
|
|
|
|
let text_width = inner_width.saturating_sub(3); // account for " ↳ " prefix
|
|
|
|
|
|
if text_width > 0 {
|
|
|
|
|
|
let opts = TwOptions::new(text_width)
|
|
|
|
|
|
.break_words(false)
|
|
|
|
|
|
.word_splitter(WordSplitter::NoHyphenation);
|
|
|
|
|
|
for q in &self.queued_messages {
|
|
|
|
|
|
let wrapped = textwrap::wrap(q, &opts);
|
|
|
|
|
|
let lines = wrapped.len().min(3) as u16;
|
|
|
|
|
|
total = total.saturating_add(lines);
|
|
|
|
|
|
if wrapped.len() > 3 {
|
|
|
|
|
|
total = total.saturating_add(1); // ellipsis line
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if !self.queued_messages.is_empty() {
|
|
|
|
|
|
total = total.saturating_add(1); // keybind hint line
|
|
|
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
|
|
|
// At least one line per message if width is extremely narrow
|
|
|
|
|
|
total = total.saturating_add(self.queued_messages.len() as u16);
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
2025-08-25 14:38:38 -07:00
|
|
|
|
total.saturating_add(1) // spacer line
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-12 15:43:07 -07:00
|
|
|
|
pub(crate) fn interrupt(&self) {
|
|
|
|
|
|
self.app_event_tx.send(AppEvent::CodexOp(Op::Interrupt));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-20 16:58:56 -07:00
|
|
|
|
/// Update the animated header label (left of the brackets).
|
|
|
|
|
|
pub(crate) fn update_header(&mut self, header: String) {
|
|
|
|
|
|
if self.header != header {
|
|
|
|
|
|
self.header = header;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 14:38:38 -07:00
|
|
|
|
/// Replace the queued messages displayed beneath the header.
|
|
|
|
|
|
pub(crate) fn set_queued_messages(&mut self, queued: Vec<String>) {
|
|
|
|
|
|
self.queued_messages = queued;
|
|
|
|
|
|
// Ensure a redraw so changes are visible.
|
|
|
|
|
|
self.frame_requester.schedule_frame();
|
2025-08-22 14:03:58 -07:00
|
|
|
|
}
|
2025-09-04 12:37:43 -07:00
|
|
|
|
|
|
|
|
|
|
pub(crate) fn pause_timer(&mut self) {
|
|
|
|
|
|
self.pause_timer_at(Instant::now());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn resume_timer(&mut self) {
|
|
|
|
|
|
self.resume_timer_at(Instant::now());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn pause_timer_at(&mut self, now: Instant) {
|
|
|
|
|
|
if self.is_paused {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
self.elapsed_running += now.saturating_duration_since(self.last_resume_at);
|
|
|
|
|
|
self.is_paused = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pub(crate) fn resume_timer_at(&mut self, now: Instant) {
|
|
|
|
|
|
if !self.is_paused {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
self.last_resume_at = now;
|
|
|
|
|
|
self.is_paused = false;
|
|
|
|
|
|
self.frame_requester.schedule_frame();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn elapsed_seconds_at(&self, now: Instant) -> u64 {
|
|
|
|
|
|
let mut elapsed = self.elapsed_running;
|
|
|
|
|
|
if !self.is_paused {
|
|
|
|
|
|
elapsed += now.saturating_duration_since(self.last_resume_at);
|
|
|
|
|
|
}
|
|
|
|
|
|
elapsed.as_secs()
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fn elapsed_seconds(&self) -> u64 {
|
|
|
|
|
|
self.elapsed_seconds_at(Instant::now())
|
|
|
|
|
|
}
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
impl WidgetRef for StatusIndicatorWidget {
|
|
|
|
|
|
fn render_ref(&self, area: Rect, buf: &mut Buffer) {
|
2025-08-25 14:38:38 -07:00
|
|
|
|
if area.is_empty() {
|
2025-08-04 21:23:22 -07:00
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-14 16:59:47 -04:00
|
|
|
|
// Schedule next animation frame.
|
2025-08-20 13:47:24 -07:00
|
|
|
|
self.frame_requester
|
2025-08-20 16:58:56 -07:00
|
|
|
|
.schedule_frame_in(Duration::from_millis(32));
|
2025-09-04 12:37:43 -07:00
|
|
|
|
let elapsed = self.elapsed_seconds();
|
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
|
|
|
|
|
2025-08-04 21:23:22 -07:00
|
|
|
|
// Plain rendering: no borders or padding so the live cell is visually indistinguishable from terminal scrollback.
|
2025-08-25 14:38:38 -07:00
|
|
|
|
let mut spans = vec![" ".into()];
|
|
|
|
|
|
spans.extend(shimmer_spans(&self.header));
|
|
|
|
|
|
spans.extend(vec![
|
|
|
|
|
|
" ".into(),
|
|
|
|
|
|
format!("({elapsed}s • ").dim(),
|
|
|
|
|
|
"Esc".dim().bold(),
|
|
|
|
|
|
" to interrupt)".dim(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// Build lines: status, then queued messages, then spacer.
|
|
|
|
|
|
let mut lines: Vec<Line<'static>> = Vec::new();
|
|
|
|
|
|
lines.push(Line::from(spans));
|
|
|
|
|
|
// Wrap queued messages using textwrap and show up to the first 3 lines per message.
|
|
|
|
|
|
let text_width = area.width.saturating_sub(3); // " ↳ " prefix
|
|
|
|
|
|
let opts = TwOptions::new(text_width as usize)
|
|
|
|
|
|
.break_words(false)
|
|
|
|
|
|
.word_splitter(WordSplitter::NoHyphenation);
|
|
|
|
|
|
for q in &self.queued_messages {
|
|
|
|
|
|
let wrapped = textwrap::wrap(q, &opts);
|
|
|
|
|
|
for (i, piece) in wrapped.iter().take(3).enumerate() {
|
|
|
|
|
|
let prefix = if i == 0 { " ↳ " } else { " " };
|
|
|
|
|
|
let content = format!("{prefix}{piece}");
|
2025-08-25 17:36:05 -07:00
|
|
|
|
lines.push(Line::from(content.dim().italic()));
|
2025-08-25 14:38:38 -07:00
|
|
|
|
}
|
|
|
|
|
|
if wrapped.len() > 3 {
|
2025-08-25 17:36:05 -07:00
|
|
|
|
lines.push(Line::from(" …".dim().italic()));
|
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
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-25 14:38:38 -07:00
|
|
|
|
if !self.queued_messages.is_empty() {
|
2025-09-04 10:55:50 -07:00
|
|
|
|
let shortcut = key_hint::alt("↑");
|
|
|
|
|
|
lines.push(Line::from(vec![" ".into(), shortcut, " edit".into()]).dim());
|
2025-08-25 14:38:38 -07:00
|
|
|
|
}
|
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
|
|
|
|
|
2025-08-04 21:23:22 -07:00
|
|
|
|
let paragraph = Paragraph::new(lines);
|
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
|
|
|
|
paragraph.render_ref(area, buf);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-03 11:51:33 -07:00
|
|
|
|
|
2025-08-04 21:23:22 -07:00
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
use crate::app_event::AppEvent;
|
|
|
|
|
|
use crate::app_event_sender::AppEventSender;
|
2025-08-25 14:38:38 -07:00
|
|
|
|
use ratatui::Terminal;
|
|
|
|
|
|
use ratatui::backend::TestBackend;
|
2025-09-04 12:37:43 -07:00
|
|
|
|
use std::time::Duration;
|
|
|
|
|
|
use std::time::Instant;
|
2025-08-20 10:11:09 -07:00
|
|
|
|
use tokio::sync::mpsc::unbounded_channel;
|
2025-08-04 21:23:22 -07:00
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-08-25 14:38:38 -07:00
|
|
|
|
fn renders_with_working_header() {
|
2025-08-20 10:11:09 -07:00
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
2025-08-04 21:23:22 -07:00
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
2025-08-25 14:38:38 -07:00
|
|
|
|
let w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
|
|
|
|
|
|
|
|
|
|
|
// Render into a fixed-size test terminal and snapshot the backend.
|
|
|
|
|
|
let mut terminal = Terminal::new(TestBackend::new(80, 2)).expect("terminal");
|
|
|
|
|
|
terminal
|
|
|
|
|
|
.draw(|f| w.render_ref(f.area(), f.buffer_mut()))
|
|
|
|
|
|
.expect("draw");
|
2025-09-04 10:55:50 -07:00
|
|
|
|
insta::assert_snapshot!(terminal.backend());
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-08-25 14:38:38 -07:00
|
|
|
|
fn renders_truncated() {
|
2025-08-20 10:11:09 -07:00
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
2025-08-04 21:23:22 -07:00
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
2025-08-25 14:38:38 -07:00
|
|
|
|
let w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
|
|
|
|
|
|
|
|
|
|
|
// Render into a fixed-size test terminal and snapshot the backend.
|
|
|
|
|
|
let mut terminal = Terminal::new(TestBackend::new(20, 2)).expect("terminal");
|
|
|
|
|
|
terminal
|
|
|
|
|
|
.draw(|f| w.render_ref(f.area(), f.buffer_mut()))
|
|
|
|
|
|
.expect("draw");
|
2025-09-04 10:55:50 -07:00
|
|
|
|
insta::assert_snapshot!(terminal.backend());
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|
2025-08-07 01:45:04 -07:00
|
|
|
|
|
|
|
|
|
|
#[test]
|
2025-08-25 14:38:38 -07:00
|
|
|
|
fn renders_with_queued_messages() {
|
2025-08-20 10:11:09 -07:00
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
2025-08-07 01:45:04 -07:00
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
2025-08-20 13:47:24 -07:00
|
|
|
|
let mut w = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
2025-08-25 14:38:38 -07:00
|
|
|
|
w.set_queued_messages(vec!["first".to_string(), "second".to_string()]);
|
|
|
|
|
|
|
|
|
|
|
|
// Render into a fixed-size test terminal and snapshot the backend.
|
|
|
|
|
|
let mut terminal = Terminal::new(TestBackend::new(80, 8)).expect("terminal");
|
|
|
|
|
|
terminal
|
|
|
|
|
|
.draw(|f| w.render_ref(f.area(), f.buffer_mut()))
|
|
|
|
|
|
.expect("draw");
|
2025-09-04 10:55:50 -07:00
|
|
|
|
insta::assert_snapshot!(terminal.backend());
|
2025-08-07 01:45:04 -07:00
|
|
|
|
}
|
2025-09-04 12:37:43 -07:00
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn timer_pauses_when_requested() {
|
|
|
|
|
|
let (tx_raw, _rx) = unbounded_channel::<AppEvent>();
|
|
|
|
|
|
let tx = AppEventSender::new(tx_raw);
|
|
|
|
|
|
let mut widget = StatusIndicatorWidget::new(tx, crate::tui::FrameRequester::test_dummy());
|
|
|
|
|
|
|
|
|
|
|
|
let baseline = Instant::now();
|
|
|
|
|
|
widget.last_resume_at = baseline;
|
|
|
|
|
|
|
|
|
|
|
|
let before_pause = widget.elapsed_seconds_at(baseline + Duration::from_secs(5));
|
|
|
|
|
|
assert_eq!(before_pause, 5);
|
|
|
|
|
|
|
|
|
|
|
|
widget.pause_timer_at(baseline + Duration::from_secs(5));
|
|
|
|
|
|
let paused_elapsed = widget.elapsed_seconds_at(baseline + Duration::from_secs(10));
|
|
|
|
|
|
assert_eq!(paused_elapsed, before_pause);
|
|
|
|
|
|
|
|
|
|
|
|
widget.resume_timer_at(baseline + Duration::from_secs(10));
|
|
|
|
|
|
let after_resume = widget.elapsed_seconds_at(baseline + Duration::from_secs(13));
|
|
|
|
|
|
assert_eq!(after_resume, before_pause + 3);
|
|
|
|
|
|
}
|
2025-08-04 21:23:22 -07:00
|
|
|
|
}
|