Welcome back! In Chapter 2: Modal Input Processing, we built a sophisticated keyboard and voice interface for our "Spaceship" (the application). We can now send commands into the system.
But a spaceship flying blindly is useless. It needs Sensors and Comms.
This chapter is about Connectivity. Our application is not an island; it lives in a rich ecosystem:
These concepts exist outside of React. This chapter explains how we build "Diplomatic Bridges" to keep our internal state synchronized with the outside world.
useTasksV2
Imagine you have a file called TODO.md on your desktop.
We need a way to "watch" the file system and trigger a re-render the instant the file changes on the disk.
We cannot have every component set up its own file watcher (that would be inefficient). Instead, we create a single Store that watches the file.
We use the useTasksV2 hook, which relies on a React feature called useSyncExternalStore. This allows React to subscribe to things that aren't React state.
import { useTasksV2 } from '../hooks/useTasksV2.js';
export function TaskListDisplay() {
// 1. Subscribe to the external file system
const tasks = useTasksV2();
if (!tasks) return <Text>No tasks found.</Text>;
// 2. Render the live data
return (
<Box flexDirection="column">
{tasks.map(task => <Text key={task.id}>- {task.title}</Text>)}
</Box>
);
}
What happens here?
useTasksV2 checks if the file watcher is running. If not, it starts one.TODO.md in an external editor, the watcher fires.TaskListDisplay updates automatically.useSSHSessionSometimes, we aren't running commands on our own computer. We are controlling a remote server via SSH. This isn't just a simple function call; it's a continuous Session. It can connect, disconnect, lag, or require passwords.
The useSSHSession hook acts as a lifecycle manager. It doesn't just send data; it manages the health of the connection.
This hook provides a sendMessage function that routes your text to the server instead of the local AI.
import { useSSHSession } from '../hooks/useSSHSession.js';
export function RemoteConsole({ session, setMessages }) {
// Initialize the bridge
const { isRemoteMode, sendMessage } = useSSHSession({
session,
setMessages,
// ... other props
});
// If we are connected, show a status indicator
if (isRemoteMode) {
return <Text color="green">Connected to Remote Server</Text>;
}
}
Key Concept: The Bridge
When isRemoteMode is true, the main application loop stops processing your commands locally. Instead, it pipes them through sendMessage, which sends them over the SSH tunnel.
useIDEIntegrationIf a developer is using our AI tool inside VS Code, the AI should be context-aware. If the developer highlights code in VS Code, our App should know about it. But VS Code and our App are two different programs.
We use the Model Context Protocol (MCP) via the useIDEIntegration hook. It tries to auto-connect to the IDE using Server-Sent Events (SSE).
This hook usually runs invisibly in the background of the main layout.
// Inside a top-level component
useIDEIntegration({
autoConnectIdeFlag: true,
setDynamicMcpConfig: (config) => {
// When IDE is found, update the config
console.log("IDE Connected!");
},
// ... callbacks for installation status
});
The Result: When this connects, the AI gains a "new sense." It can now "see" what files are open in your editor, effectively merging the command line tool with the graphical editor.
useTasksV2 Works
Connecting React to the File System is the most complex "External Context" challenge here because it involves threading. Let's trace the data flow using useTasksV2 as an example.
fs.watch function monitors the disk.
The magic happens in TasksV2Store class (inside useTasksV2.ts). It ensures we don't read the disk 100 times if 100 components ask for tasks.
We keep a cached version of the tasks (#tasks) and only update it when the disk actually changes.
// Simplified from useTasksV2.ts
class TasksV2Store {
#tasks: Task[] | undefined = undefined;
// This is what React calls to get data
getSnapshot = () => {
return this.#tasks;
}
}
When the file system watcher detects a change, we fetch the data and notify subscribers. Notice the Debounce: we wait a tiny bit (50ms) because file systems often fire multiple events for a single save.
// Simplified from useTasksV2.ts
#debouncedFetch = () => {
// Clear existing timer to prevent double-fetching
if (this.#debounceTimer) clearTimeout(this.#debounceTimer);
// Wait 50ms, then fetch
this.#debounceTimer = setTimeout(async () => {
const newTasks = await listTasks();
this.#tasks = newTasks; // Update cache
this.#notify(); // Tell React to update
}, 50);
}
Finally, the hook ties the Class to the Component using useSyncExternalStore.
export function useTasksV2() {
const store = getStore(); // Get the singleton instance
return useSyncExternalStore(
store.subscribe, // How to listen
store.getSnapshot // How to get data
);
}
This is the standard, modern way to connect React to anything that isn't React (databases, websockets, file systems).
In this chapter, we learned how to give our AI access to the real world:
useTasksV2: Uses the Singleton Store pattern to watch the file system efficiently without spamming the disk.useSSHSession: Manages the lifecycle of remote connections, acting as a pipe for commands.useIDEIntegration: Auto-discovers and connects to IDEs like VS Code to share context.Now our Spaceship has sensors (File Watchers) and radios (SSH/IDE). It can see the world. But with great power comes great responsibility. If the AI decides to "delete all files," we need a security system to stop it.
Next Chapter: Tool Permission Architecture
Generated by Code IQ