@@ -246,6 +246,63 @@ def find_cowork_sessions(base_dir=None, limit=10):
246246 return results [:limit ]
247247
248248
249+ def find_cowork_session_by_process_name (process_name , base_dir = None ):
250+ """Find a single Cowork session by its processName.
251+
252+ Returns a session dict (title, jsonl_path, folders, mtime) or None if not found.
253+ Useful for non-interactive in-session use: pass basename of $PWD as process_name.
254+ """
255+ if base_dir is None :
256+ base_dir = (
257+ Path .home ()
258+ / "Library"
259+ / "Application Support"
260+ / "Claude"
261+ / "local-agent-mode-sessions"
262+ )
263+ base_dir = Path (base_dir )
264+ if not base_dir .exists ():
265+ return None
266+
267+ for metadata_file in base_dir .glob ("**/local_*.json" ):
268+ if not metadata_file .is_file ():
269+ continue
270+ try :
271+ metadata = json .loads (metadata_file .read_text (encoding = "utf-8" ))
272+ except (json .JSONDecodeError , OSError ):
273+ continue
274+
275+ if metadata .get ("processName" ) != process_name :
276+ continue
277+
278+ cli_session_id = metadata .get ("cliSessionId" , "" )
279+ title = metadata .get ("title" ) or metadata .get ("initialMessage" , "(untitled)" )
280+ folders = metadata .get ("userSelectedFolders" , [])
281+ last_activity_at = metadata .get ("lastActivityAt" , 0 )
282+
283+ stem = metadata_file .stem
284+ jsonl_path = (
285+ metadata_file .parent
286+ / stem
287+ / ".claude"
288+ / "projects"
289+ / f"-sessions-{ process_name } "
290+ / f"{ cli_session_id } .jsonl"
291+ )
292+
293+ if not jsonl_path .exists ():
294+ return None
295+
296+ return {
297+ "title" : title ,
298+ "jsonl_path" : jsonl_path ,
299+ "folders" : folders ,
300+ "mtime" : last_activity_at / 1000 ,
301+ }
302+
303+ return None
304+
305+
249306def get_project_display_name (folder_name ):
250307 """Convert encoded folder name to readable project name.
251308
@@ -1686,38 +1743,58 @@ def local_cmd(output, output_auto, repo, gist, include_json, open_browser, limit
16861743 default = 10 ,
16871744 help = "Maximum number of sessions to show (default: 10)" ,
16881745)
1689- def cowork_cmd (output , output_auto , gist , open_browser , limit ):
1746+ @click .option (
1747+ "--process-name" ,
1748+ "process_name" ,
1749+ default = None ,
1750+ help = (
1751+ "Process name to match (e.g. 'quirky-eager-fermat'). "
1752+ "Skips the interactive picker. "
1753+ 'Use --process-name "$(basename $PWD)" from within a Cowork session.'
1754+ ),
1755+ )
1756+ def cowork_cmd (output , output_auto , gist , open_browser , limit , process_name ):
16901757 """Select and convert a local Claude Cowork session to HTML."""
1691- click .echo ("Loading Cowork sessions..." )
1692- sessions = find_cowork_sessions (limit = limit )
1758+ if process_name :
1759+ # Non-interactive mode: find session by processName (for in-session use)
1760+ selected = find_cowork_session_by_process_name (process_name )
1761+ if selected is None :
1762+ click .echo (f"No Cowork session found with process name: { process_name } " )
1763+ click .echo (
1764+ "Ensure ~/Library/Application Support/Claude/ is in your userSelectedFolders."
1765+ )
1766+ return
1767+ else :
1768+ click .echo ("Loading Cowork sessions..." )
1769+ sessions = find_cowork_sessions (limit = limit )
16931770
1694- if not sessions :
1695- click .echo ("No Cowork sessions found." )
1696- click .echo (
1697- "Expected sessions in: ~/Library/Application Support/Claude/local-agent-mode-sessions/"
1698- )
1699- return
1771+ if not sessions :
1772+ click .echo ("No Cowork sessions found." )
1773+ click .echo (
1774+ "Expected sessions in: ~/Library/Application Support/Claude/local-agent-mode-sessions/"
1775+ )
1776+ return
17001777
1701- # Build choices for questionary
1702- choices = []
1703- for session in sessions :
1704- mod_time = datetime .fromtimestamp (session ["mtime" ])
1705- date_str = mod_time .strftime ("%Y-%m-%d %H:%M" )
1706- title = session ["title" ]
1707- if len (title ) > 50 :
1708- title = title [:47 ] + "..."
1709- folder = session ["folders" ][0 ] if session ["folders" ] else "(no folder)"
1710- display = f"{ title :50} { date_str } { folder } "
1711- choices .append (questionary .Choice (title = display , value = session ))
1778+ # Build choices for questionary
1779+ choices = []
1780+ for session in sessions :
1781+ mod_time = datetime .fromtimestamp (session ["mtime" ])
1782+ date_str = mod_time .strftime ("%Y-%m-%d %H:%M" )
1783+ title = session ["title" ]
1784+ if len (title ) > 50 :
1785+ title = title [:47 ] + "..."
1786+ folder = session ["folders" ][0 ] if session ["folders" ] else "(no folder)"
1787+ display = f"{ title :50} { date_str } { folder } "
1788+ choices .append (questionary .Choice (title = display , value = session ))
17121789
1713- selected = questionary .select (
1714- "Select a session to convert:" ,
1715- choices = choices ,
1716- ).ask ()
1790+ selected = questionary .select (
1791+ "Select a session to convert:" ,
1792+ choices = choices ,
1793+ ).ask ()
17171794
1718- if selected is None :
1719- click .echo ("No session selected." )
1720- return
1795+ if selected is None :
1796+ click .echo ("No session selected." )
1797+ return
17211798
17221799 session_file = selected ["jsonl_path" ]
17231800
0 commit comments