/tip
Author a new contextual tip for Nimbalyst's tips system (transcript-inline tip cards with trigger/targeting rules).
$ npx -y skills add nimbalyst/nimbalyst --agent claude-codeHow it fires
How this command gets triggered: by you, by Claude, or both.
- Fires itselfClaude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/tip
Context preview
What this command does when you run it.
Author a new contextual tip for Nimbalyst's tips system (transcript-inline tip cards with trigger/targeting rules).
Command definition
tip.mdname: tip
description: Author a new contextual tip for Nimbalyst's tips system (transcript-inline tip cards with trigger/targeting rules).
Author a new contextual tip: {{arg1}}
A **contextual tip** is a small, dismissible card Nimbalyst shows in the empty panel of a new AI session to teach users a feature they have not discovered yet. We are adding many of these to help users get the most value from Nimbalyst. This command walks you through writing one correctly.
If `{{arg1}}` is empty, ask the user what feature/behavior the tip should teach and who should see it, then proceed.
How the tips system works (read before writing)
All code lives under `packages/electron/src/renderer/tips/`.
Where a tip is displayed
Tips render **inline in the empty panel of a new/unused AI session transcript** — not as a floating popup (the floating `TipCard` variant exists but is dormant). The surface is wired in `SessionTranscript.tsx` via `renderEmptyExtra()`, which mounts `InlineTipDisplay` above the slash-command suggestions when `messages.length === 0`.
- The card shows: icon + title + body (basic markdown) + optional primary action button + optional secondary link.
- Footer controls: **Next** (cycles through tips, sorted by priority) and **All tips** (opens `AllTipsDialog` to browse every tip).
- Dismiss = X button; primary action = `markTipCompleted`; both clear the active tip.
- Body markdown (`parseMarkdownBody` in `TipCard.tsx`) supports only: `**bold**`, paragraph breaks (blank line), and bullet lists (`- ` / `* `). No links, headings, or inline code.
How targeting / rules work
`TipProvider.tsx` runs an evaluation loop. A tip is **eligible** only when ALL of these hold: 1. Not shown yet this app launch (`tipShownThisSession` — in-memory, one tip per launch, resets on restart). 2. Help/tips master toggle is on (`walkthroughState.enabled`), no walkthrough active, no dialog/overlay visible, no tip already active. 3. An empty-transcript surface is mounted (`emptyTranscriptVisibleCountAtom > 0`). 4. Not previously dismissed or completed (`shouldShowTip` in `TipService.ts`) — unless `version` was bumped. 5. `trigger.screen === '*'` OR matches the current `ContentMode` (e.g. `'agent'`, `'files'`, `'tracker'`). 6. `trigger.condition(context)` returns `true`.
Among eligible tips, the highest `priority` wins; then it waits `trigger.delay` ms and re-checks the condition before showing. The loop only starts ~15s after launch and re-evaluates every 5s, reading live state from refs.
The `condition` receives a `TipTriggerContext`:
interface TipTriggerContext {
currentMode: ContentMode;
workspacePath?: string;
isGitRepo: boolean;
isWorktreesAvailable: boolean;
featureUsage: Record<string, FeatureUsageRecord>;
hasBeenUsed: (feature: string) => boolean; // count > 0
hasReachedCount: (feature: string, threshold: number) => boolean; // count >= threshold
}Most tips follow the pattern "user has done X enough times but never used Y" — e.g. `hasReachedCount(SESSION_CREATED, 10) && !hasBeenUsed(WORKTREE_CREATED)`. The condition must be a **pure, synchronous** predicate (no async, no IPC).
Persistence & analytics
Tips reuse the walkthrough store via IPC (no new tables). IDs MUST start with `tip-`. Bumping `version` re-shows a tip to users who dismissed an older version. PostHog events (`tip_shown`, `tip_dismissed`, `tip_action_clicked`, `tip_navigated`, `tip_all_tips_opened`) are captured automatically — do not add your own.
Steps to author the tip
1. Pick the trigger signal
Decide what user state should surface this tip. If you can express it with an existing key in `FEATURE_USAGE_KEYS` (`packages/electron/src/shared/featureUsage.ts`), use it. Current keys include: `SESSION_CREATED`, `SESSION_COMPLETED`, `APP_LAUNCH`, `AI_PROMPT_SUBMITTED`, `EXCALIDRAW_OPENED`, `MOCKUP_OPENED`, `SPREADSHEET_OPENED`, `DATAMODEL_OPENED`, `TRACKER_USED`, `THEME_CHANGED`, `KEYBOARD_SHORTCUT_USED`, `FILE_CREATED`, `WORKTREE_CREATED`.
If no key fits, you must add a new one (see step 4) AND wire a `recordUsage` call at the feature's call site — otherwise the condition can never flip and the tip will never show. Confirm with the user before introducing a new key.
2. Create the definition file
`packages/electron/src/renderer/tips/definitions/<kebab-name>.tsx`. Match the style of a nearby tip such as `worktree-session.tsx`. Prefer `<MaterialSymbol icon="..." size={16} />` for the icon. Drive actions through atoms/IPC/`dialogRef` like the existing tips do — never reach into DOM.
**Action options.** A tip's `content.action` can either:
- run code via `onClick` (navigate, open a dialog, set an atom), or
- seed the composer via `insertPrompt: '/some-command '` — drops that text into the session input so the user can review and submit. Use this to point at a slash command (e.g. a planning-extension command). `insertPrompt` only works in the inline surface of a **claude-code** session; the button is hidden automatically where there's nowhere to insert, so keep the body meaningful without it. See `session-cleanup.tsx`.
import { MaterialSymbol } from '@nimbalyst/runtime';
import { store } from '@nimbalyst/runtime/store';
import { FEATURE_USAGE_KEYS } from '../../../shared/featureUsage';
import type { TipDefinition } from '../types';
const Icon = <MaterialSymbol icon="lightbulb" size={16} />;
export const myFeatureTip: TipDefinition = {
id: 'tip-my-feature', // MUST start with 'tip-'
name: 'My Feature Suggestion', // human-readable, used in analytics
version: 1, // bump later to re-show after dismissal
trigger: {
screen: '*', // or 'agent' | 'files' | 'tracker' | ...
condition: (ctx) =>
ctx.hasReachedCount(FEATURE_USAGE_KEYS.SESSION_CREATED, 5) &&
!ctx.hasBeenUsed(FEATURE_USAGE_KEYS.MY_FEATURE),
delay: 2500, // ms after eligible before showing (default 2000)
priority:Read more
name: tip description: Author a new contextual tip for Nimbalyst's tips system (transcript-inline tip cards with trigger/targeting rules).
Author a new contextual tip: {{arg1}}
A **contextual tip** is a small, dismissible card Nimbalyst shows in the empty panel of a new AI session to teach users a feature they have not discovered yet. We are adding many of these to help users get the most value from Nimbalyst. This command walks you through writing one correctly.
If `{{arg1}}` is empty, ask the user what feature/behavior the tip should teach and who should see it, then proceed.
How the tips system works (read before writing)
All code lives under `packages/electron/src/renderer/tips/`.
Where a tip is displayed
Tips render **inline in the empty panel of a new/unused AI session transcript** — not as a floating popup (the floating `TipCard` variant exists but is dormant). The surface is wired in `SessionTranscript.tsx` via `renderEmptyExtra()`, which mounts `InlineTipDisplay` above the slash-command suggestions when `messages.length === 0`.
- The card shows: icon + title + body (basic markdown) + optional primary action button + optional secondary link.
- Footer controls: **Next** (cycles through tips, sorted by priority) and **All tips** (opens `AllTipsDialog` to browse every tip).
- Dismiss = X button; primary action = `markTipCompleted`; both clear the active tip.
- Body markdown (`parseMarkdownBody` in `TipCard.tsx`) supports only: `**bold**`, paragraph breaks (blank line), and bullet lists (`- ` / `* `). No links, headings, or inline code.
How targeting / rules work
`TipProvider.tsx` runs an evaluation loop. A tip is **eligible** only when ALL of these hold: 1. Not shown yet this app launch (`tipShownThisSession` — in-memory, one tip per launch, resets on restart). 2. Help/tips master toggle is on (`walkthroughState.enabled`), no walkthrough active, no dialog/overlay visible, no tip already active. 3. An empty-transcript surface is mounted (`emptyTranscriptVisibleCountAtom > 0`). 4. Not previously dismissed or completed (`shouldShowTip` in `TipService.ts`) — unless `version` was bumped. 5. `trigger.screen === '*'` OR matches the current `ContentMode` (e.g. `'agent'`, `'files'`, `'tracker'`). 6. `trigger.condition(context)` returns `true`.
Among eligible tips, the highest `priority` wins; then it waits `trigger.delay` ms and re-checks the condition before showing. The loop only starts ~15s after launch and re-evaluates every 5s, reading live state from refs.
The `condition` receives a `TipTriggerContext`:
interface TipTriggerContext {
currentMode: ContentMode;
workspacePath?: string;
isGitRepo: boolean;
isWorktreesAvailable: boolean;
featureUsage: Record<string, FeatureUsageRecord>;
hasBeenUsed: (feature: string) => boolean; // count > 0
hasReachedCount: (feature: string, threshold: number) => boolean; // count >= threshold
}Most tips follow the pattern "user has done X enough times but never used Y" — e.g. `hasReachedCount(SESSION_CREATED, 10) && !hasBeenUsed(WORKTREE_CREATED)`. The condition must be a **pure, synchronous** predicate (no async, no IPC).
Persistence & analytics
Tips reuse the walkthrough store via IPC (no new tables). IDs MUST start with `tip-`. Bumping `version` re-shows a tip to users who dismissed an older version. PostHog events (`tip_shown`, `tip_dismissed`, `tip_action_clicked`, `tip_navigated`, `tip_all_tips_opened`) are captured automatically — do not add your own.
Steps to author the tip
1. Pick the trigger signal
Decide what user state should surface this tip. If you can express it with an existing key in `FEATURE_USAGE_KEYS` (`packages/electron/src/shared/featureUsage.ts`), use it. Current keys include: `SESSION_CREATED`, `SESSION_COMPLETED`, `APP_LAUNCH`, `AI_PROMPT_SUBMITTED`, `EXCALIDRAW_OPENED`, `MOCKUP_OPENED`, `SPREADSHEET_OPENED`, `DATAMODEL_OPENED`, `TRACKER_USED`, `THEME_CHANGED`, `KEYBOARD_SHORTCUT_USED`, `FILE_CREATED`, `WORKTREE_CREATED`.
If no key fits, you must add a new one (see step 4) AND wire a `recordUsage` call at the feature's call site — otherwise the condition can never flip and the tip will never show. Confirm with the user before introducing a new key.
2. Create the definition file
`packages/electron/src/renderer/tips/definitions/<kebab-name>.tsx`. Match the style of a nearby tip such as `worktree-session.tsx`. Prefer `<MaterialSymbol icon="..." size={16} />` for the icon. Drive actions through atoms/IPC/`dialogRef` like the existing tips do — never reach into DOM.
**Action options.** A tip's `content.action` can either:
- run code via `onClick` (navigate, open a dialog, set an atom), or
- seed the composer via `insertPrompt: '/some-command '` — drops that text into the session input so the user can review and submit. Use this to point at a slash command (e.g. a planning-extension command). `insertPrompt` only works in the inline surface of a **claude-code** session; the button is hidden automatically where there's nowhere to insert, so keep the body meaningful without it. See `session-cleanup.tsx`.
import { MaterialSymbol } from '@nimbalyst/runtime';
import { store } from '@nimbalyst/runtime/store';
import { FEATURE_USAGE_KEYS } from '../../../shared/featureUsage';
import type { TipDefinition } from '../types';
const Icon = <MaterialSymbol icon="lightbulb" size={16} />;
export const myFeatureTip: TipDefinition = {
id: 'tip-my-feature', // MUST start with 'tip-'
name: 'My Feature Suggestion', // human-readable, used in analytics
version: 1, // bump later to re-show after dismissal
trigger: {
screen: '*', // or 'agent' | 'files' | 'tracker' | ...
condition: (ctx) =>
ctx.hasReachedCount(FEATURE_USAGE_KEYS.SESSION_CREATED, 5) &&
!ctx.hasBeenUsed(FEATURE_USAGE_KEYS.MY_FEATURE),
delay: 2500, // ms after eligible before showing (default 2000)
priority:Nimbalyst is a free, open-source, local, interactive visual editor & session/task manager for developers, product managers, designers, builders.
Repo: nimbalyst/nimbalyst
Other commands on nimbalyst.
- /android-release
Prepare and execute an Android release (patch/minor/major)
Open command - /bug-report
Gather details and draft an actionable bug report for developers.
Open command - /commit
Create a git commit with concise, bullet-point commit message
Open command - /design
Create a new plan document for tracking work.
Open command - /e2e-devcontainer
Run E2E tests in a dev container (isolated environment)
Open command - /implement
Execute a plan document while keeping progress synchronized.
Open command

