Skip to content
System One

milind-soni/tiptour-macos

A macOS menu bar companion with two modes: type a task and Jev picks what to click from a local OmniParser running on CoreML, looping for up to 12 actions, or talk to Gemini Live, which takes one desktop action per turn.

TipTour cursor actions
Image from github.com

milind-soni/tiptour-macos on GitHub

Stars
662
Forks
103
Language
Swift
Last push
19 Sep 2026

Post on X

Views
61,095
Likes
509
Reposts
29

Read from GitHub and X on . Counts change daily.

Reported by the author

Action limit
12 actionsThe loop stops when JEV chooses none or reports completion, on an execution pause/failure, or at its 12-action limit.github.com

TipTour is a macOS menu bar app with two ways to drive your desktop. Press Ctrl+Option and talk, and Gemini handles clicking, typing, shortcuts, opening apps or URLs, scrolling, and highlighted-text edits, one action per turn. Press Ctrl+K instead and type a task, and Jev takes over: a local OmniParser model running on CoreML detects the controls on screen, and Jev chooses which one to click, double-click, or right-click.

Jev’s role is narrower than Gemini’s. It works from on-screen labels and locations, not images, and it cannot generate replacement text, so the README says to use Gemini for writing or keyboard actions. It acts on its top-ranked target each turn with no confidence cutoff. The loop stops when Jev chooses none or reports completion, on an execution pause or failure, or at a 12-action limit. TipTour executes and validates each action.

You bring your own API keys, stored in macOS Keychain, with no shared keys or hosted proxies. In the earlier demo post, Soni reports about 90ms per Jev decision. The open-source post says voice mode is next if people want it.

How it uses Jev

private let metrics = JevCallMetrics(milliseconds: 1, inputTokens: 100, model: "jev-latest")
private func candidate(_ id: String = "save", label: String = "Save") -> JevCandidate {
    JevCandidate(id: id, label: label, source: "ocr", confidence: 1, centre: .zero)
}
private func answers(choice: String = "save", absent: Double = 0.1,
                     probability: Double = 0.9, kind: String = "click") throws -> [String: JevAnswer] {
    let data = try JSONSerialization.data(withJSONObject: [
        "pick": ["choice": choice, "probabilities": [choice: probability]],
        "done": ["noul": 0.1], "absent": ["noul": absent], "kind": ["choice": kind]
    ])
    return try JSONDecoder().decode([String: JevAnswer].self, from: data)
}

View in TipTourTests/JevTests.swift

Open on GitHub

More like this

Use cases this is tagged with