Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .github/workflows/supply-chain-audit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ jobs:

- name: Post warning comment
if: steps.scan.outputs.found == 'true'
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
Expand Down
65 changes: 65 additions & 0 deletions cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3942,6 +3942,67 @@ def _parse_flags(tokens):
print(f"(._.) Unknown cron command: {subcommand}")
print(" Available: list, add, edit, pause, resume, run, remove")

def _handle_make_index_command(self, cmd: str):
"""Handle /make-index command to generate vault topic indexes."""
import subprocess
import shlex

# Parse arguments
parts = shlex.split(cmd)[1:] if len(shlex.split(cmd)) > 1 else []
folder = parts[0] if parts else "Clippings"

# Handle stats option
if folder == "stats" or folder == "--stats":
result = subprocess.run(
["python3", str(Path.home() / ".hermes/skills/make-index/script.py"), "--stats"],
capture_output=True, text=True
)
print(result.stdout)
return

# Run the index generator
result = subprocess.run(
["python3", str(Path.home() / ".hermes/skills/make-index/script.py"), folder],
capture_output=True, text=True
)

if result.returncode == 0:
print(result.stdout)
print(f"\n✅ Index generated! Opening in Obsidian...")
# Open the INDEX.md file
vault_path = Path.home() / "Documents" / "great-vault"
index_path = vault_path / folder / "INDEX.md"
if index_path.exists():
subprocess.run(["open", str(index_path)])
else:
print(f"❌ Error: {result.stderr}")

def _handle_kb_command(self, cmd: str):
"""Handle /kb command for Knowledge Base v2."""
import subprocess
import shlex

# Parse arguments
parts = shlex.split(cmd)[1:] if len(shlex.split(cmd)) > 1 else []
subcommand = parts[0] if parts else "status"

# Build the command
vault_path = Path.home() / "Documents" / "great-vault"
kb_script = vault_path / ".kb" / "scripts" / "cli.py"

# Run the KB CLI
result = subprocess.run(
["python3", str(kb_script)] + parts,
capture_output=True, text=True
)

if result.returncode == 0:
print(result.stdout)
else:
print(f"❌ Error: {result.stderr}")
if result.stdout:
print(result.stdout)

def _handle_skills_command(self, cmd: str):
"""Handle /skills slash command — delegates to hermes_cli.skills_hub."""
from hermes_cli.skills_hub import handle_skills_slash
Expand Down Expand Up @@ -4160,6 +4221,10 @@ def process_command(self, command: str) -> bool:
elif canonical == "skills":
with self._busy_command(self._slow_command_status(cmd_original)):
self._handle_skills_command(cmd_original)
elif canonical == "make-index":
self._handle_make_index_command(cmd_original)
elif canonical == "kb":
self._handle_kb_command(cmd_original)
elif canonical == "platforms":
self._show_gateway_status()
elif canonical == "statusbar":
Expand Down
14 changes: 3 additions & 11 deletions cron/scheduler.py
Original file line number Diff line number Diff line change
Expand Up @@ -234,17 +234,9 @@ def _build_job_prompt(job: dict) -> str:
prompt = job.get("prompt", "")
skills = job.get("skills")

# Always prepend [SILENT] guidance so the cron agent can suppress
# delivery when it has nothing new or noteworthy to report.
silent_hint = (
"[SYSTEM: If you have a meaningful status report or findings, "
"send them — that is the whole point of this job. Only respond "
"with exactly \"[SILENT]\" (nothing else) when there is genuinely "
"nothing new to report. [SILENT] suppresses delivery to the user. "
"Never combine [SILENT] with content — either report your "
"findings normally, or say [SILENT] and nothing more.]\n\n"
)
prompt = silent_hint + prompt
# NOTE: [SILENT] guidance removed - job prompts already contain their own
# delivery instructions. This was causing conflicts where jobs that should
# ALWAYS produce output were getting truncated due to mixed instructions.
if skills is None:
legacy = job.get("skill")
skills = [legacy] if legacy else []
Expand Down
20 changes: 20 additions & 0 deletions hermes_cli/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,14 @@ class CommandDef:
subcommands=("connect", "disconnect", "status")),
CommandDef("plugins", "List installed plugins and their status",
"Tools & Skills", cli_only=True),
CommandDef("make-index", "Generate topic index for vault folders",
"Tools & Skills", cli_only=True,
args_hint="[folder_name]",
subcommands=("Clippings", "DeepResearchReports", "YT Research Reports", "Personal Tech Deep Dives", "stats")),
CommandDef("kb", "Knowledge Base v2: compile, query, lint, stats",
"Tools & Skills",
args_hint="[command]",
subcommands=("compile", "query", "lint", "stats", "status", "output")),

# Info
CommandDef("commands", "Browse all commands and skills (paginated)", "Info",
Expand All @@ -138,6 +146,18 @@ class CommandDef:
CommandDef("update", "Update Hermes Agent to the latest version", "Info",
gateway_only=True),

# GSD Workflow
CommandDef("gsd", "GSD project workflow commands", "Project",
subcommands=("init", "map", "autonomous", "executor", "verifier", "status", "next")),
CommandDef("gsd:init", "Initialize a new GSD project", "Project"),
CommandDef("gsd:map", "Analyze existing codebase before planning", "Project"),
CommandDef("gsd:autonomous", "Run all GSD phases autonomously", "Project",
args_hint="[--from N]"),
CommandDef("gsd:executor", "Execute GSD phase plans via subagents", "Project",
args_hint="<phase>"),
CommandDef("gsd:verifier", "Verify GSD phase against success criteria", "Project",
args_hint="<phase>"),

# Exit
CommandDef("quit", "Exit the CLI", "Exit",
cli_only=True, aliases=("exit", "q")),
Expand Down
Loading