In the previous chapter, Context Injection, we connected our companion to the AI's brain, allowing it to "see" and "hear" what is happening in the chat.
We now have a complete feature:
But there is one final problem: Invisibility.
If a user installs buddy but doesn't know the command /buddy exists, they will never see their new friend. We need a way to announce the feature without being annoying.
Welcome to Feature Discovery.
Imagine walking past a cinema. You know a new movie is coming out because there is a poster with the release date.
We want to do the same thing in the terminal. We want to show a "Coming Soon" or "Now Available" sign.
However, we need strict rules:
We define a specific date range (e.g., April 1st to April 7th, 2026). The code checks the user's system clock. If we are outside this window, the teaser remains hidden.
A "Feature Flag" is a master switch in the code. If feature('BUDDY') is false, the code acts like the feature doesn't exist. This lets us ship code before it is ready to turn on.
Terminals usually support 16 basic colors. To grab attention, we render text where every letter has a different color from a calculated spectrum.
The discovery logic is packaged into a React Hook called useBuddyNotification. You simply call this hook in your main application component.
You don't pass arguments. The hook checks the environment automatically.
import { useBuddyNotification } from './useBuddyNotification'
export function App() {
// Run the logic silently in the background
useBuddyNotification()
return <Layout>...</Layout>
}
If the date is correct and the user has no buddy, a notification appears at the bottom of the screen:
New Feature: Try typing /buddy to meet your companion!
How does the app decide whether to annoy the user with a popup?
We write a helper function to check the current date. Note that in JavaScript, month starts at 0 (January is 0, April is 3).
// useBuddyNotification.tsx
export function isBuddyTeaserWindow(): boolean {
const d = new Date()
// Only active in April (3) of 2026, from the 1st to the 7th
return d.getFullYear() === 2026
&& d.getMonth() === 3
&& d.getDate() <= 7
}
To make the text /buddy pop, we split the string into individual characters and map a color to each index.
// useBuddyNotification.tsx
function RainbowText({ text }) {
return (
<>
{[...text].map((char, i) => (
// getRainbowColor(i) returns a different hex code based on position
<Text key={i} color={getRainbowColor(i)}>
{char}
</Text>
))}
</>
)
}
This is where we combine everything inside a useEffect. We check the Flag, the Config, and the Date.
// useBuddyNotification.tsx
export function useBuddyNotification() {
const { addNotification } = useNotifications()
useEffect(() => {
// 1. Safety Check: Is feature enabled?
if (!feature('BUDDY')) return
// 2. Logic Check: Do they have a pet? Is it the right date?
const config = getGlobalConfig()
if (config.companion || !isBuddyTeaserWindow()) return
// 3. Action: Show the rainbow text
addNotification({
key: 'buddy-teaser',
jsx: <RainbowText text="/buddy" />,
timeoutMs: 15000 // Disappears after 15 seconds
})
}, [])
}
config.companion, we ensure that once the user engages with the feature, we stop pestering them.Congratulations! You have completed the buddy architecture tutorial.
Let's look back at what we built:
You now understand the full lifecycle of a modern CLI agent featureβfrom the random number generator to the pixels on the screen. Happy coding!
Generated by Code IQ