Skip to content
Merged
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
33 changes: 33 additions & 0 deletions src/dippy/dippy.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,39 @@ def main():
"""Main entry point for the hook."""
global MODE

# Early exit flags — checked before reading stdin
if "--help" in sys.argv or "-h" in sys.argv:
from dippy import __version__

print(f"Dippy v{__version__} — approval autopilot for AI coding assistants")
print()
print("Usage: dippy [--claude|--gemini|--cursor]")
print()
print("Reads JSON hook payload from stdin. Outputs a JSON decision.")
print()
print("Modes:")
print(" --claude Force Claude Code mode")
print(" --gemini Force Gemini CLI mode")
print(" --cursor Force Cursor mode")
print(" (auto-detected from input if not specified)")
print()
print("Flags:")
print(" --help, -h Show this help")
print(" --version, -V Show version")
raise SystemExit(0)

if "--version" in sys.argv or "-V" in sys.argv:
from dippy import __version__

print(f"dippy {__version__}")
raise SystemExit(0)

# If stdin is a TTY, no input is being piped — show help instead of hanging
if sys.stdin.isatty():
print("dippy: no input (expected JSON on stdin)")
print("Run 'dippy --help' for usage.")
raise SystemExit(0)

setup_logging()

try:
Expand Down
63 changes: 63 additions & 0 deletions tests/test_dippy.py
Original file line number Diff line number Diff line change
Expand Up @@ -3966,6 +3966,69 @@ def test_command(check, cmd, expected_safe):
assert needs_confirmation(result), f"Expected confirmation for: {cmd}"


class TestCLI:
"""Test CLI flags (--help, --version) and TTY detection."""

def test_help_flag(self, capsys):
import sys
from unittest.mock import patch

with patch.object(sys, "argv", ["dippy", "--help"]):
from dippy.dippy import main

with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "Usage:" in captured.out
assert "--claude" in captured.out

def test_help_flag_short(self, capsys):
import sys
from unittest.mock import patch

with patch.object(sys, "argv", ["dippy", "-h"]):
from dippy.dippy import main

with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "Usage:" in captured.out

def test_version_flag(self, capsys):
import sys
from unittest.mock import patch

with patch.object(sys, "argv", ["dippy", "--version"]):
from dippy.dippy import main

with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
from dippy import __version__

assert __version__ in captured.out

def test_tty_shows_help(self, capsys):
"""When stdin is a TTY (no piped input), show help instead of hanging."""
import sys
from unittest.mock import patch

with patch.object(sys, "argv", ["dippy"]), patch.object(
sys.stdin, "isatty", return_value=True
):
from dippy.dippy import main

with pytest.raises(SystemExit) as exc_info:
main()
assert exc_info.value.code == 0
captured = capsys.readouterr()
assert "no input" in captured.out
assert "--help" in captured.out


class TestPostToolUse:
"""Test PostToolUse hook handling."""

Expand Down
Loading