{"repo":"NousResearch/hermes-agent","public_id":"6448","display_label":"Ctrl+D CLI behavior: delete char vs EOF exit","summary":"These issues and pull requests address how the CLI handles Ctrl+D, specifically whether it should delete the character under the cursor or exit the session, with proposals to match standard readline/bash/zsh semantics (exit only on empty input).","subsystem":"hermes_cli","counts":{"members":8,"open_issues":1,"open_issues_distinct":1,"open_prs":0,"closed_issues":1,"merged_prs":1,"attempt_prs":5},"landed_fix":{"status":"merged_to_main","basis":"structural","pr":15383,"merged_at":"2026-04-24T22:17:10+00:00"},"resolution":{"state":"unresolved","by":null},"freshness":{"state":"stale","last_verified_at":"2026-04-24T22:17:10+00:00","is_stale":true},"grouping":{"backbone":"STRUCTURAL_SPANNING","link_density":0.26285714285714284},"fix_edges":[{"issue_number":6448,"pr_number":15383,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-04-24T22:17:10+00:00"},{"issue_number":8478,"pr_number":15383,"tier":"verified","basis":"superseded_ref","confidence":0.9,"recoverable_from_timeline":false,"pr_merged_at":"2026-04-24T22:17:10+00:00"}],"members":[{"kind":"issue","number":6448,"title":"Ctrl+D unconditionally exits CLI session even with text in input buffer","url":null,"state":"closed"},{"kind":"issue","number":8478,"title":"fix: Ctrl+D deletes character under cursor instead of sending EOF","url":null,"state":"open"},{"kind":"pr","number":4783,"title":"fix: Ctrl+D deletes char under cursor, exits only on empty input","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#15383","number":15383}],"category":"merged_via","implication":"superseded"},"merged":false},{"kind":"pr","number":6471,"title":"fix(cli): only exit on Ctrl+D when input buffer is empty","url":null,"state":"closed","close_reason":{"category":"silent_close","implication":"active"},"merged":false},{"kind":"pr","number":6476,"title":"[codex] Fix Ctrl+D EOF behavior in the CLI","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#15383","number":15383}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":8489,"title":"fix: Ctrl+D deletes char under cursor, only exits on empty input (bash/zsh behaviour)","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#4783","number":4783}],"category":"duplicate_of","implication":"duplicate"},"merged":false},{"kind":"pr","number":9252,"title":"fix(cli): make Ctrl-D respect Unix EOF semantics","url":null,"state":"closed","close_reason":{"refs":[{"kind":"pr","value":"#15383","number":15383},{"kind":"pr","value":"#4783","number":4783}],"category":"superseded_by_pr","implication":"superseded"},"merged":false},{"kind":"pr","number":15383,"title":"fix(cli): Ctrl+D = readline semantics (delete-char + EOF-only-when-empty)","url":null,"state":"merged","close_reason":{"category":"merged"},"merged":true,"is_fix_pr":true,"fix_tier":"verified","files_changed":["cli.py","scripts/release.py"],"fix_hunks":[{"file":"cli.py","hunks":["@@ -9525,9 +9525,20 @@ def handle_ctrl_c(event):\n         \n         @kb.add('c-d')\n         def handle_ctrl_d(event):\n-            \"\"\"Handle Ctrl+D - exit.\"\"\"\n-            self._should_exit = True\n-            event.app.exit()\n+            \"\"\"Ctrl+D: delete char under cursor (standard readline behaviour).\n+            Only exit when the input is empty — same as bash/zsh. Pending\n+            attached images count as input and block the EOF-exit so the\n+            user doesn't lose them silently.\n+            \"\"\"\n+            buf = event.app.current_buffer\n+            if buf.text:\n+                buf.delete()\n+            elif self._attached_images:\n+                # Empty text but pending attachments — no-op, don't exit.\n+                return\n+            else:\n+                self._should_exit = True\n+                event.app.exit()\n \n         _modal_prompt_active = Condition(\n             lambda: bool(self._secret_state or self._sudo_state)"]},{"file":"scripts/release.py","hunks":["@@ -68,6 +68,7 @@\n     \"185121704+stablegenius49@users.noreply.github.com\": \"stablegenius49\",\n     \"101283333+batuhankocyigit@users.noreply.github.com\": \"batuhankocyigit\",\n     \"255305877+ismell0992-afk@users.noreply.github.com\": \"ismell0992-afk\",\n+    \"[redacted:email]\": \"iRonin\",\n     \"[redacted:email]\": \"jvcl\",\n     \"[redacted:email]\": \"aj-nt\",\n     \"[redacted:email]\": \"francip\",\n"]}]}],"trust":{"default_tier":"verified","includes_suggested":false}}