-- main.lua — entry point -- Phase 0: arg parsing, config load, REPL start. -- See docs/PHASE0.md §4, §10. -- Make project modules and the vendored dkjson resolvable from the repo root. -- Run aish with the repo root as cwd; PTY-relative resolution lands later. package.path = "./?.lua;./vendor/?.lua;" .. package.path local USAGE = [[ aish — AI-augmented conversational shell. Usage: luajit main.lua [--config ] [--help] Config resolution order (PHASE0.md §10): 1. --config 2. $AISH_CONFIG 3. ~/.config/aish/config.lua 4. ./config.lua ]] local function parse_args(argv) local out = {} local i = 1 while i <= #argv do local a = argv[i] if a == "--config" then out.config = argv[i + 1] i = i + 2 elseif a == "--help" or a == "-h" then out.help = true i = i + 1 else io.stderr:write("aish: unrecognized argument: " .. a .. "\n") os.exit(2) end end return out end local function load_config(opts) -- --config is explicit: use exactly that path or fail. No silent fallback. if opts.config then local f = io.open(opts.config, "r") if not f then error("aish: --config " .. opts.config .. ": cannot open") end f:close() return dofile(opts.config), opts.config end local home = os.getenv("HOME") or "" local candidates = {} local function push(p) if p and p ~= "" then candidates[#candidates + 1] = p end end push(os.getenv("AISH_CONFIG")) push(home .. "/.config/aish/config.lua") push("./config.lua") for _, path in ipairs(candidates) do local f = io.open(path, "r") if f then f:close(); return dofile(path), path end end error("aish: no config.lua found (tried: " .. table.concat(candidates, ", ") .. ")") end local function main(argv) local opts = parse_args(argv or {}) if opts.help then io.write(USAGE); return end local config, config_path = load_config(opts) io.stderr:write(("aish: loaded config from %s\n"):format(config_path)) local repl = require("repl") repl.run(config) end main(arg)