You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<p><code>flux9s</code> is a terminal UI for operators who want live visibility into Flux resources and the cluster state around them without leaving the shell. It watches Flux resources in real time, keeps a local in-memory view of their current state, and lets you move quickly between lists, details, YAML, traces, graphs, and reconciliation history.</p>
83
+
<p>The project is intentionally keyboard-first and closely follows familiar <a href="https://github.com/derailed/k9s" target="_blank" rel="noopener noreferrer">K9s</a> patterns: <code>j</code>/<code>k</code> navigation, <code>:</code> command mode, context and namespace switching, footer help, and k9s-style skins.</p>
84
+
85
+
<h2>The problem it solves</h2>
86
+
<p>Flux already provides strong controller APIs, and the <a href="https://fluxoperator.dev/web-ui/" target="_blank" rel="noopener noreferrer">Flux Operator Web UI</a> is an excellent browser-based experience for dashboards and cluster-wide visibility. <code>flux9s</code> was built to complement that workflow, not replace it.</p>
87
+
<p>Use <code>flux9s</code> when you want to stay in the terminal and:</p>
88
+
<ul>
89
+
<li>see Flux reconciliation state update live</li>
90
+
<li>inspect Kustomizations, HelmReleases, sources, and Flux Operator resources in one place</li>
91
+
<li>trace ownership chains and visualize managed workloads</li>
92
+
<li>check controller readiness and Flux bundle version from the same interface</li>
93
+
<li>run quick actions such as suspend, resume, reconcile, reconcile-with-source, and delete</li>
94
+
</ul>
95
+
96
+
<h2>Why it stays fast</h2>
97
+
<p><code>flux9s</code> uses the Kubernetes Watch API for supported Flux resource types instead of repeatedly polling. By default it starts scoped to a namespace, with the default configuration targeting <code>flux-system</code>, and only switches to cluster-wide watches when you explicitly choose <code>all</code>. That keeps API usage and terminal updates lighter on larger clusters.</p>
98
+
<p>The same watch-driven model is also used to surface Flux controller pod state and deployment metadata in the header, which is how the UI can show controller readiness and the detected Flux bundle version alongside resource health.</p>
99
+
100
+
<h2>Built for Flux and Flux Operator</h2>
101
+
<p>Beyond core Flux controller resources, <code>flux9s</code> also understands Flux Operator resources such as <code>FluxInstance</code>, <code>ResourceSet</code>, <code>ResourceSetInputProvider</code>, and <code>FluxReport</code>. That support shows up in practical features, not just extra rows in a table: graph and history views extend to operator-managed resources, and the graph builder follows the same relationship-discovery patterns used by the Flux Operator Web UI.</p>
102
+
<p>For a deeper code-level walkthrough, see the <a href="{{< relref "developer-guide/" >}}">Developer Guide</a>. If you want to get running quickly, jump to <a href="{{< relref "getting-started/" >}}">Getting Started</a>.</p>
flux9s follows a modified Elm Architecture pattern with async task spawning:
12
+
flux9s is a Rust TUI that keeps a live, local model of Flux resources and renders it through a keyboard-first interface. The architecture is intentionally simple: watch Kubernetes objects continuously, normalize them into in-memory state, and keep the UI loop responsive by pushing slower work onto async tasks.
13
13
14
-
### Model
14
+
### Entry Points
15
+
16
+
The repository currently has two top-level execution modes:
17
+
18
+
-`src/main.rs` is the CLI and TUI binary entry point.
19
+
-`src/lib.rs` exposes the reusable library API, including headless usage through `ClusterSession`.
20
+
21
+
The crate enables the TUI by default, but the `tui` feature is optional. That means contributor-facing architecture should be understood as "shared Flux watcher/library core plus an optional terminal UI", not only as a standalone binary.
22
+
23
+
### Data Flow
15
24
16
-
`App` struct holds all application state in a centralized location. State is organized into logical sub-structures for better maintainability.
25
+
At a high level, the runtime looks like this:
17
26
18
-
### Update
27
+
1.`src/watcher/mod.rs` starts a watch stream for each supported Flux resource kind, plus dedicated watchers for Flux controller pods and controller deployments.
28
+
2. Watch events are normalized into `WatchEvent` values and applied to `ResourceState` in `src/watcher/state.rs`.
29
+
3.`App` in `src/tui/app/` reads that state and renders list, detail, YAML, trace, graph, history, and favorites views.
30
+
4.`ResourceService` and `ClusterSession` provide the same watcher/state/operation foundation without requiring the TUI layer.
19
31
20
-
`handle_key()` processes events and updates state synchronously. Event handling is centralized in `src/tui/app/events.rs`.
32
+
### Watch Strategy And Performance
21
33
22
-
### View
34
+
Performance is driven mostly by the watcher design:
35
+
36
+
- When a namespace is selected, `ResourceWatcher` uses `Api::namespaced(...)`.
37
+
- Only when the user switches to `all` does it use `Api::all(...)`.
38
+
- Namespace changes restart the watcher set instead of broad-watching everything and filtering afterward.
39
+
- The default configuration starts in `flux-system`, which keeps initial watch scope narrow on larger clusters.
40
+
41
+
This is why flux9s can provide live updates while staying responsive on clusters where a cluster-wide watch would be unnecessarily expensive.
42
+
43
+
### Model
23
44
24
-
`render()` displays current state using stateless components. Views are organized in `src/tui/views/` and receive all needed data as parameters.
45
+
`App` still follows a modified Elm-style split:
46
+
47
+
-`App` and the state structs in `src/tui/app/state.rs` hold the centralized TUI state.
48
+
-`handle_key()` in `src/tui/app/events.rs` processes input synchronously.
49
+
-`render()` in `src/tui/app/rendering.rs` draws the current state using stateless view functions from `src/tui/views/`.
50
+
51
+
This split keeps event handling predictable while making individual views easy to reason about and test.
25
52
26
53
### Async Layer
27
54
28
-
Spawned tasks + oneshot channels handle I/O operations without blocking the UI. Async operations are managed in `src/tui/app/async_ops.rs`.
55
+
Network-bound and potentially slower operations are spawned off the main UI loop and returned through `oneshot` channels. This includes YAML fetches, trace resolution, graph building, and write operations such as suspend, resume, reconcile, and delete. The async entry points live in `src/tui/app/async_ops.rs`.
56
+
57
+
The important behavior is that the UI never blocks on these calls; it schedules the work, keeps rendering, and picks up results later.
58
+
59
+
### Type System And Generated Models
60
+
61
+
Flux and Flux Operator CRD types are generated into `src/models/_generated/`. The rest of the codebase relies on `FluxResourceKind` and the Kubernetes API helpers built around it as the single source of truth for resource names, aliases, groups, versions, and plural forms.
62
+
63
+
That approach is what keeps the watcher registry, fetch paths, command aliases, and type-specific views aligned when CRDs evolve.
64
+
65
+
### K9s Conventions And Flux-Specific Additions
66
+
67
+
flux9s deliberately reuses the K9s interaction model where it helps operators move quickly:
68
+
69
+
-`j`/`k` navigation and keyboard-first workflows
70
+
-`:` command mode with aliases and autocomplete
71
+
- context and namespace switching
72
+
- footer and help overlays driven from centralized keybinding definitions
73
+
- k9s-style skin compatibility
74
+
75
+
On top of that, flux9s adds workflows that are specific to Flux and Flux Operator:
76
+
77
+
- support for `FluxInstance`, `ResourceSet`, `ResourceSetInputProvider`, and `FluxReport`
78
+
- trace and graph views for Flux-managed relationships
79
+
- reconciliation history for resource types that expose `status.history`
80
+
- reconcile-with-source and other Flux-aware resource actions
81
+
82
+
The graph code in `src/trace/graph_builder.rs` explicitly follows patterns from the Flux Operator Web UI, which is why Flux Operator resources can participate in the same relationship views as core Flux resources.
29
83
30
84
## Project Structure
31
85
32
86
```
33
87
flux9s/
34
88
├── src/
35
-
│ ├── cli/ # CLI command parsing
36
-
│ ├── config/ # Configuration management
37
-
│ ├── kube/ # Kubernetes client wrapper
38
-
│ ├── models/ # Generated and custom models
39
-
│ ├── trace/ # Resource tracing
40
-
│ ├── tui/ # Terminal UI
41
-
│ │ ├── app/ # Application state and logic (refactored)
42
-
│ │ │ ├── core.rs # App struct and core logic
43
-
│ │ │ ├── state.rs # State structures
44
-
│ │ │ ├── events.rs # Event handling
45
-
│ │ │ ├── rendering.rs # Render orchestration
46
-
│ │ │ └── async_ops.rs # Async operations
47
-
│ │ ├── views/ # View components
48
-
│ │ ├── submenu.rs # Submenu system
49
-
│ │ ├── keybindings.rs # Keybinding management
50
-
│ │ └── ... # Other TUI modules
51
-
│ └── watcher/ # Resource watching
52
-
├── crds/ # Flux CRD files
53
-
├── tests/ # Integration tests
54
-
└── docs/ # Documentation
89
+
│ ├── main.rs # Binary entry point
90
+
│ ├── lib.rs # Library entry point and public exports
├── tests/ # Integration-style tests and snapshots
109
+
├── docs/ # Hugo docs site
110
+
└── justfile # Common contributor workflows
55
111
```
56
112
57
-
### Recent Architecture Changes
113
+
### TUI Module Notes
58
114
59
-
**App Module Refactoring:**The application logic has been refactored from a single `app.rs` file into a modular structure under `src/tui/app/`:
115
+
The TUI is not a single monolith anymore. The current split is:
60
116
61
117
-**`core.rs`** - Main App struct and core logic
62
-
-**`state.rs`** - Organized state structures (ViewState, SelectionState, UIState, AsyncOperationState)
118
+
-**`state.rs`** - Organized state structures (view, selection, UI, async, controller pod state)
63
119
-**`events.rs`** - Event handling and input processing
64
120
-**`rendering.rs`** - Rendering orchestration
65
121
-**`async_ops.rs`** - Async operation management
66
122
67
-
This separation improves code organization, maintainability, and makes the codebase easier to navigate.
68
-
69
-
**Submenu System:** An interactive submenu system has been added for commands like `:ctx` and `:skin`, providing a user-friendly way to select from available options. The system is built using the `CommandSubmenu` trait and can be extended to other commands. See the main `DEVELOPER_GUIDE.md` for implementation details.
70
-
71
-
**Keybinding Centralization:** All keybindings are now centralized in `src/tui/keybindings.rs`, providing a single source of truth for footer rendering, help text, and layout calculations.
123
+
The command palette and submenu behavior live outside that folder in `src/tui/commands.rs` and `src/tui/submenu.rs`, while footer/help consistency is driven by `src/tui/keybindings.rs`.
72
124
73
125
## Development Setup
74
126
@@ -91,11 +143,41 @@ cargo build
91
143
just ci
92
144
```
93
145
94
-
This runs:
146
+
The current `just ci` workflow runs:
95
147
96
148
-`cargo fmt` - Format code
97
149
-`cargo clippy` - Lint code
98
-
-`cargo test` - Run tests
150
+
-`cargo audit` - Advisory check
151
+
-`cargo test --lib --tests` - Library and unit-style tests
152
+
-`cargo test --test ...` - Selected integration-style test binaries
153
+
154
+
`cargo audit` needs network access to refresh the RustSec advisory database, so it may fail in restricted environments even when the code is fine.
155
+
156
+
### Docs Workflow
157
+
158
+
The docs site is maintained in the same repository and has explicit `just` helpers:
159
+
160
+
```bash
161
+
just docs-deps
162
+
just docs-serve
163
+
just docs-build
164
+
```
165
+
166
+
Use these instead of ad hoc commands when working on the Hugo site from the repo root.
167
+
168
+
## Testing Layout
169
+
170
+
The test tree is flatter than some older internal notes imply. Today, most contributor-facing tests live as top-level files under `tests/`:
171
+
172
+
-`crd_compatibility.rs` - compatibility checks for watched CRDs and status extraction
-`navigation_tests.rs` and `snapshot_tests.rs` - TUI behavior and rendering snapshots
179
+
180
+
Snapshot artifacts live in `tests/snapshots/`. TUI-specific tests are feature-gated in `Cargo.toml`, while the headless/library tests run without the `tui` feature.
Copy file name to clipboardExpand all lines: docs/content/getting-started/_index.md
+10Lines changed: 10 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -7,6 +7,16 @@ toc: true
7
7
type: docs
8
8
---
9
9
10
+
## What Is flux9s?
11
+
12
+
`flux9s` is a terminal UI for watching Flux resources and the cluster state around them in real time. It is designed for operators who already live in a shell and want fast visibility into what Flux is doing, how resources relate to each other, and whether quick intervention is needed.
13
+
14
+
That includes core Flux resources such as `Kustomization`, `HelmRelease`, and source objects, plus Flux Operator resources such as `FluxInstance` and `ResourceSet`. From the same interface you can inspect YAML, trace ownership, open graph and history views, and run common actions like suspend, resume, and reconcile.
15
+
16
+
## Why Use It If Flux Operator Has a Web UI?
17
+
18
+
The [Flux Operator Web UI](https://fluxoperator.dev/web-ui/) is excellent for browser-based visibility. `flux9s` complements it with a terminal-first workflow: keyboard navigation, quick context switching, namespace-scoped live watches, and operational actions without leaving your current shell session.
0 commit comments