How it works

The philosophy page says why Naseem behaves the way it does. This one says how. Each section names the mechanism and where you can see it in the app, so every claim here can be tested.

1. Context that stays small

Long tasks die of context bloat: every file read and every build log lands in the prompt until the model forgets the objective. Naseem compacts completed tool work while keeping the full output as artifacts the model can retrieve when it needs them. Compaction is designed to preserve prompt-cache efficiency rather than constantly rewriting the conversation history, so a long session keeps hitting your provider's cache instead of paying full price every turn.

When a run stops making progress, Naseem pauses instead of spending turns indefinitely. It shows the objective and what it tried, and your next message continues the run from there.

Memory across conversations is stored locally as readable markdown. Reveal in Finder shows you everything Naseem remembers.

See it: the tool trail in any run · the brain icon in the toolbar → Memory → Reveal in Finder.

2. Simulator and Mac, driven natively

iOS Simulator. Naseem uses Apple's own Simulator tooling for lifecycle — boot, install, launch — and accessibility information for the UI. It acts on elements rather than guessing coordinates from a screenshot, and it refuses an action when its view of the screen is no longer current.

Mac apps. Native Accessibility API plus synthetic input events. No AppleScript, no screenshots-and-guess, no embedded browser or cloud VM. Every conversation has its own allowlist of apps; the first time the agent reaches for one that is not on it, you get an approval sheet.

See it: the Simulator and Mac tool calls in the trail · the app allowlist in each conversation's settings. Both are Pro.

3. Eyes for any model

Most good coding models are text-only. When a screenshot arrives and the chat model cannot see, Naseem sends the image to the vision model you chose and hands the description back to the chat model as its own inspection. If no vision model is configured, the agent is required to say on the first line of its reply that it could not see the image — no silent guessing. The vision call's tokens are recorded in Usage & Cost like everything else.

See it: Settings → General → Vision model (provider and model) · the "inspected for you by …" block in the trail.

4. Suggestions from your project, not a template

Each project has a readable naseem/ folder with project context, a roadmap, and journal notes — plain markdown you can edit and commit. Naseem uses that context to generate start cards from the actual state of your project rather than a generic list.

Suggestions run on the helper model so they don't consume your chat model's time or budget: a reasoning model once spent thirty seconds and its whole token budget thinking about six one-line cards.

See it: naseem/ in any project folder · Settings → General → Helper model · the start panel of a new chat.

5. Rules that cannot bluff

Rules have to look before they report. Naseem rejects a run that makes no observation, and quiet rules must explicitly distinguish "all clear" from something that needs attention. Silence is never interpreted as success. Dry run lets you see what a rule would do without letting it change anything.

Once a week a heartbeat leads with the run count per rule and names any rule that did not run. The menu bar shows the age of the last run, and a rules-status.json in your Outputs folder mirrors it for anything else that wants to watch.

See it: Tools → Rules · the menu-bar badge · Outputs/rules-status.json. Pro, currently Beta.

6. Light by construction

Naseem is Swift and AppKit/SwiftUI end to end. There is no JavaScript runtime, no Chromium, no Python sidecar. Heavy work — the compiler, the Simulator, the model — happens outside the process. The Memory panel reads the same physical-footprint number Activity Monitor shows, plus the session peak, and attributes it to components so you can see what a long session actually costs.

See it: Tools → Usage & Cost → Memory. A measured figure is on the philosophy page.

7. How a run goes, start to finish

Who does what when you send a request, in plain words.

  • You send a request. The chat model — the one in the header menu — reads it with your project notes, the profile's instructions and the tools it may use.
  • It plans and works. Files, terminal, Simulator, Mac apps, asking first where approval is required. Independent side tasks can go to sub-agents: fresh helpers with only that task, on a cheaper model if you choose one. The transcript says N sub-agents working while they run; only their summaries come back.
  • The chat model writes the answer. Every reply you see is written by the chat model — never by a sub-agent, never by the reviewer.
  • Checks run before you see it. Built-in checks first: did it actually use tools when the task needed them, does every file it says it created exist. Then, if your profile names a review model, that model reads the request, the answer and the list of tool calls, and returns pass or fail with a reason.
  • Pass — the answer is shown unchanged. The reviewer adds nothing to a good answer.
  • Fail — the reason goes back to the chat model, not to you: not complete yet, here is why; reply with the complete answer. It fixes the work, alone or by delegating again, and the checks run once more. The send-back appears as a small note in the activity card.
  • It always ends. Reviews and send-backs are capped per run; after that the run stops and shows the chat model's last answer, so a strict reviewer can never trap a run.
  • Afterwards, Usage & Cost lists every call by model: the chat model's turns, the sub-agents' calls, the reviewer's call.

See it: the activity card of any run · Profiles → Edit → Models by phase (Pro) · Usage & Cost.

8. Where your data goes

Naseem hosts nothing. Every connection leaves your Mac directly for a service you configured with your own key.

your Mac ──▶ model provider API (Anthropic, OpenAI, Gemini, OpenRouter, Ollama Cloud) your Mac ──▶ api.telegram.org (long-polled by the app; replies go the same way) your Mac ──▶ Tavily or Brave (web search, only if you add a key) your Mac ──▶ nowhere (local Ollama, on-device MLX) Naseem servers: none. Telemetry: none.

Telegram accepts commands only from the user id you set. The gateway does not start until one is configured: blank means nobody, not everybody.

See it: Settings → Providers · Settings → Integrations → Telegram → Allowed user id.