2026-04-29 20:29:42 -07:00
"""
Top - level argparse construction for the hermes CLI .
Lives in its own module so other modules ( e . g . ` ` relaunch . py ` ` ) can
introspect the parser to discover which flags exist without running the
` ` main ` ` fn .
Only the top - level parser and the ` ` chat ` ` subparser live here . Every other
subparser ( model , gateway , sessions , … ) is built inline in ` ` main . py ` `
because its dispatch is tightly coupled to module - level ` ` cmd_ * ` ` functions .
"""
import argparse
# `--profile` / `-p` is consumed by ``main._apply_profile_override`` before
# argparse runs (it sets ``HERMES_HOME`` and strips itself from ``sys.argv``),
# so it isn't on the parser. Listed here so all "carry over on relaunch"
# metadata lives in one file.
PRE_ARGPARSE_INHERITED_FLAGS : list [ tuple [ str , bool ] ] = [
( " --profile " , True ) ,
( " -p " , True ) ,
]
def _inherited_flag ( parser , * args , * * kwargs ) :
""" Register a flag that ``hermes_cli.relaunch`` should carry over when
the CLI re - execs itself ( e . g . after ` ` sessions browse ` ` picks a session ,
or after the setup wizard launches chat ) .
Equivalent to ` ` parser . add_argument ( . . . ) ` ` plus tagging the resulting
Action with ` ` inherit_on_relaunch = True ` ` so the relaunch table builder
can find it via introspection .
"""
action = parser . add_argument ( * args , * * kwargs )
action . inherit_on_relaunch = True
return action
_EPILOGUE = """
Examples :
hermes Start interactive chat
hermes chat - q " Hello " Single query mode
hermes - c Resume the most recent session
hermes - c " my project " Resume a session by name ( latest in lineage )
hermes - - resume < session_id > Resume a specific session by ID
hermes setup Run setup wizard
hermes logout Clear stored authentication
hermes auth add < provider > Add a pooled credential
hermes auth list List pooled credentials
hermes auth remove < p > < t > Remove pooled credential by index , id , or label
hermes auth reset < provider > Clear exhaustion status for a provider
hermes model Select default model
hermes fallback [ list ] Show fallback provider chain
hermes fallback add Add a fallback provider ( same picker as ` hermes model ` )
hermes fallback remove Remove a fallback provider from the chain
hermes config View configuration
hermes config edit Edit config in $ EDITOR
hermes config set model gpt - 4 Set a config value
hermes gateway Run messaging gateway
hermes - s hermes - agent - dev , github - auth
hermes - w Start in isolated git worktree
hermes gateway install Install gateway background service
hermes sessions list List past sessions
hermes sessions browse Interactive session picker
hermes sessions rename ID T Rename / title a session
hermes logs View agent . log ( last 50 lines )
hermes logs - f Follow agent . log in real time
hermes logs errors View errors . log
hermes logs - - since 1 h Lines from the last hour
hermes debug share Upload debug report for support
hermes update Update to latest version
2026-05-03 23:05:13 +08:00
hermes dashboard Start web UI dashboard ( port 9119 )
hermes dashboard - - stop Stop running dashboard processes
hermes dashboard - - status List running dashboard processes
2026-04-29 20:29:42 -07:00
For more help on a command :
hermes < command > - - help
"""
def build_top_level_parser ( ) :
""" Build the top-level parser, the subparsers action, and the ``chat`` subparser.
Returns ` ` ( parser , subparsers , chat_parser ) ` ` . The caller wires
` ` chat_parser . set_defaults ( func = cmd_chat ) ` ` and continues registering
other subparsers via ` ` subparsers . add_parser ( . . . ) ` ` .
"""
parser = argparse . ArgumentParser (
prog = " hermes " ,
description = " Hermes Agent - AI assistant with tool-calling capabilities " ,
formatter_class = argparse . RawDescriptionHelpFormatter ,
epilog = _EPILOGUE ,
)
parser . add_argument (
" --version " , " -V " , action = " store_true " , help = " Show version and exit "
)
parser . add_argument (
" -z " ,
" --oneshot " ,
metavar = " PROMPT " ,
default = None ,
help = (
" One-shot mode: send a single prompt and print ONLY the final "
" response text to stdout. No banner, no spinner, no tool "
" previews, no session_id line. Tools, memory, rules, and "
" AGENTS.md in the CWD are loaded as normal; approvals are "
" auto-bypassed. Intended for scripts / pipes. "
) ,
)
# --model / --provider are accepted at the top level so they can pair
# with -z without needing the `chat` subcommand. If neither -z nor a
# subcommand consumes them, they fall through harmlessly as None.
# Mirrors `hermes chat --model ... --provider ...` semantics.
_inherited_flag (
parser ,
" -m " ,
" --model " ,
default = None ,
help = (
" Model override for this invocation (e.g. anthropic/claude-sonnet-4.6). "
" Applies to -z/--oneshot and --tui. Also settable via HERMES_INFERENCE_MODEL env var. "
) ,
)
_inherited_flag (
parser ,
" --provider " ,
default = None ,
help = (
" Provider override for this invocation (e.g. openrouter, anthropic). "
" Applies to -z/--oneshot and --tui. Also settable via HERMES_INFERENCE_PROVIDER env var. "
) ,
)
parser . add_argument (
" -t " ,
" --toolsets " ,
default = None ,
help = " Comma-separated toolsets to enable for this invocation. Applies to -z/--oneshot and --tui. " ,
)
parser . add_argument (
" --resume " ,
" -r " ,
metavar = " SESSION " ,
default = None ,
help = " Resume a previous session by ID or title " ,
)
parser . add_argument (
" --continue " ,
" -c " ,
dest = " continue_last " ,
nargs = " ? " ,
const = True ,
default = None ,
metavar = " SESSION_NAME " ,
help = " Resume a session by name, or the most recent if no name given " ,
)
parser . add_argument (
" --worktree " ,
" -w " ,
action = " store_true " ,
default = False ,
help = " Run in an isolated git worktree (for parallel agents) " ,
)
_inherited_flag (
parser ,
" --accept-hooks " ,
action = " store_true " ,
default = False ,
help = (
" Auto-approve any unseen shell hooks declared in config.yaml "
" without a TTY prompt. Equivalent to HERMES_ACCEPT_HOOKS=1 or "
" hooks_auto_accept: true in config.yaml. Use on CI / headless "
" runs that can ' t prompt. "
) ,
)
_inherited_flag (
parser ,
" --skills " ,
" -s " ,
action = " append " ,
default = None ,
help = " Preload one or more skills for the session (repeat flag or comma-separate) " ,
)
_inherited_flag (
parser ,
" --yolo " ,
action = " store_true " ,
default = False ,
help = " Bypass all dangerous command approval prompts (use at your own risk) " ,
)
_inherited_flag (
parser ,
" --pass-session-id " ,
action = " store_true " ,
default = False ,
help = " Include the session ID in the agent ' s system prompt " ,
)
_inherited_flag (
parser ,
" --ignore-user-config " ,
action = " store_true " ,
default = False ,
help = " Ignore ~/.hermes/config.yaml and fall back to built-in defaults (credentials in .env are still loaded) " ,
)
_inherited_flag (
parser ,
" --ignore-rules " ,
action = " store_true " ,
default = False ,
help = " Skip auto-injection of AGENTS.md, SOUL.md, .cursorrules, memory, and preloaded skills " ,
)
_inherited_flag (
parser ,
" --tui " ,
action = " store_true " ,
default = False ,
help = " Launch the modern TUI instead of the classic REPL " ,
)
_inherited_flag (
parser ,
" --dev " ,
dest = " tui_dev " ,
action = " store_true " ,
default = False ,
help = " With --tui: run TypeScript sources via tsx (skip dist build) " ,
)
subparsers = parser . add_subparsers ( dest = " command " , help = " Command to run " )
# =========================================================================
# chat command
# =========================================================================
chat_parser = subparsers . add_parser (
" chat " ,
help = " Interactive chat with the agent " ,
description = " Start an interactive chat session with Hermes Agent " ,
)
chat_parser . add_argument (
" -q " , " --query " , help = " Single query (non-interactive mode) "
)
chat_parser . add_argument (
" --image " , help = " Optional local image path to attach to a single query "
)
_inherited_flag (
chat_parser ,
" -m " , " --model " , help = " Model to use (e.g., anthropic/claude-sonnet-4) " ,
)
chat_parser . add_argument (
" -t " , " --toolsets " , help = " Comma-separated toolsets to enable "
)
_inherited_flag (
chat_parser ,
" -s " ,
" --skills " ,
action = " append " ,
default = argparse . SUPPRESS ,
help = " Preload one or more skills for the session (repeat flag or comma-separate) " ,
)
_inherited_flag (
chat_parser ,
" --provider " ,
# No `choices=` here: user-defined providers from config.yaml `providers:`
# are also valid values, and runtime resolution (resolve_runtime_provider)
# handles validation/error reporting consistently with the top-level
# `--provider` flag.
default = None ,
help = " Inference provider (default: auto). Built-in or a user-defined name from `providers:` in config.yaml. " ,
)
chat_parser . add_argument (
" -v " , " --verbose " , action = " store_true " , help = " Verbose output "
)
chat_parser . add_argument (
" -Q " ,
" --quiet " ,
action = " store_true " ,
help = " Quiet mode for programmatic use: suppress banner, spinner, and tool previews. Only output the final response and session info. " ,
)
chat_parser . add_argument (
" --resume " ,
" -r " ,
metavar = " SESSION_ID " ,
default = argparse . SUPPRESS ,
help = " Resume a previous session by ID (shown on exit) " ,
)
chat_parser . add_argument (
" --continue " ,
" -c " ,
dest = " continue_last " ,
nargs = " ? " ,
const = True ,
default = argparse . SUPPRESS ,
metavar = " SESSION_NAME " ,
help = " Resume a session by name, or the most recent if no name given " ,
)
chat_parser . add_argument (
" --worktree " ,
" -w " ,
action = " store_true " ,
default = argparse . SUPPRESS ,
help = " Run in an isolated git worktree (for parallel agents on the same repo) " ,
)
_inherited_flag (
chat_parser ,
" --accept-hooks " ,
action = " store_true " ,
default = argparse . SUPPRESS ,
help = (
" Auto-approve any unseen shell hooks declared in config.yaml "
" without a TTY prompt (see also HERMES_ACCEPT_HOOKS env var and "
" hooks_auto_accept: in config.yaml). "
) ,
)
chat_parser . add_argument (
" --checkpoints " ,
action = " store_true " ,
default = False ,
help = " Enable filesystem checkpoints before destructive file operations (use /rollback to restore) " ,
)
chat_parser . add_argument (
" --max-turns " ,
type = int ,
default = None ,
metavar = " N " ,
help = " Maximum tool-calling iterations per conversation turn (default: 90, or agent.max_turns in config) " ,
)
_inherited_flag (
chat_parser ,
" --yolo " ,
action = " store_true " ,
default = argparse . SUPPRESS ,
help = " Bypass all dangerous command approval prompts (use at your own risk) " ,
)
_inherited_flag (
chat_parser ,
" --pass-session-id " ,
action = " store_true " ,
default = argparse . SUPPRESS ,
help = " Include the session ID in the agent ' s system prompt " ,
)
_inherited_flag (
chat_parser ,
" --ignore-user-config " ,
action = " store_true " ,
default = argparse . SUPPRESS ,
help = " Ignore ~/.hermes/config.yaml and fall back to built-in defaults (credentials in .env are still loaded). Useful for isolated CI runs, reproduction, and third-party integrations. " ,
)
_inherited_flag (
chat_parser ,
" --ignore-rules " ,
action = " store_true " ,
default = argparse . SUPPRESS ,
help = " Skip auto-injection of AGENTS.md, SOUL.md, .cursorrules, memory, and preloaded skills. Combine with --ignore-user-config for a fully isolated run. " ,
)
chat_parser . add_argument (
" --source " ,
default = None ,
help = " Session source tag for filtering (default: cli). Use ' tool ' for third-party integrations that should not appear in user session lists. " ,
)
_inherited_flag (
chat_parser ,
" --tui " ,
action = " store_true " ,
default = False ,
help = " Launch the modern TUI instead of the classic REPL " ,
)
_inherited_flag (
chat_parser ,
" --dev " ,
dest = " tui_dev " ,
action = " store_true " ,
default = False ,
help = " With --tui: run TypeScript sources via tsx (skip dist build) " ,
)
return parser , subparsers , chat_parser