@@ -34,6 +34,14 @@ export interface DaemonStatusReport {
3434 readonly nextStep : string | null ;
3535}
3636
37+ type DaemonRepairLaunchdStatus = {
38+ readonly installed : boolean ;
39+ readonly loaded : boolean ;
40+ readonly running : boolean ;
41+ readonly pid : number | null ;
42+ readonly exitStatus : number | null ;
43+ } ;
44+
3745export async function readDaemonStatus ( {
3846 paths,
3947} : {
@@ -166,3 +174,69 @@ export function buildDaemonStatusReport(opts: {
166174 nextStep : "hack daemon start" ,
167175 } ;
168176}
177+
178+ export function buildDaemonRepairMessage ( opts : {
179+ readonly report : DaemonStatusReport ;
180+ readonly launchdStatus : DaemonRepairLaunchdStatus | null ;
181+ readonly dockerBackendName : string | null ;
182+ readonly dockerReachable : boolean ;
183+ } ) : string {
184+ if ( opts . report . status === "running" ) {
185+ return `hackd running (pid ${ opts . report . pid ?? "unknown" } )` ;
186+ }
187+
188+ if ( opts . report . status === "starting" ) {
189+ return `hackd starting (pid ${
190+ opts . report . pid ?? "unknown"
191+ } ): API not responding yet | If this persists, check: hack daemon logs --tail 200`;
192+ }
193+
194+ if ( opts . report . stale ) {
195+ return "hackd stopped with stale local state | Run: hack daemon clear | Then run: hack daemon start" ;
196+ }
197+
198+ const crashExitStatus = opts . launchdStatus ?. loaded
199+ ? opts . launchdStatus . exitStatus
200+ : null ;
201+ const startCommand =
202+ opts . launchdStatus ?. loaded || crashExitStatus !== null
203+ ? "hack daemon restart"
204+ : "hack daemon start" ;
205+ const segments = [ "hackd is not running" ] ;
206+
207+ if ( crashExitStatus !== null && crashExitStatus !== 0 ) {
208+ segments . push ( `launchd last exit status ${ crashExitStatus } ` ) ;
209+ }
210+
211+ if ( ! opts . dockerReachable ) {
212+ segments . push (
213+ buildDockerStartHint ( { backendName : opts . dockerBackendName } )
214+ ) ;
215+ }
216+
217+ segments . push ( `Run: ${ startCommand } ` ) ;
218+
219+ if ( crashExitStatus !== null && crashExitStatus !== 0 ) {
220+ segments . push ( "Then check: hack daemon logs --tail 200" ) ;
221+ }
222+
223+ return segments . join ( " | " ) ;
224+ }
225+
226+ function buildDockerStartHint ( opts : {
227+ readonly backendName : string | null ;
228+ } ) : string {
229+ if ( opts . backendName === "Docker Desktop" ) {
230+ return "Start Docker Desktop" ;
231+ }
232+
233+ if ( opts . backendName === "OrbStack" ) {
234+ return "Start OrbStack" ;
235+ }
236+
237+ if ( opts . backendName === "Docker (systemd)" ) {
238+ return "Start the Docker system service" ;
239+ }
240+
241+ return "Start Docker" ;
242+ }
0 commit comments