mirror of
https://github.com/instructkr/claw-code.git
synced 2026-04-27 00:44:57 +08:00
fix: #167 — show-command and show-tool now accept --output-format flag; CLI parity with session-lifecycle family
Closes the inspect-capability parity gap: show-command and show-tool were
the only discovery/inspection CLI commands lacking --output-format support,
making them outliers in the ecosystem that already had unified JSON
contracts across list-sessions, load-session, delete-session, and
flush-transcript (#160/#165/#166).
Concrete additions:
- show-command: --output-format {text,json}
- show-tool: --output-format {text,json}
JSON envelope shape (found case):
{name, found: true, source_hint, responsibility}
JSON envelope shape (not-found case):
{name, found: false, error: {kind:'command_not_found'|'tool_not_found',
message, retryable: false}}
Exit codes:
0 = success
1 = not found
Backward compatibility:
- Default (no --output-format) is 'text' (unchanged)
- Text output byte-identical to pre-#167 (three newline-separated lines)
Tests (10 new, test_show_command_tool_output_format.py):
- TestShowCommandOutputFormat (5): found + not-found in JSON; text mode
backward compat; text is default
- TestShowToolOutputFormat (3): found + not-found in JSON; text mode
backward compat
- TestShowCommandToolFormatParity (2): both accept same flag choices;
consistent JSON envelope shape
Full suite: 114 → 124 passing, zero regression.
Closes ROADMAP #167.
Why this matters:
Before: Claws calling show-command/show-tool had to parse human-readable
prose output via regex, with no structured error signal.
After: Same envelope contract as load-session and friends: JSON-first,
typed errors, machine-parseable.
Related clusters:
- Session-lifecycle CLI parity family (#160, #165, #166, #167)
- Machine-readable error contracts (same vein as #162 atomicity + #164
cancellation state-safety: structured boundaries for orchestration)
This commit is contained in:
56
src/main.py
56
src/main.py
@@ -157,8 +157,10 @@ def build_parser() -> argparse.ArgumentParser:
|
||||
|
||||
show_command = subparsers.add_parser('show-command', help='show one mirrored command entry by exact name')
|
||||
show_command.add_argument('name')
|
||||
show_command.add_argument('--output-format', choices=['text', 'json'], default='text')
|
||||
show_tool = subparsers.add_parser('show-tool', help='show one mirrored tool entry by exact name')
|
||||
show_tool.add_argument('name')
|
||||
show_tool.add_argument('--output-format', choices=['text', 'json'], default='text')
|
||||
|
||||
exec_command_parser = subparsers.add_parser('exec-command', help='execute a mirrored command shim by exact name')
|
||||
exec_command_parser.add_argument('name')
|
||||
@@ -394,16 +396,62 @@ def main(argv: list[str] | None = None) -> int:
|
||||
if args.command == 'show-command':
|
||||
module = get_command(args.name)
|
||||
if module is None:
|
||||
print(f'Command not found: {args.name}')
|
||||
if args.output_format == 'json':
|
||||
import json
|
||||
error_envelope = {
|
||||
'name': args.name,
|
||||
'found': False,
|
||||
'error': {
|
||||
'kind': 'command_not_found',
|
||||
'message': f'Unknown command: {args.name}',
|
||||
'retryable': False,
|
||||
},
|
||||
}
|
||||
print(json.dumps(error_envelope))
|
||||
else:
|
||||
print(f'Command not found: {args.name}')
|
||||
return 1
|
||||
print('\n'.join([module.name, module.source_hint, module.responsibility]))
|
||||
if args.output_format == 'json':
|
||||
import json
|
||||
output = {
|
||||
'name': module.name,
|
||||
'found': True,
|
||||
'source_hint': module.source_hint,
|
||||
'responsibility': module.responsibility,
|
||||
}
|
||||
print(json.dumps(output))
|
||||
else:
|
||||
print('\n'.join([module.name, module.source_hint, module.responsibility]))
|
||||
return 0
|
||||
if args.command == 'show-tool':
|
||||
module = get_tool(args.name)
|
||||
if module is None:
|
||||
print(f'Tool not found: {args.name}')
|
||||
if args.output_format == 'json':
|
||||
import json
|
||||
error_envelope = {
|
||||
'name': args.name,
|
||||
'found': False,
|
||||
'error': {
|
||||
'kind': 'tool_not_found',
|
||||
'message': f'Unknown tool: {args.name}',
|
||||
'retryable': False,
|
||||
},
|
||||
}
|
||||
print(json.dumps(error_envelope))
|
||||
else:
|
||||
print(f'Tool not found: {args.name}')
|
||||
return 1
|
||||
print('\n'.join([module.name, module.source_hint, module.responsibility]))
|
||||
if args.output_format == 'json':
|
||||
import json
|
||||
output = {
|
||||
'name': module.name,
|
||||
'found': True,
|
||||
'source_hint': module.source_hint,
|
||||
'responsibility': module.responsibility,
|
||||
}
|
||||
print(json.dumps(output))
|
||||
else:
|
||||
print('\n'.join([module.name, module.source_hint, module.responsibility]))
|
||||
return 0
|
||||
if args.command == 'exec-command':
|
||||
result = execute_command(args.name, args.prompt)
|
||||
|
||||
Reference in New Issue
Block a user