Appearance
Architecture
Klix is organized around a small set of cooperating subsystems. The implementation is intentionally compact, so understanding the architecture is mostly about understanding the runtime flow.
See also:
The Runtime Shape
At runtime, a typical Klix app looks like this:
Appis created and registrations happenapp.run()parses top-level CLI flags- Klix creates a
Session - Klix chooses a renderer and input engine
- Klix emits the
startevent - Klix reads a line
- Klix emits the
inputevent - Klix parses the line through the router
- Klix runs middleware
- Klix invokes the command handler
- Klix emits
exitand saves state on shutdown
That flow is implemented in klix/app.py. See App.
Subsystems
App
App is the composition root. It owns:
- command registry
- middleware list
- event bus
- router
- state manager
- completer registration
- the main run loop
Session
Session is the per-terminal runtime object passed into handlers. It contains:
- typed app state
- metadata about the terminal
- input history
- UI access through
session.ui - a background task registry
Router
The router is responsible for:
- mapping a raw slash-command line to
ParsedCommand - resolving aliases
- validating arguments against
args_schema
The parser is intentionally simple. It is not a full shell parser. See Router.
Event Bus
The event bus is a small ordered dispatcher. It supports both sync and async handlers and is used for lifecycle and input-related hooks.
Middleware
Middleware wraps command dispatch. It runs after parsing and before the final handler. That means middleware can inspect ctx.command.
Input Engine
The input engine is the thin prompt layer over prompt_toolkit. It owns:
- input mode
- prompt history
- key bindings
- CI fallback behavior
UI Namespace
session.ui is the developer-facing convenience surface. It binds together:
- renderer-backed print/stream helpers
session.ui.inputsession.ui.outputsession.ui.layout- cursor helpers
Why The Architecture Looks Like This
Klix is trying to be a framework, not a single-purpose tool. That pushes the architecture toward separation:
- routing is separate from input reading
- middleware is separate from command logic
- session state is separate from app registration
- rendering is separate from UI widgets
This is what lets the same framework support:
- generated starter CLIs
- command-driven demos like
examples/minimal.py - more custom flows like the Gemini-style chat demo in
examples/chat_ai.py
Current Implementation Boundaries
The docs in this folder reflect the current code, which includes some intentional simplifications:
- the layout system redraws coarsely instead of maintaining a fully persistent screen model
- the event system exists for many event names, but only some events are actively emitted by
App.run() - command parsing is token-based, not shell-quote aware
- persistence is file-based JSON with a simple version field
These are not hidden footnotes. They affect how you should build with Klix today. Read:
Common Mistakes
Treating Klix like a full-screen TUI framework
Klix has layout regions, but the current implementation is still closer to a smart command-line runtime than a fully managed alternate-screen UI.
Expecting middleware for plain text in custom loops automatically
If you build a custom interaction loop outside App.run(), you need to explicitly route command lines through the router and middleware if you want that behavior.
Ignoring the simple parser
If your command syntax needs shell-level quoting rules, nested subcommands, or highly flexible parsing, you should design around the current parser limits or extend the routing approach deliberately.