Skip to content

Instantly share code, notes, and snippets.

@mindbound
Created June 29, 2025 00:23
Show Gist options
  • Save mindbound/d06dcd9473626d23767a6d004e8339fd to your computer and use it in GitHub Desktop.
Save mindbound/d06dcd9473626d23767a6d004e8339fd to your computer and use it in GitHub Desktop.
History persistence for OpenOS

History persistence for OpenOS

Installation

  1. Add the path to historysvc.lua to .shrc
  2. Copy history.lua to a directory in $PATH
local args = {...}
local shell = require("shell")
local HISTORY_FILE = (os.getenv("HOME") or "/home") .. "/.history"
local function load_history()
local history = {}
local fs = require("filesystem")
if fs.exists(HISTORY_FILE) then
local file = io.open(HISTORY_FILE, "r")
if file then
for line in file:lines() do
line = line:match("^%s*(.-)%s*$")
if #line > 0 then
table.insert(history, line)
end
end
file:close()
end
end
return history
end
local history = load_history()
if #args == 0 then
if #history == 0 then
print("No history available.")
else
for i = 1, #history do
print(string.format("%4d %s", i, history[i]))
end
end
elseif args[1] == "-c" then
local file = io.open(HISTORY_FILE, "w")
if file then
file:close()
print("History cleared.")
end
elseif args[1] == "-q" then
print("Stopping history service...")
local computer = require("computer")
computer.pushSignal("history_service_stop")
print("History service stop signal sent.")
elseif args[1] == "-h" or args[1] == "--help" then
print("Usage: history [-c|-q|-h] [number]")
print(" (no args) Show entire history with numbers")
print(" -c Clear history")
print(" -q Stop history service")
print(" -h Show this help message")
print(" number Execute command with that history number")
elseif tonumber(args[1]) then
local num = tonumber(args[1])
if num > 0 and num <= #history then
local command = history[num]
print("Executing: " .. command)
shell.execute(command)
else
print("Error: History entry " .. num .. " does not exist.")
print("Available history entries: 1-" .. #history)
end
else
print("Error: Invalid argument '" .. args[1] .. "'")
print("Use 'history -h' for usage information.")
end
local fs = require("filesystem")
local event = require("event")
local sh = require("sh")
local HISTORY_FILE = (os.getenv("HOME") or "/home") .. "/.history"
local MAX_HISTORY = tonumber(os.getenv("HISTSIZE")) or 100
local history = {}
local service_running = false
local function load_history()
history = {}
if fs.exists(HISTORY_FILE) then
local file = io.open(HISTORY_FILE, "r")
if file then
for line in file:lines() do
line = line:match("^%s*(.-)%s*$")
if #line > 0 then
table.insert(history, line)
end
end
file:close()
end
end
end
local function save_command(command)
command = command:match("^%s*(.-)%s*$")
if #command == 0 or (#history > 0 and history[#history] == command) then
return
end
if command:match("^history%s") or command == "history" then
return
end
table.insert(history, command)
if #history > MAX_HISTORY then
table.remove(history, 1)
local file = io.open(HISTORY_FILE, "w")
if file then
for _, cmd in ipairs(history) do
file:write(cmd, "\n")
end
file:close()
end
else
local file = io.open(HISTORY_FILE, "a")
if file then
file:write(command, "\n")
file:close()
end
end
end
local function hook_shell_input()
local tty = require("tty")
local original_window = tty.window
local window_proxy = setmetatable({}, {
__index = original_window,
__newindex = function(_, key, value)
if key == "cursor" and value and type(value) == "table" then
for i = #history, math.max(1, #history - MAX_HISTORY + 1), -1 do
local idx = #history - i + 1
if idx <= MAX_HISTORY then
value[idx] = history[i]
end
end
if not value.hint then
value.hint = sh.hintHandler
end
end
original_window[key] = value
end
})
tty.window = window_proxy
local core_cursor = require("core/cursor")
if core_cursor.read then
local original_cursor_read = core_cursor.read
core_cursor.read = function(cursor)
local result = original_cursor_read(cursor)
if result and type(result) == "string" then
local trimmed = result:match("^%s*(.-)%s*$")
if #trimmed > 0 and trimmed ~= "" then
pcall(save_command, trimmed)
end
end
return result
end
end
end
local function initialize()
if service_running then
return
end
print("Loading shell history service...")
load_history()
print("Loaded " .. #history .. " commands from history")
hook_shell_input()
service_running = true
print("Shell history service started.")
print("Commands will be logged to " .. HISTORY_FILE)
print("Use 'history' command to view saved commands, 'history N' to execute command N.")
end
local function cleanup()
if not service_running then
return
end
service_running = false
print("Shell history service stopped.")
end
local function on_service_stop()
cleanup()
print("History service stopped by user request.")
os.exit()
end
event.listen("history_service_stop", on_service_stop)
initialize()
print("History service initialization complete.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment