fix(sessions): support stdout (-) in session and snapshot export (salvage #3617) (#3641)

* fix(sessions): support stdout when output path is '-' in session export

* fix: style cleanup + extend stdout support to snapshot export

Follow-up for salvaged PR #3617:
- Fix import sys; on one line (style consistency)
- Update help text to mention - for stdout
- Apply same stdout support to hermes skills snapshot export

---------

Co-authored-by: ygd58 <buraysandro9@gmail.com>
This commit is contained in:
Teknium
2026-03-28 17:24:32 -07:00
committed by GitHub
parent 17617e4399
commit dc74998718
2 changed files with 27 additions and 12 deletions

View File

@@ -3713,7 +3713,7 @@ For more help on a command:
skills_snapshot = skills_subparsers.add_parser("snapshot", help="Export/import skill configurations")
snapshot_subparsers = skills_snapshot.add_subparsers(dest="snapshot_action")
snap_export = snapshot_subparsers.add_parser("export", help="Export installed skills to a file")
snap_export.add_argument("output", help="Output JSON file path")
snap_export.add_argument("output", help="Output JSON file path (use - for stdout)")
snap_import = snapshot_subparsers.add_parser("import", help="Import and install skills from a file")
snap_import.add_argument("input", help="Input JSON file path")
snap_import.add_argument("--force", action="store_true", help="Force install despite caution verdict")
@@ -3990,7 +3990,7 @@ For more help on a command:
sessions_list.add_argument("--limit", type=int, default=20, help="Max sessions to show")
sessions_export = sessions_subparsers.add_parser("export", help="Export sessions to a JSONL file")
sessions_export.add_argument("output", help="Output JSONL file path")
sessions_export.add_argument("output", help="Output JSONL file path (use - for stdout)")
sessions_export.add_argument("--source", help="Filter by source")
sessions_export.add_argument("--session-id", help="Export a specific session")
@@ -4071,15 +4071,25 @@ For more help on a command:
if not data:
print(f"Session '{args.session_id}' not found.")
return
with open(args.output, "w", encoding="utf-8") as f:
f.write(_json.dumps(data, ensure_ascii=False) + "\n")
print(f"Exported 1 session to {args.output}")
line = _json.dumps(data, ensure_ascii=False) + "\n"
if args.output == "-":
import sys
sys.stdout.write(line)
else:
with open(args.output, "w", encoding="utf-8") as f:
f.write(line)
print(f"Exported 1 session to {args.output}")
else:
sessions = db.export_all(source=args.source)
with open(args.output, "w", encoding="utf-8") as f:
if args.output == "-":
import sys
for s in sessions:
f.write(_json.dumps(s, ensure_ascii=False) + "\n")
print(f"Exported {len(sessions)} sessions to {args.output}")
sys.stdout.write(_json.dumps(s, ensure_ascii=False) + "\n")
else:
with open(args.output, "w", encoding="utf-8") as f:
for s in sessions:
f.write(_json.dumps(s, ensure_ascii=False) + "\n")
print(f"Exported {len(sessions)} sessions to {args.output}")
elif action == "delete":
resolved_session_id = db.resolve_session_id(args.session_id)

View File

@@ -887,10 +887,15 @@ def do_snapshot_export(output_path: str, console: Optional[Console] = None) -> N
"taps": tap_list,
}
out = Path(output_path)
out.write_text(json.dumps(snapshot, indent=2, ensure_ascii=False) + "\n")
c.print(f"[bold green]Snapshot exported:[/] {out}")
c.print(f"[dim]{len(installed)} skill(s), {len(tap_list)} tap(s)[/]\n")
payload = json.dumps(snapshot, indent=2, ensure_ascii=False) + "\n"
if output_path == "-":
import sys
sys.stdout.write(payload)
else:
out = Path(output_path)
out.write_text(payload)
c.print(f"[bold green]Snapshot exported:[/] {out}")
c.print(f"[dim]{len(installed)} skill(s), {len(tap_list)} tap(s)[/]\n")
def do_snapshot_import(input_path: str, force: bool = False,