In the previous chapter, Dynamic Agent Scope, we learned how the system dynamically creates folders for AI agents. Before that, Memory Hierarchy Interface showed us how files are organized.
But how do you actually use all of this?
If you have used a command line before, you are probably used to typing long commands. But for managing memory, we want an interactive dashboardβsomething that feels like a modern app, but lives inside your text-based terminal.
This chapter introduces the Terminal Interaction Layer.
Standard terminal programs are "streams." You type a command, hit Enter, and text scrolls by. Once the text is printed, it's deadβyou can't click it or change it.
The Challenge:
memory --toggle-auto --select-file=./CLAUDE.md.We solve this using a library called Ink. Ink lets us build TUIs (Terminal User Interfaces) using React.
If you know React for the web (HTML/CSS), this is exactly the same, but:
<div />, we use <Box />.<span />, we use <Text />.onClick, we use Keybindings (keyboard shortcuts).It translates your React components into text that the terminal draws and updates instantly.
Our goal is to render a screen that looks like this:
Auto-memory: on
Auto-dream: off
> User memory
Project memory
Open auto-memory folder
The user can use the Up/Down Arrows to move the cursor (>) and Enter to select.
In MemoryFileSelector.tsx, we don't just print text strings. We build a visual tree of components.
The layout is a vertical column containing two main sections:
Here is the high-level structure of our component.
// MemoryFileSelector.tsx simplified structure
return (
<Box flexDirection="column" width="100%">
{/* The Header Section */}
<Box flexDirection="column" marginBottom={1}>
<ToggleItem label="Auto-memory" isOn={autoMemoryOn} />
<ToggleItem label="Auto-dream" isOn={autoDreamOn} />
</Box>
{/* The File List Section */}
<Select
options={memoryOptions}
onChange={handleSelect}
/>
</Box>
);
Explanation:
<Box>: Acts like a container (similar to a <div>). flexDirection="column" stacks items vertically.marginBottom={1}: Adds a blank line between the settings and the file list for readability.<Select>: A custom component that renders the list of files.
Since we can't click, we rely on the keyboard. We use a custom hook called useKeybinding. This listens for specific keystrokes and runs a function when they happen.
We need to listen for the "Enter" key (confirmation) to toggle settings or select files.
// Define what happens when the user presses "Enter"
useKeybinding('confirm:yes', () => {
if (focusedToggle === 0) {
// If on first line, toggle memory
handleToggleAutoMemory();
} else if (focusedToggle === 1) {
// If on second line, toggle dreaming
handleToggleAutoDream();
}
}, { isActive: toggleFocused });
Explanation:
'confirm:yes': This is mapped to the Enter key.focusedToggle: A state variable (0 or 1) that tracks which setting is currently highlighted.isActive: A safety check. We only run this logic if the user is currently focused on the toggle section, not the file list.How does the system know whether you are toggling a setting or selecting a file?
The UI has two "modes" or sections:
We manage this with simple state logic. When you press the Down Arrow, we check: "Are we at the bottom of the toggle list? If yes, move focus to the file list."
Let's look at MemoryFileSelector.tsx to see how we handle the "Auto-memory" toggle logic.
We use React's useState to keep track of the setting locally so the UI updates instantly.
// Initialize state with current system setting
const [autoMemoryOn, setAutoMemoryOn] = useState(isAutoMemoryEnabled);
function handleToggleAutoMemory() {
const newValue = !autoMemoryOn;
// 1. Save to disk (persistent settings)
updateSettingsForSource("userSettings", {
autoMemoryEnabled: newValue
});
// 2. Update UI instantly
setAutoMemoryOn(newValue);
}
Explanation:
isAutoMemoryEnabled.updateSettingsForSource) and the frontend state (setAutoMemoryOn). This ensures the text changes from "off" to "on" immediately.We use conditional rendering to change the color of the text based on focus.
// Inside the render return
<ListItem isFocused={focusedToggle === 0}>
<Text>
Auto-memory: {autoMemoryOn ? "on" : "off"}
</Text>
</ListItem>
Explanation:
isFocused: A prop that tells the ListItem to draw a cursor (>) or highlight the background.focusedToggle is 0 (the first index), this item is highlighted.Sometimes the system updates memory in the background (like an agent finishing a task). We need to tell the user without breaking their current screen.
We use a small component called MemoryUpdateNotification.
// MemoryUpdateNotification.tsx
export function MemoryUpdateNotification({ memoryPath }) {
// Convert full path to readable short path (e.g. "./CLAUDE.md")
const displayPath = getRelativeMemoryPath(memoryPath);
return (
<Box flexDirection="column">
<Text color="text">
Memory updated in {displayPath} Β· /memory to edit
</Text>
</Box>
);
}
This simply renders a text message. Because it is a React component, ink handles inserting it into the terminal output stream cleanly.
In this chapter, we learned:
We have a beautiful interface to select files. But when we open a file, how does the AI know where that file is relative to everything else?
Next Chapter: Path Contextualization
Generated by Code IQ