Repository navigation
[feat] auto-complete history plugins #140
Description
Here’s a stronger version of the prompt, framed as an engineering task/specification rather than just a feature request. I also make the distinction between shell core behavior and plugin behavior explicit.
Objective
Implement an intelligent interactive command-autocompletion plugin for Hellish, located in the hellishrc_plugins project rather than in the POSIX shell core.
The goal is to reproduce the useful parts of the Zsh-style interactive completion/history experience, while keeping the Hellish core minimal and POSIX-oriented.
The feature should work directly inside the current command line while the user is typing, rather than requiring a separate history-search command.
Core behavior
The plugin should provide intelligent suggestions based on the user's current input.
For example, when the user types:
make
the shell could detect available Make targets and provide interactive completions such as:
make all
make clean
make fclean
make re
make test
make debug
The user should be able to navigate/select a suggestion and insert it into the current command line, or ignore it and continue typing.
The completion mechanism should also work for normal shell commands, arguments, paths, options, and other useful completion sources where possible.
History-aware suggestions
The plugin should not behave like a simple static autocomplete dictionary.
It should take into account the user's recent command history and usage patterns.
For example, if the history contains:
make re
make test
make re
make clean
make re
then entering:
make
should prioritize frequently/recently used commands.
The system should ideally combine several signals:
current input
+
recent history
+
frequency
+
recency
+
context
+
available completions
↓
ranked suggestions
The exact ranking algorithm should be designed and documented rather than hard-coded arbitrarily.
Inline suggestion behavior
The most important UX requirement is that suggestions should appear while the user is editing the current command line.
For example:
❯ make re█
└── suggested completion
The suggestion should ideally be displayed as an inline placeholder/ghost text, similar to modern shells and terminal tools.
The user should be able to:
- accept the suggestion;
- partially accept it if technically feasible;
- cycle through alternatives;
- ignore it;
- continue editing normally;
- invoke explicit completion when desired.
For example:
❯ make re
└── ghost suggestion: `build`
Pressing an appropriate key could transform it into:
❯ make rebuild
without requiring the user to manually type the remaining characters.
The interaction must remain compatible with Hellish's existing line editor and should not interfere with normal cursor movement, deletion, history navigation, or Ctrl+C/Ctrl+D behavior.
Make target completion
Make targets are an important initial use case.
When the current command is:
make <TAB>
the plugin should inspect the relevant Makefile(s) and discover available targets.
Potential sources include:
Makefile
makefile
GNUmakefile
included Makefiles
where practical.
The plugin should avoid treating every arbitrary token as a target. It should understand the structure sufficiently to provide meaningful candidates.
For example:
❯ make c█
could suggest:
clean
while:
❯ make f█
could suggest:
fclean
The implementation should also consider whether the current working directory contains a Makefile before attempting Make-specific completion.
Intelligent contextual completion
The architecture should be extensible so that Make targets are only the first completion provider.
Ideally, the plugin should eventually support providers such as:
Command completion
│
├── Executables
├── Shell builtins
├── Aliases
├── Functions
├── Paths/files
├── Make targets
├── Git branches
├── Git commands
├── Options/flags
└── History-based suggestions
The completion engine should therefore be designed around a provider/ranking architecture rather than a large collection of hard-coded if statements.
For example:
Input
│
▼
Context parser
│
▼
Completion providers
├── History
├── Make
├── Filesystem
├── Commands
└── Git
│
▼
Candidate aggregation
│
▼
Ranking
│
▼
Interactive suggestion
Zsh-inspired behavior
The objective is not to clone Zsh internally.
Instead, study the relevant behavior of Zsh and similar modern shells and reproduce the useful UX while keeping the implementation appropriate for Hellish.
In particular, investigate:
- inline autosuggestions;
- history-based prediction;
- completion candidate ranking;
- contextual completion;
- keyboard interaction;
- completion caching;
- performance considerations.
Avoid copying implementation details that are unnecessarily coupled to Zsh's architecture.
Architecture constraints
This functionality should live in:
hellishrc_plugins
and not become part of the Hellish POSIX shell core, unless a minimal core interface is genuinely required.
The separation should be approximately:
HELLISH
│
stable plugin API
│
▼
hellishrc_plugins
│
┌──────────────┼──────────────┐
▼ ▼ ▼
completion history providers
engine engine
│
▼
inline editor
The plugin should consume existing Hellish interfaces wherever possible instead of modifying the shell parser/executor unnecessarily.
If a change to Hellish core is unavoidable, clearly document:
- why it is required;
- the smallest required interface;
- why the same functionality cannot be implemented entirely inside the plugin.
Performance requirements
Completion happens during interactive typing, so latency is critical.
The plugin must not perform expensive work synchronously for every keystroke.
For example, avoid repeatedly:
parse entire Makefile
scan entire filesystem
search entire history
spawn multiple processes
for every character typed.
Investigate appropriate strategies such as:
- caching;
- incremental updates;
- asynchronous completion generation;
- invalidation when relevant files change;
- bounded history searches;
- candidate ranking without unnecessary process spawning.
The interactive shell must remain responsive even in large repositories.
Configuration
The plugin should expose configuration through the existing hellishrc plugin mechanism.
Potential configuration should include:
enable/disable autosuggestions
enable/disable Make completion
history suggestion limit
minimum suggestion length
ranking behavior
key bindings
maximum completion latency
Use the existing project conventions instead of inventing a second configuration system.
Testing
Add tests covering at minimum:
Make completion
Makefile exists
Makefile does not exist
multiple targets
partial target
target with special characters
included Makefiles
large Makefile
History
recent command
frequent command
duplicate commands
partial history match
no matching history
large history
Interactive behavior
accept suggestion
reject suggestion
cycle suggestions
cursor movement
backspace
Ctrl+C
Ctrl+D
history navigation
empty input
Regression
Ensure existing Hellish command-line behavior remains unchanged when the plugin is disabled.
Important engineering questions
Before implementing, investigate the existing Hellish line-editor architecture and determine:
- Where is interactive input currently handled?
- How are key sequences interpreted?
- How is the current editable buffer represented?
- How does Hellish currently implement history?
- Can the plugin observe changes to the input buffer?
- Can the plugin render ghost text without modifying the core renderer?
- What plugin API already exists?
- What minimal API additions would be necessary?
- Can completion providers run asynchronously?
- How can the plugin avoid blocking the shell while generating suggestions?
Do not immediately implement the feature.
First inspect the existing architecture and propose an implementation design that respects the current Hellish/plugin separation.
Expected deliverables
Produce:
- an architectural analysis of the existing Hellish line editor/plugin system;
- a proposed completion architecture;
- the minimal required Hellish/plugin API changes;
- the implementation;
- Make target completion;
- history-aware inline suggestions;
- keyboard interaction;
- tests;
- documentation and configuration examples;
- performance considerations and known limitations.
The final result should feel like a native Hellish interactive feature, while remaining cleanly isolated as a hellishrc_plugins capability.
The key principle is:
Hellish provides the shell;
hellishrc_pluginsprovides the intelligent interactive UX.
Activity
LESdylan commentedon Sep 26, 2026
The issue asks for the architecture analysis and a design before any implementation, so this comment is that first step. File references are to
develop.What the line editor is today
Input. hellish links the system GNU readline (8.0 or later reads in-process). There is no editor of its own;
src/editing/is a thin zsh-style layer on top of readline.repl_shell→readline_cmd→get_more_input_readline→rl_read_inproc→readline().rl_line_buffer/rl_point, and the shell keeps no copy between keys.Keys (all merged in #152):
bindworks like bash's, includingbind -xwithREADLINE_LINE/READLINE_POINT.zle -Nplusbindkeyrun a shell widget withBUFFER/LBUFFER/RBUFFER/CURSORin scope. AssigningLBUFFERmoves the cursor; assigningCURSORis not read back.bindkey KEY readline-commandbinds readline's own commands, andzle .forward-charcalls them from a widget.History.
hist_cmdsvector is the source of truth, mirrored into readline's list.HISTFILE,HISTSIZE,HISTCONTROLandHISTIGNOREare honoured.history-search-backward/-forward. hellishrc_plugins binds Up/Down to them whereverbindexists (branchfeat/history-prefix-search).Hooks.
HELLISH_PRECMD_FUNCS,HELLISH_PREEXEC_FUNCS,precmd/preexec,chpwd_functions.zle-line-init,zle-line-pre-redraw, …).rp_redisplay(src/platform/posix/rl_rprompt.c) already runs after every key, because it is readline's redisplay function. It paintsRPROMPT, but it runs no shell code.Text that is not input. Nothing exists for this today: no
POSTDISPLAY, noregion_highlight.RPROMPTis the only thing painted beside the line. It is written by the redisplay hook in one write (save cursor, clear to end of line, text, restore cursor), and readline never learns it is there. Ghost text needs exactly that mechanism.Completion.
complete/compgenwith-W,-Fand the actions.fix/compgen-actionsfixes-e -g -j -s -u, which listed files.-Ffunctions run in-process withCOMP_*set, onceshopt -s progcompis on (rc.d/70-completion.hshturns it on).Asynchronous work.
zle -Fis not supported.git statusscan for the prompt.Proposed split
In hellish (core), the smallest interface that cannot be written in shell:
zle-line-pre-redraw, the zsh name for "the buffer changed". It is a widget that hellish calls after an editing command changesrl_line_buffer/rl_point, withBUFFER/CURSORin scope and edits collected, like any other widget.rl_getc_hook, before it waits for the next key.POSTDISPLAY, the zsh variable. It holds text painted after the cursor in a dim style and never becomes part of the line:accept-line, history andfcnever see it.RPROMPT.hx_cap postdisplaycan detect, the same wayhooksandrpromptare detected.Everything else goes in hellishrc_plugins, as
plugins/suggest/:completespecs. Each is a function that appends candidates for the current buffer, so a new provider is a new function and not anotherif. Make comes first, as asked:Makefile,makefileorGNUmakefileis present;^[A-Za-z0-9_./-]+:and not:=), plusincluded files one level deep;.PHONY…) and pattern rules are excluded;conf/hellish.conf:HX_SUGGEST on|off;HX_SUGGEST_MAKE on|off;HX_SUGGEST_HISTORY_MAX;HX_SUGGEST_MIN_CHARS;HX_SUGGEST_STYLE.conf doctorand loads nothing. Disabling it changes no key.Tests
pytethat types, checks the dim text after the cursor, and checks that the cursor column has not moved;test/run.hshcases for each provider: no Makefile, several targets, partial target, special characters,include, a 5000-rule file;This touches the core in two places (
rl_getc.candrl_rprompt.c) and adds one widget name and one variable, both with zsh's meaning. If this split is what you want, I'll do it as two PRs: the core interface with its pty tests first, then the plugin.Generated by Claude Code
Merge pull request #168 from Univers42/feat/complete-make
qwO-Owp commentedon Oct 17, 2026
Progress update. Most of this follows @LESdylan's design above; one change is explained below.
Done: #168,
maketarget completion + the provider architectureMerged into
developat 0dacfc9, with every check green: CI, Platforms including macOS and WSL, and Docker distros.make cl<TAB>completesclean. Targets come fromGNUmakefile,makefileorMakefile(GNU make's order), parsed in-process: make is never run and nothing forks.{command, function}, so a new per-command completion is one row plus one function.makeandgmakeare the first rows, and they also work behindsudo,env X=1,&&and(.define/endef, every kind of assignment, directives, and%,$and.SPECIALtargets.a b c:,a::, backslash continuations (as GNU make reads them) and CRLF. Includes are followed one level deep.completespec still wins.-C/-f, or when no target matches.tests/complete_make_test.pyhas 24 case groups, in-process and forked, and all 10 mutants are killed.Next: inline suggestions
HELLISH_AUTOSUGGEST=1.HELLISH_SUGGEST_MAXbounds how far back it scans.RPROMPT.POSTDISPLAYcomes from the core interface you proposed. It is exposed tozlewidgets with zsh's meaning, so plugins in hellishrc_plugins can still paint their own text after the cursor.frontend_budget_test.pyenforces (at most 9 syscalls and 3 writes per key).erasedups.This issue stays open until PR3b/3c land. #136 (prefix search on Up/Down) is done in #167.
Merge pull request #169 from Univers42/feat/autosuggest
Merge pull request #175 from Univers42/feat/suggest-word-cycle
Merge pull request #188 from Univers42/feat/suggest-frecency
qwO-Owp commentedon Oct 18, 2026
Done: every part of this issue is merged into
developmake <TAB>targets, parsed in-process, cache invalidated on change{command, function}table)makeprefersmake re")make: targets you run come first)HELLISH_SUGGEST_MAX)frontend_budget_test.pyDeliberate departures from the spec, and why
hellishrc_pluginsplugin. Ghost text has to paint during readline's redisplay, and Alt-N/Alt-P have to bind keys without breaking user bindings. Neither is reachable from shell code without a new per-key callback API, which would cost a fork or an eval per key. The smallest interface for plugins is exposed instead:POSTDISPLAY(zsh's meaning) is readable and settable from zle widgets (feat(editor): inline history suggestions as dim ghost text (#140) #169).HELLISH_*variables, notconf/hellish.conf(no such builtin exists).HELLISH_AUTOSUGGEST,HELLISH_SUGGEST_MAXandHELLISH_SUGGEST_STRATEGY=recentare read at every prompt, soexport/unsettakes effect on the next line.HELLISH_HISTORY_PREFIXbelongs to [feat] Smart history #136.Known limits (Caveat-marked in the code)
makeranking reads words:make a && make bcredits both, andsudo make xisn't counted.The ranking is not released yet. It is in
develop, and the notes are drafted in #189 for the next release.