What is argrelay
?
A wrapper for command line interface (CLI) tools
to search & select custom data input directly in the standard shell.
It integrates shell + client + server to enable local commands
with enriched data based on concise input syntax.
- Although its initial purpose was command auto-completion, that become a trivial byproduct of...
- Its primary target feature: keyword-based structured data search.
CLI is indispensable for rapidly evolving custom tools:
- [A] ubiquitous automation (any command is effectively replay-able code)
- [B] quick implementation (get it done "in the afternoon" without discussing fullstack API whole month)
- [C] ultimate manual intervention (when everything else is already failed and unavailable)
Achieving all three [A, B, C] is nearly impossible without CLI.
And argrelay
makes CLI more human-efficient by reducing manual and guess work:
- enables inline search directly in shell (without copy-and-pasting args from other apps)
- reduces cognitive load via feedback eliminating syntax and options memorization
- unifies expectations for all commands via generic data-driven framework
See also "general dilemma" below.
It employs the same shell API as auto-completion for any other (e.g. ls
or git
) command,
except that requests go to the server with its plugin-s to run search logic against indexed data
(instead of processing requests locally by querying file system).
Essentially, sitting between the user shell and the user program,
argrelay
"relays" command line args (hence, the name) to the server on each request,
then uses response data to complete/explain/invoke the command for the user:
sequenceDiagram
autonumber
actor U as <br/>User with shell
box transparent <br/>argrelay
participant C as Client
participant S as Server
end
participant P as Any program:<br/>user-specific<br/>client-side-local
U ->> C: use shell hotkeys
activate C
C ->> S: "relay" all args
activate S
S ->> C: provide data to<br/>complete<br/>explain<br/>invoke<br/>the command
deactivate S
C ->> U: if<br/>complete<br/>or<br/>explain
C ->> P: if invoke
deactivate C
activate P
P ->> U: produce invocation results
deactivate P
See "full picture" below.
- Human types in some remembered args (via
Tab
-auto-completion) in relaxed syntax and order. - Machine provides feedback (via
Alt+Shift+Q
-query) on the progress of the input interrogation - it tells:- What args machine already matched with the data according to command schema.
- What else machine needs from human to disambiguate and select the remaining command args.
Try "interactive demo" below.
There are 3 types of requests corresponding to 3 types of hotkeys.
Bash: | Server: | Client: |
---|---|---|
Alt+Shift+Q |
reports existing and missing input | displays command input interrogation status |
Tab |
suggests options for missing input | lists options to Bash for auto-completion |
Enter |
provides data to invoke a command | executes the command |
Apart from the trivial Enter
to execute command,
Tab
and Alt+Shift+Q
hotkeys are configured via Readline
library Bash relies on.
Data-assisted CLI with search and completion
GUI-s are targeted secondarily as they not have the restrictions vs the benefits CLI-s have:
- To leverage minimal syntax queries, API requests can be handled from anything (including GUI).
- But API-s are purposefully feature-tailored to support (both challenging and rewarding) CLI peculiarities.
show example
For example, in GUI-s, typing a query into a search bar may easily be accompanied by
[1] a separate (from the search bar) window area
[2] with individually selectable
[3] full-text-search results
[4] populated async-ly with typing...
In CLI-s, grep
does [3] full-text-search,
but it is slow and completely misses the rest [1], [2], [4].
Also, simple full-text-search is imprecise - facilitating selection in CLI works best with:
a catalogue-like navigation selecting keywords via structured data search with auto-completion.
Neither GUI nor CLI will ever go way:
GUI | CLI |
---|---|
➕ diagrams, images, video | ✖️ only via integration with GUI |
➖ might be time-consuming for an ad-hoc functionality | ➕ always quick dev option (low ceremony) |
➖ may not exist early in feature development | ➕ likely available early in development |
➖ error is a pop-up requiring human attendance | ➕ error is an error code = ubiquitous API |
➖ no simple way to store and share GUI output | ➕ store and share results as text |
➖ repeat steps 500 times? give up! | ➕ repeat steps 500 time? loop! |
➖ no universal way to reproduce (composite) GUI actions | ➕ paste and "replay" commands as text |
➖ no universal way to search stored GUI output | ➕ grep -search results as text |
➖ no universal way to compare GUI output | ➕ diff -compare results as text |
➖ no universal way to auto-trigger GUI actions on events | ➕ hook commands anyhow (e.g. schedule) |
➖ a separate stack (skill set) from backend to contribute to | ➕ familiarly dominates backend tools |
➖ uses APIs but hardly exposes API to integrate itself | ➕ inherent script-ability |
➖ limits system access (a layer behind a narrow API) | ➕ ultimate control |
➕ keyword captions | ➖ hardly remembered cryptic -o options |
➕ point-click actions | ➖ increased typing❗ |
➕ intuitive data-driven human interface | ➖ human interface❓ API, in fact |
To resolve this dilemma, while retaining advantages of a CLI tool,
argrelay
compensates for those last ➕-s by:
- intuitive data-driven interface
- reduced typing (args auto-reduction)
- keyword options (args auto-completion)
As opposed to GUI-demanding approaches like Warp or IDEA terminal
(in desktop environment where any tool competes for installation),
argrelay
is slim and survives everywhere in basic text modes (over telnet or SSH).
Also, none of these desktop tools allow building commands with custom input spec -
they simply augment interaction, in fact, they complement argrelay
(as they may work together).
Alternatively, unlike this argrelay
framework, independent argcomplete
library:
- ➕ queries args directly from the source
- ➖ supports only
Tab
-completion - ➖ does not search data inline
- ➖ does not provide feedback on input interrogation status
- ➖ does not eliminate irrelevant args
- ➖ uses stringent CLI syntax
- ➖ suffers performance limitations (no specialized data index)
Given that argrelay
target audience are devs (using shell),
the advantages of CLI tools over GUI can be summarized aspect-by-aspect:
aspect | ➖ GUI | ➕ CLI |
---|---|---|
output | image | text |
interaction | manual | automate-able |
design | heavy | light |
languages | exclusive | inclusive |
integration | denying | composable |
cycle | days | hours |
reviewers | many | few |
team | another | same |
users | anyone | devs |
resources | max | min |
It aimed at command auto-completion based on arbitrary data sets,
for example, using metadata for 10s x clusters, 100s x hosts, 1000s x processes, ...
(over 15K objects in total) directly from the standard shell.
Selecting args directly in shell CLI avoids otherwise error-prone
coping-and-pasting via clumsy GUI window switching.
Flexible and responsive lookup required data indexing
(e.g. each Tab-request demands short loading and querying time for context-specific data)
which suggested a server...
The performance qualities are achieved by running a standby server with pre-loaded data
(instead of loading this data into each client).
For example, with 1000s of data entries,
even if someone could generate static Bash completion rules,
it would take considerable time to load them for every shell instance.
Unlike static | generated | offline index per client,
standby server also naturally supports dynamic data updates.
This is a non-intrusive demo (e.g. without permanent changes to ~/.bashrc
).
Clone this repo somewhere (@/
is the project root).
Start @/exe/relay_demo.bash
(it may take a couple of minutes to start for the first time):
./exe/relay_demo.bash
Optionally, review env state (any time):
./exe/check_env.bash
This sub-shell configures request hotkeys to bind lay
command with @/exe/run_argrelay_client
:
-
Interact with
lay
command (which uses demo test data):lay goto # press `Alt+Shift+Q` to describe available options
lay goto host # press `Tab` one or multiple times
lay goto host dev # press `Alt+Shift+Q` to observe changes in the output
If executed (press
Enter
), it runs stub implementations (in real app it would do remotessh
-login for example). -
Browse and retrieve data (for specific query):
lay get ConfigOnlyClass ERROR
stdout
(one JSON per line):{"envelope_payload": {"text_message": "text message C"}, "exit_code": "1", "envelope_class": "ConfigOnlyClass", "severity_level": "ERROR"} {"envelope_payload": {"text_message": "text message D"}, "exit_code": "2", "envelope_class": "ConfigOnlyClass", "severity_level": "ERROR"}
-
Replace this data (for specific query):
stdin
(one JSON per line):echo ' {"envelope_payload": {"text_message": "text message C"}, "exit_code": "101", "envelope_class": "ConfigOnlyClass", "severity_level": "ERROR"} {"envelope_payload": {"text_message": "text message D"}, "exit_code": "102", "envelope_class": "ConfigOnlyClass", "severity_level": "ERROR"} ' | lay set ConfigOnlyClass ERROR
NOTE: Replacing data on the server is in alpha version (it misses validations allowing updates incompatible with schema).
-
To clean up, exit the sub-shell:
exit
-
While inside the sub-shell, inspect how auto-completion is configured for
relay_demo
:complete -p lay
-
See
@/logs/relay_demo.bash.log
of the background server:less ./logs/relay_demo.bash.log
-
Inspect configs:
@/conf/argrelay_client.json
@/conf/argrelay_server.yaml
@/conf/argrelay_plugin.yaml
-
To reset the demo, remove
@/conf
:rm conf
Script
@/exe/relay_demo.bash
relies on@/conf
being a symlink specifically to@/dst/relay_demo
:If
@/conf
is absent, it re-creates the symlink with that destination and re-installs everything. -
To debug shell scripts, export
ARGRELAY_DEBUG
with value containings
:export ARGRELAY_DEBUG="s" ./exe/relay_demo.bash
This table summarizes all executables most users ever need to know:
Executable from @/exe/ dir |
Purpose |
---|---|
check_env.bash |
checks Bash/Python environments for any issues |
bootstrap_env.bash |
bootstraps the environment (installs or upgrades argrelay ) |
dev_shell.bash |
starts configured shell with activated venv and argrelay -linked commands |
shell_env.bash |
script source -able by ~/.bashrc to avoid starting dev_shell.bash |
run_argrelay_server |
runs argrelay server (in foreground) |
run_argrelay_client |
not used directly (invoked by Alt+Shift+Q -query and Tab -completion) |
See FS_29_54_67_86.dir_structure.md for details.
- Client to be invoked by Bash hook on every Tab to
send command line arguments to the server. - Server to parse command line and propose values from
pre-loaded data for the argument under the cursor. - Plugins to customize:
- actions the client can run
- objects the server can search
- grammar the command line can have
- Interfaces to bind these all together.
- Bootstrap process to init the environment and maintain it.
- Demo example to start from.
- Testing support and coverage.
There are two options at the moment - both using MongoDB API:
Category | mongomock (default) |
pymongo |
---|---|---|
Data set size: | practical convenience limit ~ 10K objects | tested with ~ 1M objects |
Pro: | nothing else to install | no practical data set size limit found (yet) for argrelay intended use cases |
Con: | understandably, does not meet performance requirements for large data sets |
require some knowledge of MongoDB, additional setup, additional running processes |
Quantitative comparison tables between the two can be seen in docstring for DistinctValuesQuery
enum.
sequenceDiagram
autonumber
actor U as <br/>User
participant B as Bash
box transparent <br/>argrelay
participant C as Client
participant S as Server
participant DB as Data backend<br/>(internal or external)
end
participant DS as Data sources
participant P as Any program:<br/>user-specific<br/>client-side-local
DS ->> S: load data
activate S
S ->> DB: load data
deactivate S
Note over S: <br/>stand-by<br/>
U ->> B: type command and use hotkeys
B ->> C: invoke
activate C
C ->> S: "relay" all args
activate S
S ->> DB: query request
activate DB
DB ->> S: query result
deactivate DB
S ->> C: "relay" enriched lookup details
deactivate S
Note over C: next steps depend on hotkeys
C ->> U: show results
C ->> P: "relay" details to invoke
deactivate C
activate P
P ->> U: show results
deactivate P
Feel free to raise issues or discussions.