* feat(skills): inject absolute skill dir and expand ${HERMES_SKILL_DIR} templates
When a skill loads, the activation message now exposes the absolute
skill directory and substitutes ${HERMES_SKILL_DIR} /
${HERMES_SESSION_ID} tokens in the SKILL.md body, so skills with
bundled scripts can instruct the agent to run them by absolute path
without an extra skill_view round-trip.
Also adds opt-in inline-shell expansion: !`cmd` snippets in SKILL.md
are pre-executed (with the skill directory as CWD) and their stdout is
inlined into the message before the agent reads it. Off by default —
enable via skills.inline_shell in config.yaml — because any snippet
runs on the host without approval.
Changes:
- agent/skill_commands.py: template substitution, inline-shell
expansion, absolute skill-dir header, supporting-files list now
shows both relative and absolute forms.
- hermes_cli/config.py: new skills.template_vars,
skills.inline_shell, skills.inline_shell_timeout knobs.
- tests/agent/test_skill_commands.py: coverage for header, both
template tokens (present and missing session id), template_vars
disable, inline-shell default-off, enabled, CWD, and timeout.
- website/docs/developer-guide/creating-skills.md: documents the
template tokens, the absolute-path header, and the opt-in inline
shell with its security caveat.
Validation: tests/agent/ 1591 passed (includes 9 new tests).
E2E: loaded a real skill in an isolated HERMES_HOME; confirmed
${HERMES_SKILL_DIR} resolves to the absolute path, ${HERMES_SESSION_ID}
resolves to the passed task_id, !`date` runs when opt-in is set, and
stays literal when it isn't.
* feat(terminal): source ~/.bashrc (and user-listed init files) into session snapshot
bash login shells don't source ~/.bashrc, so tools that install themselves
there — nvm, asdf, pyenv, cargo, custom PATH exports — stay invisible to
the environment snapshot Hermes builds once per session. Under systemd
or any context with a minimal parent env, that surfaces as
'node: command not found' in the terminal tool even though the binary
is reachable from every interactive shell on the machine.
Changes:
- tools/environments/local.py: before the login-shell snapshot bootstrap
runs, prepend guarded 'source <file>' lines for each resolved init
file. Missing files are skipped, each source is wrapped with a
'[ -r ... ] && . ... || true' guard so a broken rc can't abort the
bootstrap.
- hermes_cli/config.py: new terminal.shell_init_files (explicit list,
supports ~ and ${VAR}) and terminal.auto_source_bashrc (default on)
knobs. When shell_init_files is set it takes precedence; when it's
empty and auto_source_bashrc is on, ~/.bashrc gets auto-sourced.
- tests/tools/test_local_shell_init.py: 10 tests covering the resolver
(auto-bashrc, missing file, explicit override, ~/${VAR} expansion,
opt-out) and the prelude builder (quoting, guarded sourcing), plus
a real-LocalEnvironment snapshot test that confirms exports in the
init file land in subsequent commands' environment.
- website/docs/reference/faq.md: documents the fix in Troubleshooting,
including the zsh-user pattern of sourcing ~/.zshrc or nvm.sh
directly via shell_init_files.
Validation: 10/10 new tests pass; tests/tools/test_local_*.py 40/40
pass; tests/agent/ 1591/1591 pass; tests/hermes_cli/test_config.py
50/50 pass. E2E in an isolated HERMES_HOME: confirmed that a fake
~/.bashrc setting a marker var and PATH addition shows up in a real
LocalEnvironment().execute() call, that auto_source_bashrc=false
suppresses it, that an explicit shell_init_files entry wins over the
auto default, and that a missing bashrc is silently skipped.
|
||
|---|---|---|
| .. | ||
| __init__.py | ||
| test_accretion_caps.py | ||
| test_ansi_strip.py | ||
| test_approval_heartbeat.py | ||
| test_approval.py | ||
| test_base_environment.py | ||
| test_browser_camofox_persistence.py | ||
| test_browser_camofox_state.py | ||
| test_browser_camofox.py | ||
| test_browser_cdp_override.py | ||
| test_browser_cdp_tool.py | ||
| test_browser_cleanup.py | ||
| test_browser_cloud_fallback.py | ||
| test_browser_console.py | ||
| test_browser_content_none_guard.py | ||
| test_browser_hardening.py | ||
| test_browser_homebrew_paths.py | ||
| test_browser_orphan_reaper.py | ||
| test_browser_secret_exfil.py | ||
| test_browser_ssrf_local.py | ||
| test_budget_config.py | ||
| test_checkpoint_manager.py | ||
| test_clarify_tool.py | ||
| test_clipboard.py | ||
| test_code_execution_modes.py | ||
| test_code_execution.py | ||
| test_command_guards.py | ||
| test_config_null_guard.py | ||
| test_credential_files.py | ||
| test_cron_approval_mode.py | ||
| test_cron_prompt_injection.py | ||
| test_cronjob_tools.py | ||
| test_daytona_environment.py | ||
| test_debug_helpers.py | ||
| test_delegate_toolset_scope.py | ||
| test_delegate.py | ||
| test_discord_tool.py | ||
| test_docker_environment.py | ||
| test_docker_find.py | ||
| test_env_passthrough.py | ||
| test_feishu_tools.py | ||
| test_file_operations_edge_cases.py | ||
| test_file_operations.py | ||
| test_file_ops_cwd_tracking.py | ||
| test_file_read_guards.py | ||
| test_file_staleness.py | ||
| test_file_sync_back.py | ||
| test_file_sync_perf.py | ||
| test_file_sync.py | ||
| test_file_tools_container_config.py | ||
| test_file_tools_live.py | ||
| test_file_tools.py | ||
| test_file_write_safety.py | ||
| test_force_dangerous_override.py | ||
| test_fuzzy_match.py | ||
| test_hidden_dir_filter.py | ||
| test_homeassistant_tool.py | ||
| test_image_generation.py | ||
| test_interrupt.py | ||
| test_llm_content_none_guard.py | ||
| test_local_background_child_hang.py | ||
| test_local_env_blocklist.py | ||
| test_local_interrupt_cleanup.py | ||
| test_local_shell_init.py | ||
| test_local_tempdir.py | ||
| test_managed_browserbase_and_modal.py | ||
| test_managed_media_gateways.py | ||
| test_managed_modal_environment.py | ||
| test_managed_server_tool_support.py | ||
| test_managed_tool_gateway.py | ||
| test_mcp_dynamic_discovery.py | ||
| test_mcp_oauth_bidirectional.py | ||
| test_mcp_oauth_cold_load_expiry.py | ||
| test_mcp_oauth_integration.py | ||
| test_mcp_oauth_manager.py | ||
| test_mcp_oauth.py | ||
| test_mcp_probe.py | ||
| test_mcp_reconnect_signal.py | ||
| test_mcp_stability.py | ||
| test_mcp_structured_content.py | ||
| test_mcp_tool_401_handling.py | ||
| test_mcp_tool_issue_948.py | ||
| test_mcp_tool.py | ||
| test_memory_tool_import_fallback.py | ||
| test_memory_tool.py | ||
| test_mixture_of_agents_tool.py | ||
| test_modal_bulk_upload.py | ||
| test_modal_sandbox_fixes.py | ||
| test_modal_snapshot_isolation.py | ||
| test_notify_on_complete.py | ||
| test_osv_check.py | ||
| test_parse_env_var.py | ||
| test_patch_parser.py | ||
| test_process_registry.py | ||
| test_read_loop_detection.py | ||
| test_registry.py | ||
| test_resolve_path.py | ||
| test_rl_training_tool.py | ||
| test_search_hidden_dirs.py | ||
| test_send_message_missing_platforms.py | ||
| test_send_message_tool.py | ||
| test_session_search.py | ||
| test_signal_media.py | ||
| test_singularity_preflight.py | ||
| test_skill_env_passthrough.py | ||
| test_skill_improvements.py | ||
| test_skill_manager_tool.py | ||
| test_skill_size_limits.py | ||
| test_skill_view_path_check.py | ||
| test_skill_view_traversal.py | ||
| test_skills_guard.py | ||
| test_skills_hub_clawhub.py | ||
| test_skills_hub.py | ||
| test_skills_sync.py | ||
| test_skills_tool.py | ||
| test_ssh_bulk_upload.py | ||
| test_ssh_environment.py | ||
| test_symlink_prefix_confusion.py | ||
| test_sync_back_backends.py | ||
| test_terminal_compound_background.py | ||
| test_terminal_exit_semantics.py | ||
| test_terminal_foreground_timeout_cap.py | ||
| test_terminal_none_command_guard.py | ||
| test_terminal_output_transform_hook.py | ||
| test_terminal_requirements.py | ||
| test_terminal_timeout_output.py | ||
| test_terminal_tool_pty_fallback.py | ||
| test_terminal_tool_requirements.py | ||
| test_terminal_tool.py | ||
| test_threaded_process_handle.py | ||
| test_tirith_security.py | ||
| test_todo_tool.py | ||
| test_tool_backend_helpers.py | ||
| test_tool_call_parsers.py | ||
| test_tool_result_storage.py | ||
| test_transcription_tools.py | ||
| test_transcription.py | ||
| test_tts_gemini.py | ||
| test_tts_mistral.py | ||
| test_tts_speed.py | ||
| test_url_safety.py | ||
| test_vision_tools.py | ||
| test_voice_cli_integration.py | ||
| test_voice_mode.py | ||
| test_watch_patterns.py | ||
| test_web_tools_config.py | ||
| test_web_tools_tavily.py | ||
| test_website_policy.py | ||
| test_windows_compat.py | ||
| test_write_deny.py | ||
| test_yolo_mode.py | ||
| test_zombie_process_cleanup.py | ||