diff --git a/app.py b/app.py
index ba877de..25e91c0 100644
--- a/app.py
+++ b/app.py
@@ -2566,8 +2566,8 @@ def clear_history():
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
- except Exception:
- pass
+ except Exception as exc:
+ logger.warning("Failed to remove execution log entry %s: %s", file_path, exc)
# Clear session logs
if os.path.exists(SESSION_LOG_DIR):
@@ -2578,8 +2578,8 @@ def clear_history():
os.unlink(file_path)
elif os.path.isdir(file_path):
shutil.rmtree(file_path)
- except Exception:
- pass
+ except Exception as exc:
+ logger.warning("Failed to remove session log entry %s: %s", file_path, exc)
return jsonify({
'success': True,
diff --git a/ui/app.js b/ui/app.js
index bf7725b..d2c13ba 100644
--- a/ui/app.js
+++ b/ui/app.js
@@ -119,6 +119,13 @@ function restoreUnlockedScripts(raw = {}) {
const RUN_BUTTON_IDLE_HTML = `Run`;
+const LOWERCASE_COMMANDS = new Set([
+ 'awk', 'bash', 'cat', 'cd', 'chmod', 'clear', 'cp', 'curl', 'docker',
+ 'echo', 'find', 'git', 'grep', 'head', 'ls', 'mkdir', 'mv', 'node',
+ 'npm', 'npx', 'pnpm', 'pwd', 'python', 'python3', 'rm', 'sed', 'sh',
+ 'tail', 'touch', 'yarn'
+]);
+
// ─── SVG Icons ─────────────────────────────────────────────
const ICONS = {
docker: ``,
@@ -1369,6 +1376,39 @@ async function executeScriptWithArguments(relPath, argumentsText) {
}
}
+function autocorrectCommandCase(rawCommand) {
+ const match = rawCommand.match(/^(\s*)([^\s]+)([\s\S]*)$/);
+ if (!match) return { command: rawCommand, corrected: false };
+
+ const [, leadingWhitespace, commandToken, rest] = match;
+ const lowerToken = commandToken.toLowerCase();
+
+ if (commandToken === lowerToken || !LOWERCASE_COMMANDS.has(lowerToken)) {
+ return { command: rawCommand, corrected: false };
+ }
+
+ return {
+ command: `${leadingWhitespace}${lowerToken}${rest}`,
+ corrected: true,
+ originalToken: commandToken,
+ correctedToken: lowerToken
+ };
+}
+
+function runCliInputCommand(cliInput) {
+ const rawCmd = cliInput.value.trim();
+ if (!rawCmd) return;
+
+ const correction = autocorrectCommandCase(rawCmd);
+ if (correction.corrected) {
+ cliInput.value = correction.command;
+ notify(`Corrected ${correction.originalToken} to ${correction.correctedToken}.`, 'info');
+ }
+
+ execCommand(correction.command);
+ cliInput.value = '';
+}
+
async function execCommand(cmd) {
if (!cmd.trim()) return;
const termId = state.activeTerminalId;
@@ -3505,11 +3545,7 @@ function bindEvents() {
const cliInput = document.getElementById('cli-input');
cliInput.addEventListener('keydown', (e) => {
if (e.key === 'Enter') {
- const cmd = cliInput.value.trim();
- if (cmd) {
- execCommand(cmd);
- cliInput.value = '';
- }
+ runCliInputCommand(cliInput);
}
if (e.key === 'ArrowUp') {
e.preventDefault();
@@ -3536,11 +3572,7 @@ function bindEvents() {
// Run Command button
document.getElementById('btn-run-cmd').addEventListener('click', () => {
- const cmd = cliInput.value.trim();
- if (cmd) {
- execCommand(cmd);
- cliInput.value = '';
- }
+ runCliInputCommand(cliInput);
});
// Keyboard shortcuts