Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
389 commits
Select commit Hold shift + click to select a range
e8dea48
fix(config): warn loudly on YAML parse failure instead of silent defa…
teknium1 May 11, 2026
61b95d9
docs(security): rewrite policy around OS-level isolation as the boundary
jquesnelle May 5, 2026
c041d4c
changes from feedback
jquesnelle May 6, 2026
df2cf76
feat: add stocks & finance skill (Yahoo Finance, no API key)
Mar 19, 2026
4f936a9
chore(skills/stocks): relocate to optional-skills/finance/stocks/
teknium1 May 11, 2026
6396080
chore(skills/stocks): tighten SKILL.md to modern format
teknium1 May 11, 2026
ae4288f
chore(release): AUTHOR_MAP entry for Mibayy clawhub email
teknium1 May 11, 2026
74c1316
fix(discord): typing indicator task not cleaned up after API error
0xbyt4 Mar 22, 2026
e448fdf
fix(auxiliary): cache 402'd providers as unhealthy with TTL to stop p…
teknium1 May 11, 2026
854d21b
feat(terminal,cli): docker_extra_args + display.timestamps
Mibayy May 11, 2026
b5f0676
feat(deps): add hindsight-client as optional dependency (#21818)
alt-glitch May 11, 2026
520d413
feat(nix): add extraDependencyGroups for sealed venv extras (#21817)
alt-glitch May 11, 2026
b4c2c8f
fix(nix): replace chown -R with targeted find in container entrypoint…
alt-glitch May 11, 2026
cdbccb3
fix(kanban): route gateway create auto-subscribe to explicit board
Frowtek May 10, 2026
876e93f
fix(kanban): call kanban_block on iteration-budget exhaustion to prev…
liuhao1024 May 10, 2026
b209f09
fix(kanban): restore HERMES_KANBAN_BOARD after scoped slash override
Sylw3ster May 10, 2026
5ce9d9a
fix(kanban): inject HERMES_HOME into worker subprocess env
TurgutKural May 10, 2026
43c7952
fix(send_message): allow kanban workers to call send_message
dmnkhorvath May 10, 2026
54c6a99
test(send_message): cover _check_send_message gating paths
dmnkhorvath May 10, 2026
ea97293
fix(kanban): use localized column label in select-all aria label
smwbev May 11, 2026
df914be
fix(kanban): treat archived parent tasks as terminal for dependency r…
Ninso112 May 10, 2026
6b6956c
chore: add salvage contributors to AUTHOR_MAP
kshitijk4poor May 11, 2026
9b2f05f
fix: guard resolve_profile_env against missing profile dirs
kshitijk4poor May 11, 2026
6e99c9f
chore: remove unused sentinel in test_send_message_tool
kshitijk4poor May 11, 2026
a37a413
fix(terminal): block sudo -S password guessing when SUDO_PASSWORD is …
May 9, 2026
3884bbc
fix(approval): catch sudo with stdin/askpass/shell privilege flags
fr33d3m0n May 7, 2026
5a0ace3
chore: AUTHOR_MAP entries for sudo-hardening salvage contributors
kshitijk4poor May 11, 2026
15a04fc
revert: roll back /goal checklist + /subgoal feature stack (#23813)
teknium1 May 11, 2026
5b753c0
fix(agent): catch ChatGPT-account Codex data-URL rejection so images …
teknium1 May 11, 2026
971c1fd
fix: make web UI build output decoding robust on Windows
VinceZcrikl May 11, 2026
7b9df6d
chore: AUTHOR_MAP entry for VinceZcrikl noreply (#23647)
teknium1 May 11, 2026
6e7e4ac
fix(dashboard): fallback to stale dist, retry build, add --skip-build…
ygd58 May 11, 2026
4e1a474
fix(dashboard): validate dist exists when --skip-build is set
teknium1 May 11, 2026
baf9e26
rebuild model catalog
rob-maron May 11, 2026
5923d92
fix: use TUI modal for slash confirmations
zhengyn0001 May 11, 2026
a998bf7
fix(cli): defensive _slash_confirm_state access + AUTHOR_MAP
teknium1 May 11, 2026
4856be0
fix(/model): surface Nous Portal models from remote catalog manifest …
teknium1 May 11, 2026
e4347a2
chore: ruff auto-fixes — collapsible-else-if, if-stmt-min-max, dict.f…
kshitijk4poor May 11, 2026
3bf05d8
fix(cli,tui): align CJK / wide-char markdown tables (#23863)
teknium1 May 11, 2026
c752750
fix(auxiliary): evict async wrappers on poisoned client (follow-up to…
wuli666 May 11, 2026
456d7e7
chore(release): add AUTHOR_MAP entry for wuli666
teknium1 May 11, 2026
b5f43a9
chore: ruff auto-fix PLR6201 — tuple → set in membership tests (#23937)
kshitijk4poor May 11, 2026
163220c
feat(prompt-cache): cross-session 1h prefix cache for Claude on Anthr…
teknium1 May 11, 2026
d378a36
chore: ruff auto-fix C401, C416, C408, PLR1722 (#23940)
kshitijk4poor May 11, 2026
a4acbd1
feat: expose HERMES_SESSION_ID to agent tools via ContextVar + env (#…
alt-glitch May 11, 2026
bbd09b2
fix: correct context-length resolution for kimi-k2.6 on Ollama Cloud …
kshitijk4poor May 11, 2026
518d2b6
fix(model-metadata): skip OpenRouter for known providers, add kimi/mo…
nicoechaniz May 11, 2026
a80fb19
chore: add nicoechaniz to AUTHOR_MAP
kshitijk4poor May 11, 2026
37a107a
feat(ui-tui): resolve markdown links to readable page titles (#24013)
OutThisLife May 11, 2026
a8fe20c
refactor(tui): bundle with esbuild, drop runtime node_modules
ethernet8023 Apr 30, 2026
72c081e
fix(nix): refresh npm lockfile hashes
github-actions[bot] Apr 30, 2026
2a62d11
refactor(docker): drop manual @hermes/ink build, rely on esbuild bundle
ethernet8023 Apr 30, 2026
71ddc24
fix(tui): update comments
ethernet8023 Apr 30, 2026
1f21822
fix(tui): don't hardcode /home/bb
ethernet8023 Apr 30, 2026
d80f60e
fix(tui): update README
ethernet8023 Apr 30, 2026
7eebd99
refactor(tui): simplify TUI build logic, remove stale staleness checks
ethernet8023 May 11, 2026
32f2e1d
fix(cli): vertical fallback for markdown tables wider than terminal (…
teknium1 May 11, 2026
40d882d
fix(dashboard): MiniMax 'Login' button launched Claude OAuth (#22832)
ahmedbadr3 May 9, 2026
26d4627
chore(release): add AUTHOR_MAP entry for ahmedbadr3
teknium1 May 11, 2026
a4dc106
feat(computer-use): refresh cua-driver on `hermes update` + add `inst…
teknium1 May 12, 2026
5cb4563
fix(nous): surface Portal-flagged free models in picker even when cur…
teknium1 May 12, 2026
d582fa7
fix(tui-clipboard): skip native safety net on OSC52-capable terminals…
benbarclay May 12, 2026
0f0688f
fix(cache): route Nous Portal Qwen through Portal-Claude cache pathwa…
teknium1 May 12, 2026
323990d
fix kimi
rob-maron May 12, 2026
e63b4d1
fix guard
rob-maron May 12, 2026
eded2e3
remove comments
rob-maron May 12, 2026
5fd0f05
fix comment
rob-maron May 12, 2026
353a18f
fix(minimax): harden OAuth dashboard and runtime
austinpickett May 12, 2026
cd5f348
add client marker tag on aux inference requests
rewbs May 12, 2026
0326c9f
fix(docs): repair Voice & TTS provider table
May 12, 2026
23ad185
fix(deps): unbreak [all] install — drop mistralai while PyPI quaranti…
teknium1 May 12, 2026
2279551
feat(security): supply-chain advisory checker + lazy-install framewor…
teknium1 May 12, 2026
67e1f19
docs: remove public advisory page (handle community comms separately)…
teknium1 May 12, 2026
bc404fb
feat(agent): per-turn file-mutation verifier footer (#24498)
teknium1 May 12, 2026
d274fb8
Use nous portal as model metadata authority (#24502)
rob-maron May 12, 2026
3399e4b
fix(install): surface uv install + uv.lock sync errors instead of sil…
teknium1 May 12, 2026
9870736
union paid recs from nous portal with static list (#24509)
rob-maron May 12, 2026
3e44575
fix(cli): parse positional insights days
helix4u May 12, 2026
0e53237
fix(dashboard): UI polish — modals, layout, consistency, test fixes
austinpickett May 12, 2026
5d8a5af
fix(gateway): detect stale scoped locks via cmdline when start_time i…
pkyanam May 11, 2026
90e9c33
test(gateway): patch _pid_exists instead of os.kill for scoped-lock t…
teknium1 May 12, 2026
4b0e64e
chore(release): map kyanam.preetham@gmail.com → pkyanam
teknium1 May 12, 2026
a288178
📝 docs(kanban): clarify dependent task gating
BlackishGreen33 May 12, 2026
f2e4e9e
fix(docs): correct broken internal links to webhooks and mlops skill …
luarss May 12, 2026
058aba0
chore(release): add AUTHOR_MAP entry for luarss
teknium1 May 12, 2026
8434103
fix(gateway): enqueue SSE EOS sentinel on task completion
May 12, 2026
8819710
fix(install): use `--extra all` not `--all-extras`; drop lazy-covered…
teknium1 May 12, 2026
6a9ee3a
feat(browser): support externally managed Camofox sessions
db-aeon May 11, 2026
d22bd46
chore(camofox): document new env vars + AUTHOR_MAP entry
teknium1 May 12, 2026
d66debc
docs(camofox): expand externally-managed sessions section (#24584)
teknium1 May 12, 2026
a2c91d6
fix(daytona): migrate legacy-sandbox lookup to cursor-based list() (#…
teknium1 May 12, 2026
25ab656
feat(lsp): semantic diagnostics from real language servers in write_f…
teknium1 May 12, 2026
79d53b4
fix(pricing): add deepseek-v4-pro to official docs pricing table
zccyman May 12, 2026
7ce1492
chore(release): add AUTHOR_MAP entries for zccyman and Osraka
teknium1 May 12, 2026
f7574cd
fix(gateway): consult lock record argv when cmdline unreadable in sco…
AhmetArif0 May 12, 2026
4accfff
chore: AUTHOR_MAP entry for AhmetArif0 (PR #24600)
teknium1 May 12, 2026
e6d1bd6
feat(gateway): wire clarify tool with inline keyboard buttons on Tele…
teknium1 May 12, 2026
6a92a13
fix: include arg-taking commands in Telegram menu
ryptotalent May 12, 2026
6e1f4b9
chore(release): add AUTHOR_MAP entry for ryptotalent
teknium1 May 12, 2026
0c48e2e
fix(auxiliary): pass cfg_base_url and cfg_api_key when resolving task…
hookinglau May 12, 2026
5e13381
chore(release): add AUTHOR_MAP entry for hookinglau
teknium1 May 12, 2026
a2528c6
fix(dashboard): skip browser-open on headless Linux to prevent proces…
AllynSheep May 12, 2026
33e71a0
chore(release): add AUTHOR_MAP entries for AllynSheep
teknium1 May 12, 2026
f38f1bd
fix(dashboard): display real config path on Config page
aqilaziz May 12, 2026
99b74d2
chore(release): add AUTHOR_MAP entries for aqilaziz
teknium1 May 12, 2026
b2a41de
fix(dashboard): rescan plugins when cached directory is removed
liuhao1024 May 12, 2026
2391edd
fix(tui): clear scrollback buffer on startup to prevent tmux scrollba…
laoli-no1 May 12, 2026
adfd8f5
chore(release): add AUTHOR_MAP entries for laoli-no1
teknium1 May 12, 2026
d4b75e0
fix(cli): use display-width for response box header label to support CJK
NorethSea May 12, 2026
2e43446
chore(release): add AUTHOR_MAP entries for NorethSea
teknium1 May 12, 2026
e6e9fee
fix(cli): @-file completion crash on Windows when paths aren't cp1252…
JamesX88 May 12, 2026
8583113
chore(release): add AUTHOR_MAP entries for JamesX88
teknium1 May 12, 2026
74b9d20
fix(telegram): clear in-progress reaction on cancelled processing (#2…
teknium1 May 13, 2026
acc9766
fix(lsp): typescript SDK install + tsc-missing skip + shellcheck warn…
teknium1 May 13, 2026
4291346
docs(gateway): mention Weixin in gateway help and docstrings
wuwuzhijing May 13, 2026
4a43a38
fix(ci): install ripgrep in e2e job
wesleysimplicio May 13, 2026
bae266f
fix(ci): bump e2e job timeout to 15 minutes
wesleysimplicio May 13, 2026
9fc84ac
fix(gateway): reduce systemd restart delay
silv-mt-holdings May 13, 2026
a6dc9e4
fix(send_message): recognize XMPP JIDs as explicit targets
Quarkex May 13, 2026
0ecc524
fix(doctor): skip /models health check for providers that don't suppo…
jak983464779 May 13, 2026
31d0d35
fix(web): add Bearer auth header for Tavily /crawl endpoint
McClean May 13, 2026
9f715cf
fix(cron): include whatsapp in _HOME_TARGET_ENV_VARS
dhruv-saxena May 13, 2026
c25b728
fix(cache): drop ttl=1h on Portal Qwen — Alibaba upstream is 5m-only …
teknium1 May 13, 2026
21ff33b
fix(retry): use float() for Retry-After header to handle sub-second v…
ryptotalent May 13, 2026
0b52412
fix(signal): handle group messages from linked devices in syncMessage…
ms-alan May 13, 2026
fb16621
fix(voice_mode): detect audio in WSL when sd.query_devices() returns …
RhombusMaximus May 13, 2026
57252f4
fix(tui): use TERMINAL_CWD in _session_info for accurate status line …
Dangooy May 13, 2026
9b79e10
docs(lsp): document follow-up fixes from #24630 (#24709)
teknium1 May 13, 2026
5987a83
fix(gateway): add chat_id to hook_ctx for message source tracking
diablozzc May 13, 2026
c4a3aeb
fix(install): use stash@{0} instead of git rev-parse refs/stash for a…
Jwd-gity May 13, 2026
2cacf28
fix(telegram): use thread fallback helper in slash-confirm result send
AhmetArif0 May 13, 2026
65b426f
fix(prompt_builder): inject tool-use enforcement for GLM models
ALIYILD May 13, 2026
b2e7893
fix(line): use build_source instead of nonexistent create_source
mizgyo May 13, 2026
da511ce
fix(wecom): update connection status after WebSocket reconnection
02356abc May 13, 2026
351a07e
fix(tools): forward thread_id via metadata in _send_via_adapter live …
AhmetArif0 May 13, 2026
ae413be
fix(gateway): make WhatsApp npm install timeout configurable
liuhao1024 May 13, 2026
cc0b6bb
fix(test): use i18n t() for restart drain assertion
alblez May 13, 2026
6ac7403
fix(agent): clear stale config context_length on model switch
AgentArcLab May 13, 2026
f84d5e9
fix: approval DELETE pattern DOTALL flag allows newline bypass
amathxbt May 13, 2026
98e663d
fix(cache): kill long-lived prefix layout — system prompt is now byte…
teknium1 May 13, 2026
2132f2e
feat(nous): unified client=hermes-client-v<version> tag on every Port…
teknium1 May 13, 2026
da8a224
feat(providers): rename Alibaba Cloud to Qwen Cloud, reorder picker (…
teknium1 May 13, 2026
b9726d7
fix(docker): chown .venv to hermes so lazy_deps can install platform …
alt-glitch May 13, 2026
82afa3c
fix(cli): add 'lsp' to _BUILTIN_SUBCOMMANDS so plugin discovery is sk…
briandevans May 13, 2026
ebeb3a5
fix: classify landed file mutations with diagnostics
GodsBoy May 13, 2026
0f2ba5d
refactor: import FILE_MUTATING_TOOL_NAMES from shared module
kshitijk4poor May 13, 2026
9edf3d7
fix(gateway): add lazy_deps.ensure() to slack, matrix, dingtalk, feis…
alt-glitch May 13, 2026
92882de
ci(docker): split :latest (releases only) from :main (main HEAD)
ethernet8023 May 13, 2026
9992b98
fix(cli): repair broken zsh completion generation
ZeterMordio Apr 17, 2026
8349847
test(cli): strengthen zsh completion regression coverage
ZeterMordio May 10, 2026
2da1453
refactor(profiles): remove dead generate_bash_completion / generate_z…
teknium1 May 13, 2026
ae49047
chore(release): map anton.kuenzi@gmail.com -> ZeterMordio
teknium1 May 13, 2026
b5f17db
fix(security): reduce unnecessary shell=True in subprocess calls
iuyup Apr 8, 2026
0beebe8
chore(release): map iuyup author for PR #6155 salvage
teknium1 May 13, 2026
149d14f
feat(custom): prompt and persist explicit api_mode for custom providers
littlewwwhite May 13, 2026
75bfd14
fix(setup): drop post-setup chat handoff (#25067)
teknium1 May 13, 2026
8418c1b
fix(tools): refuse skill_view name collisions instead of guessing
teknium1 May 13, 2026
780ad22
fix(cli): preserve startup banner on terminal resize
vominh1919 May 10, 2026
eab7c5b
tui: make URLs clickable + hover-highlight in any terminal (#25071)
OutThisLife May 13, 2026
a4c4b47
fix(gateway): preserve queued follow-up transcript history
vKongv May 13, 2026
86fd8d1
test(gateway): make queued follow-up regression generic
vKongv May 13, 2026
99b92cd
chore(release): map mgongzai author for PR #25183 salvage
teknium1 May 13, 2026
c22d63f
feat(video_gen): unified video_generate tool with pluggable provider …
teknium1 May 13, 2026
2883e64
feat(codex-runtime): optional codex app-server runtime for OpenAI/Cod…
teknium1 May 14, 2026
8cda32a
feat: add EVM multi-chain skill (8 chains, 14 commands)
May 13, 2026
5d514f8
feat(skills): merge blockchain/base into blockchain/evm; salvage PR #…
ethernet8023 May 13, 2026
fb96e93
chore(skills/evm): tighten SKILL.md to modern format
teknium1 May 14, 2026
7f80643
docs: close in-tree memory plugins to new PRs and codify skill standa…
teknium1 May 14, 2026
5a64e50
fix(tools-config): write video_gen.provider on Reconfigure tool path …
teknium1 May 14, 2026
742cea3
perf(tools): cache get_nous_auth_status() and load_env() to fix slow …
teknium1 May 14, 2026
1d97e03
feat(slack): support !cmd as alternate prefix for slash commands in t…
teknium1 May 14, 2026
f4174a6
fix(tts): update MiniMax default model to speech-02 and correct API e…
pty819 May 6, 2026
296b4fe
fix(tts): align MiniMax TTS defaults with current API and add GroupId…
teknium1 May 14, 2026
714f51b
fix(install): skip browser download when system chromium exists
helix4u May 14, 2026
17710f5
fix(gateway): complete lazy-install rebind for slack/feishu/matrix + …
alt-glitch May 14, 2026
f705ac4
feat(plugins): add thread-local tool whitelist to pre_tool_call gate
WorldWriter Apr 29, 2026
43f991a
fix(memory): hit prefix cache in background review fork
WorldWriter Apr 29, 2026
3794274
chore(release): map WorldWriter for PR #17276 salvage
teknium1 May 14, 2026
36b0b61
fix(memory): pin session_start + session_id on background review fork
teknium1 May 14, 2026
3c65bfd
test(memory): cover cache-parity + runtime whitelist on background re…
teknium1 May 14, 2026
b6a4f21
chore(release): map jake@nousresearch.com and simpolism@gmail.com to …
simpolism May 13, 2026
5b37453
feat(dashboard): hide token/cost analytics behind config flag (defaul…
teknium1 May 14, 2026
8d2a6bb
feat(codex-runtime): skip unavailable plugins during migration (#25437)
teknium1 May 14, 2026
cbcd38c
refactor(plugins): add apply_yaml_config_fn registry hook
kshitijk4poor May 13, 2026
f8b6376
fix(discord): keep free-response channels inline
simpolism May 10, 2026
8f1d5a7
feat(discord): add thread_require_mention for multi-bot threads
simpolism May 14, 2026
0372fd1
chore(release): map jake@nousresearch.com → simpolism
teknium1 May 14, 2026
a5a8a29
feat(compression): make protect_first_n configurable
simpolism May 14, 2026
ca3650c
fix(compression): keep default protect_first_n at 3 + align ABC
teknium1 May 14, 2026
b9b859d
refactor(inventory): extract shared ConfigContext + build_models_payload
kshitijk4poor May 11, 2026
148f7ff
refactor(cli): route /model picker through shared inventory module
teknium1 May 14, 2026
d0c7f83
feat(web): add WebSearchProvider ABC mirroring image_gen template
kshitijk4poor May 13, 2026
a72018b
feat(web): add web search provider registry mirroring image_gen pattern
kshitijk4poor May 13, 2026
b3322a6
feat(plugins): add ctx.register_web_search_provider() facade
kshitijk4poor May 13, 2026
306c686
feat(web): brave_free plugin (first migration from tools/web_providers/)
kshitijk4poor May 13, 2026
12e9d74
feat(web): ddgs plugin (second migration)
kshitijk4poor May 13, 2026
618b97b
feat(web): searxng plugin (search-only, third migration)
kshitijk4poor May 13, 2026
86c0fd0
refactor(web): dispatch brave-free/ddgs/searxng via web_search_registry
kshitijk4poor May 13, 2026
04874b9
feat(tools): mirror image_gen plugin-injection in Web Search picker
kshitijk4poor May 13, 2026
4af7dbf
refactor(web): remove legacy in-tree provider modules
kshitijk4poor May 13, 2026
3625b9c
fix(plugins): filter resolution by is_available() in web + image_gen …
kshitijk4poor May 13, 2026
5e94754
feat(web): extend ABC with supports_crawl and async-extract semantics
kshitijk4poor May 13, 2026
c59efcc
feat(web): exa plugin — first multi-capability migration (search + ex…
kshitijk4poor May 13, 2026
5a8f8ef
feat(web): parallel plugin — first async-extract plugin
kshitijk4poor May 13, 2026
6b62719
feat(web): tavily plugin — first three-capability plugin (search + ex…
kshitijk4poor May 13, 2026
0993b17
feat(web): firecrawl plugin — largest migration (search + async extra…
kshitijk4poor May 13, 2026
ec7f6b5
refactor(web): dispatch all three tools through web_search_registry
kshitijk4poor May 13, 2026
685c154
fix(web): preserve firecrawl crawl + website-policy gate after migration
kshitijk4poor May 13, 2026
b4883d2
refactor(web): delete inline vendor helpers, re-export from plugins
kshitijk4poor May 13, 2026
6754947
refactor(tools): drop hardcoded web picker rows + skiplist; plugins a…
kshitijk4poor May 13, 2026
5a0a6d8
refactor(web): delete legacy tools/web_providers/ directory + migrate…
kshitijk4poor May 13, 2026
4c22c40
test(plugins): tests/plugins/web/ — coverage for the 7-plugin migration
kshitijk4poor May 13, 2026
63041a9
feat(web): firecrawl plugin natively supports crawl; delete legacy in…
kshitijk4poor May 13, 2026
4087809
fix(web): align _LEGACY_PREFERENCE with legacy 7-provider order + doc…
kshitijk4poor May 13, 2026
d469951
fix(web): preserve top-level error envelope on unconfigured systems
kshitijk4poor May 13, 2026
ee37119
fix(honcho): respect HOME-anchored default profile fallback
iacker Apr 8, 2026
e1ad28f
fix(tests): exercise profile-mode HERMES_HOME for honcho fallback
teknium1 May 14, 2026
4745597
fix(clipboard): reject non-png clipboard images when png normalizatio…
Dusk1e Apr 8, 2026
d349429
fix(clipboard): only read PNG signature bytes, not entire file
teknium1 May 14, 2026
0353519
feat(goals): /subgoal — user-added criteria appended to active /goal …
teknium1 May 14, 2026
b343046
fix(cli): harden skin yaml parsing for invalid section types
Dusk1e Apr 8, 2026
c00cd20
fix(tests): correct skin engine test API call
teknium1 May 14, 2026
a830c10
fix: simplify ACP approval bridging
mrshu Apr 8, 2026
89633ae
chore(release): add AUTHOR_MAP entry for mrshu
teknium1 May 14, 2026
2cd8529
chore(release): add AUTHOR_MAP entries for 25-PR new-contributor batch
teknium1 May 14, 2026
6fa66b4
docs(user-guide): point tirith link to correct repo
domtriola May 14, 2026
df9dce5
docs(lsp): replace "git worktree" with "git repository" in LSP docs
freqyfreqy May 14, 2026
0f9bb34
fix(agent): add Xiaomi MiMo to reasoning_content echo-back providers
ephron-ren May 14, 2026
646f086
fix(discord): handle forwarded messages via message_snapshots
1RB May 14, 2026
4177691
fix(auxiliary): skip providers without credentials immediately
AllynSheep May 14, 2026
777f356
fix: gateway PID detection fails on Windows (two issues)
Tianyu199509 May 14, 2026
752b70b
feat(whatsapp): surface quoted reply metadata
kfa-ai May 14, 2026
d7ca2eb
fix: show context compaction status
raymaylee May 14, 2026
51d9bed
fix(gateway): make Feishu ws connect override sync to preserve contex…
pearjelly May 14, 2026
64b9ef6
fix: do not inherit api_mode when delegating across providers
fu576 May 14, 2026
767fa4c
fix(gateway): keep QQBot reconnect loop alive
magic524 May 14, 2026
0aed501
fix(auxiliary): forward custom_providers to compression model context…
PaTTeeL May 14, 2026
fb2551b
fix(background-review): silence memory provider teardown output leak
ayushere May 14, 2026
9b3531a
feat: add NovitaAI as LLM provider
Alex-yang00 Apr 10, 2026
3aabdb8
docs: update NovitaAI description to "90+ models, pay-per-use"
Alex-yang00 Apr 13, 2026
68bc36c
test(novita): cache pricing, add provider test coverage, AUTHOR_MAP e…
kshitijk4poor May 14, 2026
0713d05
docs: update NovitaAI provider positioning (#25532)
Alex-yang00 May 14, 2026
85b9565
Revert "chore(update) .gitignore to exclude local environment files"
AlexFoxD May 14, 2026
6440846
Potential fix for pull request finding
AlexFoxD May 21, 2026
d325142
Remove '-y' flag from parser options
AlexFoxD May 21, 2026
cc841f3
Remove custom provider mappings from auxiliary_client
AlexFoxD May 21, 2026
d14d6ff
Change OpenAI alias from 'custom' to 'openrouter'
AlexFoxD May 21, 2026
5c9be93
Update package-lock.json
AlexFoxD May 21, 2026
81cebb2
Add headless loop and centralized cleanup
AlexFoxD May 21, 2026
09c3f8b
Merge branch 'fix/headless-mode-windows' of https://github.com/AlexFo…
AlexFoxD May 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 111 additions & 69 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -1491,7 +1491,11 @@ def _replay_output_history() -> None:
_OUTPUT_HISTORY_REPLAYING = False


def _cprint(text: str):
def is_interactive():
import sys
return sys.stdout.isatty()

def _cprint(text: str, force_plain: bool = False):
"""Print ANSI-colored text through prompt_toolkit's native renderer.

Raw ANSI escapes written via print() are swallowed by patch_stdout's
Expand All @@ -1507,12 +1511,22 @@ def _cprint(text: str):
``loop.call_soon_threadsafe``, which pauses the input area, prints
the line above it, and redraws the prompt cleanly.
"""
if force_plain or not is_interactive():
print(text)
return
Comment thread
AlexFoxD marked this conversation as resolved.

_record_output_history(text)

def _safe_print():
try:
_pt_print(_PT_ANSI(text))
except Exception:
print(text)

try:
from prompt_toolkit.application import get_app_or_none, run_in_terminal
except Exception:
_pt_print(_PT_ANSI(text))
_safe_print()
return

app = None
Expand All @@ -1525,15 +1539,15 @@ def _cprint(text: str):
# direct prompt_toolkit print is safe and matches existing behavior
# (spinner frames, streamed tokens, tool activity prefixes, …).
if app is None or not getattr(app, "_is_running", False):
_pt_print(_PT_ANSI(text))
_safe_print()
return

try:
loop = app.loop # type: ignore[attr-defined]
except Exception:
loop = None
if loop is None:
_pt_print(_PT_ANSI(text))
_safe_print()
return

import asyncio as _asyncio
Expand All @@ -1549,29 +1563,23 @@ def _cprint(text: str):
current_loop = None
# Same thread as the app's loop → safe to print directly.
if current_loop is loop and loop.is_running():
_pt_print(_PT_ANSI(text))
_safe_print()
return

# Cross-thread emission: ask the app's event loop to schedule a
# ``run_in_terminal`` that wraps ``_pt_print``. This hides the
# ``run_in_terminal`` that wraps ``_safe_print``. This hides the
# prompt, prints, and redraws. Fire-and-forget — if scheduling
# fails we fall back to a direct print so the line isn't lost.
def _schedule():
try:
run_in_terminal(lambda: _pt_print(_PT_ANSI(text)))
run_in_terminal(lambda: _safe_print())
except Exception:
try:
_pt_print(_PT_ANSI(text))
except Exception:
pass
_safe_print()

try:
loop.call_soon_threadsafe(_schedule)
except Exception:
try:
_pt_print(_PT_ANSI(text))
except Exception:
pass
_safe_print()


# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -2297,6 +2305,7 @@ def __init__(
checkpoints: bool = False,
pass_session_id: bool = False,
ignore_rules: bool = False,
headless: bool = False,
):
"""
Initialize the Hermes CLI.
Expand All @@ -2316,6 +2325,7 @@ def __init__(
# Initialize Rich console
self.console = Console()
self.config = CLI_CONFIG
self.headless = headless
self.compact = compact if compact is not None else CLI_CONFIG["display"].get("compact", False)
# tool_progress: "off", "new", "all", "verbose" (from config.yaml display section)
# YAML 1.1 parses bare `off` as boolean False — normalise to string.
Expand Down Expand Up @@ -4259,6 +4269,8 @@ def _show_security_advisories(self):

def show_banner(self):
"""Display the welcome banner in Claude Code style."""
if getattr(self, "headless", False):
return
self.console.clear()
ctx_len = None
if hasattr(self, 'agent') and self.agent and hasattr(self.agent, 'context_compressor'):
Expand Down Expand Up @@ -11196,8 +11208,88 @@ def _build_tui_layout_children(
] if item is not None
]

def _run_headless_loop(self, stdin=None):
"""Process newline-delimited prompts from stdin for --no-gui mode."""
input_stream = sys.stdin if stdin is None else stdin
for line in input_stream:
line = line.rstrip("\r\n")
if not line:
continue
self._agent_running = True
try:
self.chat(line)
except (KeyboardInterrupt, BrokenPipeError, EOFError):
raise
except Exception:
self._agent_running = False
raise
else:
self._agent_running = False

def _finalize_run(self):
"""Release CLI resources and close the active session."""
self._should_exit = True
# Interrupt the agent immediately so its daemon thread stops making
# API calls and exits promptly (agent_thread is daemon, so the
# process will exit once the main thread finishes, but interrupting
# avoids wasted API calls and lets run_conversation clean up).
if self.agent and getattr(self, '_agent_running', False):
try:
self.agent.interrupt()
except Exception:
pass
# Shut down voice recorder (release persistent audio stream)
if hasattr(self, '_voice_recorder') and self._voice_recorder:
try:
self._voice_recorder.shutdown()
except Exception:
pass
self._voice_recorder = None
# Clean up old temp voice recordings
try:
from tools.voice_mode import cleanup_temp_recordings
cleanup_temp_recordings()
except Exception:
pass
# Unregister callbacks to avoid dangling references
set_sudo_password_callback(None)
set_approval_callback(None)
set_secret_capture_callback(None)
# Close session in SQLite
if hasattr(self, '_session_db') and self._session_db and self.agent:
try:
self._session_db.end_session(self.agent.session_id, "cli_close")
except (Exception, KeyboardInterrupt) as e:
logger.debug("Could not close session in DB: %s", e)
# Plugin hook: on_session_end — safety net for interrupted exits.
# run_conversation() already fires this per-turn on normal completion,
# so only fire here if the agent was mid-turn (_agent_running) when
# the exit occurred, meaning run_conversation's hook didn't fire.
if self.agent and getattr(self, '_agent_running', False):
try:
from hermes_cli.plugins import invoke_hook as _invoke_hook
_invoke_hook(
"on_session_end",
session_id=self.agent.session_id,
completed=False,
interrupted=True,
model=getattr(self.agent, 'model', None),
platform=getattr(self.agent, 'platform', None) or "cli",
)
except Exception:
pass
_run_cleanup()
self._print_exit_summary()

def run(self):
"""Run the interactive CLI loop with persistent input at bottom."""
if getattr(self, "headless", False):
try:
self._run_headless_loop()
finally:
self._finalize_run()
return

Comment thread
AlexFoxD marked this conversation as resolved.
# Push the entire TUI to the bottom of the terminal so the banner,
# responses, and prompt all appear pinned to the bottom — empty
# space stays above, not below. This prints enough blank lines to
Expand Down Expand Up @@ -13324,8 +13416,7 @@ def _suppress_closed_loop_errors(loop, context):
"This can happen with certain Python installations (e.g. uv-managed cPython on macOS).\n"
"Try reinstalling Python via pyenv or Homebrew, then re-run: hermes setup"
)
_run_cleanup()
self._print_exit_summary()
self._finalize_run()
return

# Run the application with patch_stdout for proper output handling
Expand Down Expand Up @@ -13359,58 +13450,7 @@ def _suppress_closed_loop_errors(loop, context):
else:
raise
finally:
self._should_exit = True
# Interrupt the agent immediately so its daemon thread stops making
# API calls and exits promptly (agent_thread is daemon, so the
# process will exit once the main thread finishes, but interrupting
# avoids wasted API calls and lets run_conversation clean up).
if self.agent and getattr(self, '_agent_running', False):
try:
self.agent.interrupt()
except Exception:
pass
# Shut down voice recorder (release persistent audio stream)
if hasattr(self, '_voice_recorder') and self._voice_recorder:
try:
self._voice_recorder.shutdown()
except Exception:
pass
self._voice_recorder = None
# Clean up old temp voice recordings
try:
from tools.voice_mode import cleanup_temp_recordings
cleanup_temp_recordings()
except Exception:
pass
# Unregister callbacks to avoid dangling references
set_sudo_password_callback(None)
set_approval_callback(None)
set_secret_capture_callback(None)
# Close session in SQLite
if hasattr(self, '_session_db') and self._session_db and self.agent:
try:
self._session_db.end_session(self.agent.session_id, "cli_close")
except (Exception, KeyboardInterrupt) as e:
logger.debug("Could not close session in DB: %s", e)
# Plugin hook: on_session_end — safety net for interrupted exits.
# run_conversation() already fires this per-turn on normal completion,
# so only fire here if the agent was mid-turn (_agent_running) when
# the exit occurred, meaning run_conversation's hook didn't fire.
if self.agent and getattr(self, '_agent_running', False):
try:
from hermes_cli.plugins import invoke_hook as _invoke_hook
_invoke_hook(
"on_session_end",
session_id=self.agent.session_id,
completed=False,
interrupted=True,
model=getattr(self.agent, 'model', None),
platform=getattr(self.agent, 'platform', None) or "cli",
)
except Exception:
pass
_run_cleanup()
self._print_exit_summary()
self._finalize_run()


# ============================================================================
Expand Down Expand Up @@ -13441,6 +13481,7 @@ def main(
pass_session_id: bool = False,
ignore_user_config: bool = False,
ignore_rules: bool = False,
headless: bool = False,
):
"""
Hermes Agent CLI - Interactive AI Assistant
Expand Down Expand Up @@ -13560,6 +13601,7 @@ def main(
checkpoints=checkpoints,
pass_session_id=pass_session_id,
ignore_rules=ignore_rules,
headless=headless,
)

if parsed_skills:
Expand Down
8 changes: 8 additions & 0 deletions hermes_cli/_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,14 @@ def build_top_level_parser():
default=False,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR body advertises -y, but this final definition registers only --no-gui (the branch history includes d3251422ae91 removing -y). Please update the description and examples to the actual supported flag.

help="With --tui: run TypeScript sources via tsx (skip dist build)",
)
_inherited_flag(
parser,
"--no-gui",
action="store_true",
default=False,
help="Run in headless mode for non-graphical/background execution.",
)
Comment thread
AlexFoxD marked this conversation as resolved.


subparsers = parser.add_subparsers(dest="command", help="Command to run")

Expand Down
1 change: 1 addition & 0 deletions hermes_cli/auth.py
Original file line number Diff line number Diff line change
Expand Up @@ -1388,6 +1388,7 @@ def resolve_provider(
"go": "opencode-go", "opencode-go-sub": "opencode-go",
"kilo": "kilocode", "kilo-code": "kilocode", "kilo-gateway": "kilocode",
"lmstudio": "lmstudio", "lm-studio": "lmstudio", "lm_studio": "lmstudio",
"openai": "openrouter",
# Local server aliases — route through the generic custom provider
"ollama": "custom", "ollama_cloud": "ollama-cloud",
"vllm": "custom", "llamacpp": "custom",
Expand Down
3 changes: 2 additions & 1 deletion hermes_cli/kanban_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -3979,6 +3979,7 @@ def _default_spawn(
cmd = [
*_resolve_hermes_argv(),
"-p", profile_arg,
"--no-gui",
# Auto-load the kanban-worker skill so every dispatched worker
# has the pattern library (good summary/metadata shapes, retry
# diagnostics, block-reason examples) in its context, even if
Expand All @@ -3993,7 +3994,7 @@ def _default_spawn(
# `--skills X` pair rather than a single comma-joined arg: the CLI
# accepts both forms (action='append' + comma-split), but
# per-name pairs are easier to read in `ps` output and avoid any
# quoting ambiguity if a skill name ever contains unusual chars.
# quoting ambiguity if a skill name ever contains unusual chars.Ы
# Dedupe against the built-in so we don't double-load kanban-worker
# if a task author asks for it explicitly.
if task.skills:
Expand Down
Loading