Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions .github/workflows/e2e-teaching-skills.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: E2E Teaching Skills

on:
push:
branches:
- main
- feature/teaching-skills
- feature/teaching-skills-upstream
pull_request:
branches:
- main
- feature/teaching-skills
- feature/teaching-skills-upstream

jobs:
teaching-skills-e2e:
name: Teaching skills E2E (macOS)
runs-on: macos-15
timeout-minutes: 30

steps:
- name: Checkout
uses: actions/checkout@v4

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Run teaching-skills E2E
run: |
chmod +x tests/e2e/run-all.sh tests/e2e/teaching-skills.sh tests/e2e/skills-library.sh tests/e2e/lib/common.sh
./tests/e2e/run-all.sh

- name: Upload E2E logs on failure
if: failure()
uses: actions/upload-artifact@v4
with:
name: teaching-skills-e2e-logs
if-no-files-found: ignore
path: |
/tmp/clicky-e2e-app.log
/tmp/clicky-e2e-app-read.log
/tmp/clicky-e2e-worker.log
/tmp/clicky-e2e-build.log
~/.clicky/e2e-last-system-prompt.txt
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ build/
releases/
.claude/
coding-plans/
.clicky-worktree.env
23 changes: 20 additions & 3 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ Worker vars: `ELEVENLABS_VOICE_ID`
| File | Lines | Purpose |
|------|-------|---------|
| `leanring_buddyApp.swift` | ~89 | Menu bar app entry point. Uses `@NSApplicationDelegateAdaptor` with `CompanionAppDelegate` which creates `MenuBarPanelManager` and starts `CompanionManager`. No main window — the app lives entirely in the status bar. |
| `CompanionManager.swift` | ~1026 | Central state machine. Owns dictation, shortcut monitoring, screen capture, Claude API, ElevenLabs TTS, and overlay management. Tracks voice state (idle/listening/processing/responding), conversation history, model selection, and cursor visibility. Coordinates the full push-to-talk → screenshot → Claude → TTS → pointing pipeline. |
| `CompanionManager.swift` | ~1070 | Central state machine. Owns dictation, shortcut monitoring, screen capture, Claude API, ElevenLabs TTS, overlay management, teaching skills, and niche discovery. Tracks voice state (idle/listening/processing/responding), conversation history, model selection, and cursor visibility. Coordinates the full push-to-talk → screenshot → Claude → TTS → pointing pipeline. |
| `MenuBarPanelManager.swift` | ~243 | NSStatusItem + custom NSPanel lifecycle. Creates the menu bar icon, manages the floating companion panel (show/hide/position), installs click-outside-to-dismiss monitor. |
| `CompanionPanelView.swift` | ~761 | SwiftUI panel content for the menu bar dropdown. Shows companion status, push-to-talk instructions, model picker (Sonnet/Opus), permissions UI, DM feedback button, and quit button. Dark aesthetic using `DS` design system. |
| `CompanionPanelView.swift` | ~850 | SwiftUI panel content for the menu bar dropdown. Shows companion status, push-to-talk instructions, niche onboarding/suggestions, teaching skills UI, model picker (Sonnet/Opus), permissions UI, DM feedback button, and quit button. Dark aesthetic using `DS` design system. |
| `OverlayWindow.swift` | ~881 | Full-screen transparent overlay hosting the blue cursor, response text, waveform, and spinner. Handles cursor animation, element pointing with bezier arcs, multi-monitor coordinate mapping, and fade-out transitions. |
| `CompanionResponseOverlay.swift` | ~217 | SwiftUI view for the response text bubble and waveform displayed next to the cursor in the overlay. |
| `CompanionScreenCaptureUtility.swift` | ~132 | Multi-monitor screenshot capture using ScreenCaptureKit. Returns labeled image data for each connected display. |
Expand All @@ -71,9 +71,26 @@ Worker vars: `ELEVENLABS_VOICE_ID`
| `ElevenLabsTTSClient.swift` | ~81 | ElevenLabs TTS client. Sends text to the Worker proxy, plays back audio via `AVAudioPlayer`. Exposes `isPlaying` for transient cursor scheduling. |
| `ElementLocationDetector.swift` | ~335 | Detects UI element locations in screenshots for cursor pointing. |
| `DesignSystem.swift` | ~880 | Design system tokens — colors, corner radii, shared styles. All UI references `DS.Colors`, `DS.CornerRadius`, etc. |
| `ClickyAnalytics.swift` | ~121 | PostHog analytics integration for usage tracking. |
| `ClickyAnalytics.swift` | ~175 | PostHog analytics integration for usage tracking. |
| `WindowPositionManager.swift` | ~262 | Window placement logic, Screen Recording permission flow, and accessibility permission helpers. |
| `AppBundleConfiguration.swift` | ~28 | Runtime configuration reader for keys stored in the app bundle Info.plist. |
| `TeachingTopicHistoryStore.swift` | ~95 | Persists teaching topic tokens, bundle IDs, and timestamps to `~/.clicky/topic-history.json` for cross-session repeat detection. |
| `PersistedSession.swift` | ~25 | Codable on-disk session model (`sessionId`, `startedAt`, `endedAt`, `outcome`, `privacyOptOut`, `appsUsed`, `turns`) for the memory pipeline capture step. |
| `SessionStore.swift` | ~100 | Filesystem store for voice sessions at `~/.clicky/sessions/<yyyy-MM-dd>/<sessionId>.json` with ISO8601 JSON encoding and 7-day retention cleanup. |
| `TeachingSkillStore.swift` | ~100 | Create/read/update/delete teaching skills at `~/.clicky/skills/<name>/SKILL.md`. |
| `TeachingSkill.swift` | ~280 | Model and YAML frontmatter parsing for teaching skills. |
| `SkillMatcher.swift` | ~170 | App/topic matching and duplicate skill pair detection. |
| `SkillCurator.swift` | ~175 | Time-based stale/archive lifecycle plus throttled LLM merge/patch passes. |
| `SkillSynthesizer.swift` | ~120 | Post-session skill drafting via Claude API. |
| `SkillTriggerEvaluator.swift` | ~120 | Decides when to create or update a teaching skill from session traces. |
| `TeachingPromptBuilder.swift` | ~35 | Composes voice response system prompt with matched teaching skills. |
| `TeachingSkillsLibraryView.swift` | ~260 | Full skills library UI with status filters, detail view, pin/delete/restore. |
| `ClickyE2EConfiguration.swift` | ~75 | Launch flags and E2E debug artifact paths for automated tests. |
| `NicheDiscoveryManager.swift` | ~175 | Niche onboarding, static/app-aware suggestion cards, local override loading. |
| `UserNiche.swift` | ~35 | User niche enum (general, content creator, developer, student, designer). |
| `Resources/niche-examples.json` | ~80 | Bundled niche suggestion packs and app-specific prompt maps. |
| `leanring-buddyTests/TeachingSkillTests.swift` | ~320 | Unit tests for skill parsing, matching, triggers, prompt injection, duplicate detection. |
| `tests/e2e/full-stack/` | — | Scaffold for full user-perspective E2E (BlackHole, PTT simulation, Peekaboo). |
| `worker/src/index.ts` | ~142 | Cloudflare Worker proxy. Three routes: `/chat` (Claude), `/tts` (ElevenLabs), `/transcribe-token` (AssemblyAI temp token). |

## Build & Run
Expand Down
153 changes: 153 additions & 0 deletions FUTURE_IMPLEMENTATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
# Future Implementation — Clicky Fork

Planned features captured from product brainstorming. Not implemented yet.

**Implementation order & E2E test plan:** see [`IMPLEMENTATION_AND_E2E_PLAN.md`](./IMPLEMENTATION_AND_E2E_PLAN.md) — implement Evolving Teaching Skills first, then run automated user-perspective E2E tests.

---

## 1. Evolving Teaching Skills (Auto-Learning)

**Problem:** Clicky starts from zero every session. It does not accumulate knowledge about how to teach specific apps or workflows.

**Concept:** After successful tutoring interactions, Clicky writes reusable teaching skills locally — inspired by Hermes Agent's learning loop, adapted for screen-native teaching (not CLI automation).

### What a teaching skill is

A folder under `~/.clicky/skills/<skill-name>/SKILL.md` using the [agentskills.io](https://agentskills.io) format:

- App or workflow name (e.g. `teach-final-cut-color`, `teach-xcode-source-control`)
- Step order and common user mistakes
- UI vocabulary (button labels, menu paths, shortcuts)
- Pointing heuristics (where to point first, what to avoid)
- Completion signals ("user said got it", step confirmed, correct UI state visible)

### Learning loop

1. User completes a tutoring session (push-to-talk + screen + pointing).
2. Clicky evaluates whether the session is worth persisting (multi-step help, user confirmed success, or repeated topic).
3. Clicky writes or updates a `SKILL.md` with what worked.
4. Next session: relevant skills are loaded into the system prompt when matching apps or topics appear on screen.

### Curator (maintenance)

Prevent skill bloat and stale UI knowledge:

- Track usage: viewed, used, patched
- Auto-transition: `active → stale → archived` after inactivity (e.g. 30 / 90 days)
- Optional LLM review pass to merge duplicates or patch drift when app UI changes
- User can pin important skills so they are never archived

### Triggers (when to create/update a skill)

- Multi-step guidance completed successfully
- User explicitly confirms ("got it", "thanks that worked")
- Same topic asked 2+ times in one week
- NOT: generic Q&A unrelated to screen UI

### Implementation notes

| Layer | Approach |
|-------|----------|
| Storage | `~/.clicky/skills/` (local only, privacy-first) |
| Format | `SKILL.md` with YAML frontmatter (`name`, `description`, optional `paths` for app bundles) |
| Injection | Extend `companionVoiceResponseSystemPrompt` with matched skills at request time |
| Worker | Optional `/skill-synthesize` route for post-session skill drafting (keeps API keys off-device) |
| Swift | New `TeachingSkillStore`, `SkillCurator`, hook in `CompanionManager` after successful responses |
| Phase 2 | GEPA-style optimization from traces (Hermes self-evolution pattern) — research/demo only |

### Success criteria

- Repeat questions on the same app get faster, more accurate pointing
- Skills stay small and relevant (Curator prevents catalog pollution)
- Demo: "Clicky remembered how to teach me Xcode commits from last week"

---

## 2. Niche Discovery (Onboarding + Suggestions)

**Problem:** Many users do not know what Clicky is for or what to ask. Blank-slate AI assistants fail the "first 60 seconds" test.

**Concept:** Help users discover Clicky through niche-specific, concrete examples — not generic "I'm an AI helper" messaging.

### Core UX

1. **Onboarding:** Ask what the user does (content creator, developer, student, designer, etc.) or infer from screen.
2. **Suggestion cards:** Show 3–5 actionable example prompts in the menu bar panel.
3. **Spoken intro (optional):** Clicky briefly explains what it can do *for their niche* via TTS.
4. **Live suggestions:** When screen context matches (e.g. Final Cut, OBS, Premiere), surface timely prompts.

### Example — Content creators

- "Show me where to add captions in this timeline"
- "Walk me through export settings for YouTube"
- "How do I color grade this clip?"
- "Where is the transition menu?"

Each suggestion should imply: **voice + screen + pointing**, not plain chat.

### Niche packs (optional, pairs with teaching skills)

```
~/.clicky/niches/
content-creator/
examples.json # suggested prompts
intro-script.txt # optional spoken onboarding
developer/
examples.json
student/
examples.json
```

Niche selection can seed which teaching skills to prioritize and which apps to watch for.

### Detection strategies

| Method | Effort | Notes |
|--------|--------|-------|
| User picks niche in onboarding | Low | Store in UserDefaults (`selectedUserNiche`) |
| Frontmost app bundle ID | Medium | Map `com.apple.FinalCut` → content creator suggestions |
| Screenshot + Claude one-shot classify | Medium | Fallback when app mapping unknown |
| Proactive idle suggestions | Higher | Tutor mode synergy — suggest when user pauses in a known app |

### Implementation notes

| Layer | Approach |
|-------|----------|
| Swift | `NicheDiscoveryManager`, extend `CompanionPanelView` with suggestion UI |
| Persistence | `UserDefaults` for niche; optional `~/.clicky/profile.md` for richer profile |
| Prompts | Niche-specific example strings + optional niche clause in system prompt |
| Screen | Reuse `CompanionScreenCaptureUtility` + frontmost app from `NSWorkspace` |
| Analytics | Track which suggestions get tapped / spoken (PostHog via existing `ClickyAnalytics`) |

### Success criteria

- New users ask a useful question within first session (measurable via analytics)
- Reduced "what do I use this for?" support confusion
- Niche feels personal: content creators see creator examples, not developer ones

---

## Suggested build order

1. **Niche discovery (light)** — onboarding picker + static suggestion cards per niche
2. **App-aware suggestions** — detect frontmost app, swap examples dynamically
3. **Teaching skills (write)** — post-session skill creation for successful multi-step help
4. **Teaching skills (read + Curator)** — load skills into prompts, maintain library over time
5. **Combine** — niche picks starting suggestions; skills deepen tutoring in that niche over time

---

## Out of scope (for this fork)

- Full Hermes Agent port (Telegram, VPS, 20+ tools)
- Cloud skill sync / marketplace (local-first unless explicitly added later)
- Replacing push-to-talk with Realtime API (separate future idea)

---

## References

- Hermes Agent skills + Curator: https://github.com/NousResearch/hermes-agent
- Agent Skills standard: https://agentskills.io
- Related fork ideas: Skilly (teaching skills), moonmidas/clicky (Tutor mode)
Loading