Termkit

Hooks

Read and manage sessions from anywhere under the provider.

All hooks must be used under a <TermkitProvider>.

Reading sessions

useSessions

const sessions = useSessions(); // LiveSession[]

The live snapshot of every session the daemon is running — the global view, kept fresh by the provider's poller. Independent of which terminals are mounted.

A LiveSession is:

FieldTypeNotes
sessionIdstring
pidnumber
connectedbooleanWhether a client is currently streaming it.
bufferSizenumberLines held in the screen model.
attentionbooleanHas an unseen bell.
metaRecord<string, string>The connect params, echoed back.

useSession

const session = useSession(id); // LiveSession | undefined

useSessionStatus

const status = useSessionStatus(id);
// 'connecting' | 'ready' | 'disconnected' | 'dead' | undefined

A mounted terminal's client-side connection status. undefined if no terminal is attached for that session. (Distinct from whether the daemon still holds the PTY — that's useSession.)

Bells

useRingingSessions

const ringing = useRingingSessions(); // Set<string>

The ids currently ringing for attention. Badge any tab whose id is in the set.

useIsRinging

const isRinging = useIsRinging(id); // boolean

Actions

useTermkitActions

const { focus, blur, kill, dismissBell, dismissAllBells, setPendingCommand } =
  useTermkitActions();
ActionEffect
focus(id) / blur(id)Move keyboard focus to/from a mounted terminal.
kill(id)Reap the daemon's PTY and drop the session from the registry.
dismissBell(id)Clear one session's bell without viewing it.
dismissAllBells()Clear every ringing session's bell (inbox "mark all read").
setPendingCommand(id, cmd)Queue a command to auto-run on the session's next first attach.

The returned object is stable across renders.

Finding orphans

useDanglingSessions

const dangling = useDanglingSessions(knownIds); // LiveSession[]

Live PTYs whose id isn't in the Set of ids your UI knows about (its tabs). The known-id bookkeeping is your domain, so it stays in your code; termkit just does the diff. Useful for surfacing leftover shells for cleanup.

Building your own rollups

Domain groupings (per project, per directory, …) aren't built in — compose them over useSessions() using the opaque meta you set via each terminal's params:

function useCountsBySlug() {
  const sessions = useSessions();
  return useMemo(() => {
    const counts: Record<string, { total: number; bells: number }> = {};
    for (const s of sessions) {
      const slug = s.meta.slug;
      if (!slug) continue;
      const c = (counts[slug] ??= { total: 0, bells: 0 });
      c.total++;
      if (s.attention) c.bells++;
    }
    return counts;
  }, [sessions]);
}

On this page