What Aartiq
Actually Does
This page documents Aartiq's features against the source code. Every section cites the file and line it is implemented in. Where a feature is off by default, limited, or platform-specific, that is stated explicitly. No marketing language.
Permission Management & Human-in-the-Loop
Aartiq gates every side-effecting action through a risk-tiered permission store, a capability controller with single-use tickets, an OS-native approval dialog (Touch ID / Windows Hello), and an optional QR + PIN mobile approval for high-risk commands. The defaults are deny-by-default and fail-closed.
Risk-tiered shell gating
checkShellPermission() classifies commands as low / medium / high / critical. critical is always denied at the gate; high/medium/low are denied unless a matching PermissionStore grant exists. With no PermissionStore configured the command is denied (fail-closed).
src/core/command-validator.js:77-133src/core/command-validator.js:87-89Customizable approval policy
Per-command and per-action allowlists (autoApprovedCommands / autoApprovedActions), plus toggles autoApproveLowRisk / autoApproveMidRisk (both default false). High-risk actions are never globally auto-run. Users manage this in the Permission Settings UI and the Directory Allowlist editor.
src/lib/permission-store.js:24-33src/components/PermissionSettings.tsx:476-512src/components/PermissionSettings.tsx:889-1029Directory allowlist
File access is restricted to an allowlist where each entry has an access level (read vs read-write) and a recursive flag. Paths are canonicalized with fs.realpathSync before checking, so symlink traversal is blocked. An empty allowlist denies everything.
src/core/directory-allowlist.js:60-134src/lib/permission-store.js:8-16Capability-scoped execution
Each action is registered with an approval tier (never / first-time-per-session / always). 'always' cannot be overridden by the permission store. Approvals use single-use tickets bound to the exact input hash, with a 5-minute TTL and timingSafeEqual integrity checks.
src/core/capability-controller.js:29-100src/core/approval-ticket-manager.js:139-278src/lib/approval-gate.js:53-147QR + PIN mobile approval
High-risk commands generate a 6-digit PIN (100000 + rand%900000) and a per-request token encoded into a aartiq://approve deep link rendered as a QR. The paired mobile app returns the PIN; the desktop only enables Approve when both mobileApproved and pinVerified are true. The QR is single-use.
src/main/handlers/sync-handlers.js:40-48src/main/handlers/utils.js:377-387src/components/ai/ClickPermissionModal.tsx:247-302Biometric approval (Touch ID / Windows Hello)
Native approval dialogs: macOS shows 'Approve with Touch ID', Windows runs a PowerShell dialog, Linux a bash dialog. Biometric is gated by requireBiometricPerSession (default true) and requireBiometricEveryTime (default false). macOS Touch ID is also invoked directly from the native Swift panels via LAContext.
src/main/handlers/native-approval-manager.js:22-98src/components/ai/useAIActionSecurityManager.tsx:120-153src/lib/native-panels/ViewModel.swift:255-275Cross-Session Memory & Preference Learning
Aartiq can remember past conversations (RAG vector store on disk) and learn user preferences from chat. Both are OFF by default and can be disabled. There are two storage layers: an IPC/persisted layer (authoritative) and a legacy localStorage layer used by some sidebar widgets.
Cross-session RAG memory
Conversations, page content, web-search results, OCR and SecureDOM reads are embedded and stored in vector-store.json under Electron userData, reloaded on startup, and injected as a [RAG MEMORY] block into each chat. Gated by enableCrossSessionMemory (default false).
src/main/handlers/memory-handlers.js:25-41src/lib/BrowserAI.ts:103-149src/store/useAppStore.ts:179,913Preference learning
When enabled, the model can emit SAVE_PREFERENCE:key:value in its reply; Aartiq parses it and stores it in userData/ai-user-preferences.json. Learned preferences are re-injected into the system prompt. Default off. Examples from the prompt: response_style:concise, language:simple_english.
src/store/useAppStore.ts:177,911src/components/ai/AIConstants.ts:408-410src/components/AIChatSidebar.tsx:1911-1923src/main/handlers/ai-handlers.js:186-212Memory management UI
AiMemoryManagerSection lets you edit/delete individual learned preferences and clear the vector memory. The sidebar MemoryWidget adds search over stored preferences and a clear-data action. PrivacyControls exposes Disable Memory and Disable Preference Learning toggles.
src/components/ai/AiMemoryManagerSection.tsx:38-203src/components/sidebar/widgets/MemoryWidget.tsx:54-197src/components/sidebar/PrivacyControls.tsx:37-63Session resume
SessionResumeWidget reads browser history (last 3) and stored automation runs to offer 'Pick up where you left off' and 'Restore automations' cards that re-launch an AI task. It uses history + automation-run history, not the vector store directly.
src/components/sidebar/widgets/home/SessionResumeWidget.tsx:15-70src/lib/homeIntelligence.ts:340-374Action Chain & Approval UI
AI tasks are executed one command at a time, with a live action chain and a pre-execution plan that shows risk levels and asks the user to Approve / Deny / Modify.
Live action chain timeline
ActionChainTimeline renders steps with status pending / running / done / error / skipped, a completed/total badge, and per-step timestamps. SessionTimelineWidget mirrors this live in the sidebar with a progress bar.
src/components/ai/ActionChainTimeline.tsx:7-15,97-286src/components/sidebar/widgets/SessionTimelineWidget.tsx:49-95Pre-execution plan + risk verdict
AutomationPlanApproval shows the full plan before running: each operation with its risk (low/medium/high/critical), a policy verdict (allow / requires approval / denied by policy), directories and URLs accessed, and Approve / Deny / Modify buttons. critical operations are blocked by policy.
src/components/AutomationPlanApproval.tsx:11-47src/components/AutomationPlanApproval.tsx:180-404Step-by-step queue with per-step approval
AIChatSidebar.processNextCommand runs the queue one command at a time, marking each awaiting_permission before a human approves. Critical-risk commands are auto-failed. Risk drives the label: high = Touch ID + approval, medium = approval required, low = automatic.
src/components/AIChatSidebar.tsx:2170-2204,5884src/components/AICommandQueue.tsx:27,184,233-237Approval waiting + guardrails
ApprovalWaiter blocks execution until the human approves or a 5-minute timeout fires. Guardrails prompt-injection detection fails closed (quarantine), and the SecurityPipeline returns requiresApproval before any side-effecting action. ApprovalGate binds approval to the input hash (one-time, unexpired).
src/lib/approval-waiter.ts:1-108src/lib/guardrails/prompt-injection.ts:18-316src/lib/guardrails/index.ts:95-146AI Command System
AI output is parsed into structured commands. The parser is JSON-first, then HTML-comment, then bracket tags. There is no RUN_SHELL verb; the shell command is SHELL_COMMAND and is rated HIGH risk and never auto-executes.
JSON-first command parser
AICommandParser tries JSON (```json blocks and bare {commands:[...]}), then <!-- AI_COMMANDS_START -->...<!-- AI_COMMANDS_END -->, then [TYPE]:value bracket tags. Duplicate-free and masked inside code/inline/<think:6124c78e> blocks. See /docs/ai-commands for the full verb list.
src/lib/AICommandParser.ts:374-513src/lib/AICommandParser.ts:62-138Canonical verbs
NAVIGATE, SHELL_COMMAND, CLICK_ELEMENT, FIND_AND_CLICK, FILL_FORM, MULTI_FILL_FORM, CLICK_AT, SCROLL_TO, SEARCH/WEB_SEARCH, READ_PAGE_CONTENT, OCR_SCREEN, LIST_OPEN_TABS, CREATE_FILE_JSON/GENERATE_PDF, OPEN_APP, SCHEDULE_TASK, RECORD_WORKFLOW/PLAY_WORKFLOW, PLUGIN_COMMAND, and SETTINGS_*/BOOKMARKS_*/HISTORY_*/SKILLS_* commands.
src/lib/AICommandParser.ts:62-135Shell validation + sandbox
A parsed SHELL_COMMAND value is validated by SecurityValidator (destructive-pattern / blocked-list), risk-classified by ai-action-security (HIGH, never auto-execute), gated by checkShellPermission, then run inside the fail-closed OS sandbox.
src/lib/SecurityValidator.js:2,164-178,316-346src/lib/ai-action-security.ts:520-544src/main/handlers/utils.js:111-118,244-264Recorded workflow replay
RECORD_WORKFLOW / PLAY_WORKFLOW replay recorded DOM actions via action-replay: 3 retries with backoff and element re-matching (exact / similar / fuzzy) across page-state changes. This is separate from the live AI command queue.
src/lib/action-replay.ts:7-133,202-227Aartiq Skills
Skills are two things: (1) Markdown prompt files in public/skills/*.md loaded on demand, and (2) a capability catalog (SkillRegistry) that matches the user's message to relevant skills so the system prompt is not bloated. See /docs/skills for the full list and the agent API.
Markdown prompt skills
SkillLoader is a singleton that reads public/skills/<name>.md (built-in + userData override), strips YAML-ish frontmatter and 'Aartiq runtime note' blocks, and caches. Built-ins include research, analysis, finance, documents, browsing, automation, mcp, apple-intelligence, tab-intelligence, image-generation, scheduling, security, settings, xlsx, pptx, pdf, docx.
src/lib/SkillLoader.ts:9-140src/lib/SkillRegistry.ts:15-29On-demand skill matching
SkillRegistry.matchSkills tests each skill's regex patterns against the message and always injects 'security' for credential terms and 'automation' for shell terms. listAllSkills / getSkillSummary drive the UI chip list shown by CollapsibleSkillMessage.
src/lib/SkillRegistry.ts:1-64src/components/ai/CollapsibleSkillMessage.tsx:4-68Agent API (MCP + HTTP tools)
The agent API exposes a ToolRegistry over MCP (stdio) and HTTP (POST /api/<method>). Every call runs a fail-closed pipeline: verb gate -> tab lock -> handler -> untrusted-output injection scan. Providers are model-agnostic (LM Studio / Ollama / OpenClaw), bound to 127.0.0.1 by default with defaultTrust 'limited'.
src/lib/agent-api/registry.ts:1-89src/lib/agent-api/server.ts:1-126src/lib/agent-api/providers.ts:19-80Native macOS Panels & Apple Integration
On macOS, Aartiq can render detached native SwiftUI panels (compiled from src/lib/native-panels/*.swift) instead of the Electron UI, communicating over the same /native-mac-ui HTTP bridge. These run only on macOS and only when the relevant *Mode preference is 'swiftui'.
Native SwiftUI AI sidebar
SidebarPanelView is a native SwiftUI chat surface (its own message bubbles + prompt composer + session chips) that can replace the Electron sidebar when sidebarMode === 'swiftui'. The Swift files are compiled by swiftc and spawned as a detached binary from the main process.
src/lib/native-panels/SidebarView.swift:3-238src/lib/macos-native-panels.js:7-196src/main.js:1184,2092-2093Command Center & settings panels
CommandCenterPanelView launches any native panel from one place; NativeSettingsPanelView bridges native toggles (sidebar/actionChain/utility/permission mode: swiftui vs electron) to the Electron settings window.
src/lib/native-panels/CommandCenterView.swift:3-19src/lib/native-panels/SettingsView.swift:3-218Apple Intelligence
AppleIntelligencePanelView uses on-device FoundationModels (LanguageModelSession) for Summary / Analyze / Rewrite / Extract / Writing Tools, Image Playground for image generation, and Genmoji. Summary is gated on the FoundationModels runtime (macOS 15+). A helper binary (Aartiq-AppleIntelligence) exposes the same to the React UI.
src/lib/native-panels/AppleIntelligencePanelView.swift:3-294,362-402src/lib/apple-intelligence.swift:253-289Siri & Shortcuts
AppIntents.swift (AartiqShortcutsProvider) exposes intents such as 'Ask Aartiq', Search web, Summarize page, Capture screenshot, Open app, Schedule task, Read clipboard, Create document. Shortcuts/Siri drive the live browser over HTTP with an X-Aartiq-Native-Token header. JS bridge: SiriShortcutsIntegration.js.
src/lib/native-panels/AppIntents.swift:532-823src/lib/SiriShortcutsIntegration.js:132,267Built-in Ad Blocker
Aartiq ships a built-in network-level ad + tracker blocker (no extension required). It is OFF by default and only active after a ~5s deferred init; it protects the default session only and uses the prebuilt ads+tracking filter list (no custom-filter UI).
ElectronBlocker (ads + tracking)
main.js initializes @ghostery/adblocker-electron via ElectronBlocker.fromPrebuiltAdsAndTracking(fetch) and applies it to session.defaultSession. Toggling enableAdblocker in Settings calls toggle-adblocker; if the blocker isn't initialized yet, the toggle is a no-op.
main.js:2694,3688-3692,4011-4027src/store/useAppStore.ts:311-313,544-551src/components/SettingsPanel.tsx:668-684Session Logs & Export
Aartiq keeps an audit log of AI actions in five buckets (pdf / action / shell / ocr / dom), persisted to localStorage, and can export them as structured JSON or plain text.
What the logs contain
Each entry has timestamp, success, output/error. Shell logs add command + permissionRequired + permissionGranted + executionTime. OCR logs add label + textLength + source. DOM logs add resultsCount + injectionDetected + filter stats (pii/scripts/styles/nav/ads removed). PDF logs add command + filePath.
src/lib/ActionLogsStore.ts:11-65Export (JSON + text)
exportAsJSON() emits { type:'AARTIQ_AI_ACTION_LOGS', version:'1.0', summary, logs } with counts per bucket. exportAsText() renders a human-readable list. From the chat UI these are written to disk via export-chat-txt / export-chat-pdf (default file names comet-chat-<ts>.txt / .pdf).
src/lib/ActionLogsStore.ts:308-405src/components/AIChatSidebar.tsx:6051-6054src/main/handlers/file-handlers.js:428-472Web Search & OCR Results (Expandable)
Web search and OCR/screenshot output are rendered through a single expandable component (CollapsibleOCRMessage) so long results don't flood the chat until expanded.
Collapsible results
CollapsibleOCRMessage shows a label (e.g. 'Search Results' for WEB_SEARCH_RESULTS, 'SCREENSHOT_ANALYSIS' for OCR) with a truncated 100-char preview when collapsed and a scrollable body (max-h-400px) with clickable URL/file links when expanded. Web search output is stored with ocrLabel 'WEB_SEARCH_RESULTS'.
src/components/ai/CollapsibleOCRMessage.tsx:17,112-153src/components/AIChatSidebar.tsx:2850,2893-2895,7223Settings Reference
Every user-facing setting, its default value, what it does, and where it is defined. Defaults are read directly from source. "Off by default" flags mean the behaviour only activates once you enable it.
AI & Intelligence
| Key | Default | What it does | Source |
|---|---|---|---|
| enableAIAssist | false | Master switch for the AI assistant | useAppStore.ts:103,417 |
| aiProvider | 'ollama' | Active LLM provider | useAppStore.ts:108,432 |
| enableAiOverview | false | One-glance summaries on page load | useAppStore.ts:149,441 |
| askForAiPermission | true | Prompt before AI actions | useAppStore.ts:153,897 |
| aiSafetyMode | true | AI asks confirmation before critical actions | useAppStore.ts:173,907 |
| enableAiPreferenceLearning | false | AI learns preferences via SAVE_PREFERENCE | useAppStore.ts:177,911 |
| enableCrossSessionMemory | false | RAG memory across sessions | useAppStore.ts:179,913 |
| localLlmMode | 'normal' | light | normal | heavy | useAppStore.ts:143,437 |
| mcpServerPort | 3001 | Local MCP server port | useAppStore.ts:159,444 |
Security & Permissions
| Key | Default | What it does | Source |
|---|---|---|---|
| autoApproveLowRisk | false | Auto-run low-risk actions | permission-store.js:25 |
| autoApproveMidRisk | false | Auto-run medium-risk actions | permission-store.js:26 |
| requireDeviceUnlockForManualApproval | true | OS unlock after manual shell approval | permission-store.js:27 |
| requireDeviceUnlockForVaultAccess | true | OS unlock before revealing credentials | permission-store.js:28 |
| requireBiometricPerSession | true | Touch ID / Hello once per session | permission-store.js:29 |
| requireBiometricEveryTime | false | Biometric for EVERY low-risk action | PermissionSettings.tsx:90 |
| firewallLevel | 'standard' | standard | strict | paranoid | useAppStore.ts:292,501 |
Privacy
| Key | Default | What it does | Source |
|---|---|---|---|
| disableMemory | false | Stop AI remembering conversations | sidebar/types.ts:73 |
| disablePreferenceLearning | false | Stop AI learning preferences | sidebar/types.ts:74 |
| disableTabIntelligence | false | Stop AI analyzing open tabs | sidebar/types.ts:75 |
| disableAnimations | false | Turn off AI status animations/glow | sidebar/types.ts:76 |
Appearance & Theme
| Key | Default | What it does | Source |
|---|---|---|---|
| theme | 'system' | system | dark | light | vibrant | custom | minimal | useAppStore.ts:183,457 |
| customThemePrimary | '#ff6b6b' | Custom theme primary color | useAppStore.ts:184,458 |
| customThemeSecondary | '#22d3ee' | Custom theme secondary color | useAppStore.ts:185,459 |
| browserTabLayout | 'top' | top | left | right | both | useAppStore.ts:189,460 |
| browserAccentPreset | 'minimal' | minimal | brave | ocean | mint | rose | mono | useAppStore.ts:190,461 |
| minimalAnimations | true | Animations master toggle (store) | useAppStore.ts:197,464 |
| themeOpacity | 100 | Interface opacity (20-100) | useAppStore.ts:330,568 |
| themeBlur | 20 | Backdrop blur (0-60) | useAppStore.ts:331,569 |
AI Visual (glow) effects
| Key | Default | What it does | Source |
|---|---|---|---|
| aiVisual.enabled | true | Master switch for AI visual effects | sidebar/types.ts:65 |
| aiVisual.glowMode | 'subtle' | off | subtle | dynamic | sidebar/types.ts:66 |
| aiVisual.color | '#38bdf8' | Glow color | sidebar/types.ts:67 |
| aiVisual.intensity | 0.5 | Glow strength | sidebar/types.ts:68 |
| aiVisual.animationSpeed | 1 | Animation speed multiplier | sidebar/types.ts:69 |
Browsing & Native UI
| Key | Default | What it does | Source |
|---|---|---|---|
| enableAdblocker | false | Built-in ads + tracker blocker | useAppStore.ts:312,545 |
| selectedEngine | 'google' | Default search engine | useAppStore.ts:261,527 |
| selectedLanguage | 'en' | UI / content language | useAppStore.ts:296,504 |
| macNativeSidebarMode | 'electron' | electron | swiftui (native Swift sidebar) | useAppStore.ts:222,485 |
| macNativeActionChainMode | 'electron' | electron | swiftui (native action chain) | useAppStore.ts:223,486 |
| macNativeUtilityPanelMode | 'electron' | electron | swiftui (native utility panel) | useAppStore.ts:224,487 |
| macNativePermissionMode | 'electron' | electron | swiftui (native permission UI) | useAppStore.ts:225,488 |
Sidebar widgets
| Key | Default | What it does | Source |
|---|---|---|---|
| enabledWidgets | all 7 | current-context, ai-suggestions, workspace-intelligence, session-resume, automation-monitor, memory-insights, ai-timeline | sidebar/types.ts:46-62 |
| collapsedWidgets | memory-insights, ai-timeline | Widgets collapsed by default | sidebar/types.ts:59 |
| sidebarMode | 'full' | full | compact | hidden | sidebar/types.ts:61 |
Performance & Misc
| Key | Default | What it does | Source |
|---|---|---|---|
| performanceMode | 'normal' | normal | performance | useAppStore.ts:49,574 |
| performanceModeSettings | {5 tabs, 2048MB, audio} | maxActiveTabs / maxRam / keepAudioTabsActive | useAppStore.ts:50-54,575-579 |
| enableAmbientMusic | false | Background ambient music | useAppStore.ts:252,466 |
| backendStrategy | 'firebase' | firebase | mysql | useAppStore.ts:284,540 |
| isGuestMode | false | Guest mode (no account) | useAppStore.ts:95,412 |
Security Model
Aartiq uses a six-layer defense-in-depth model: visual sandbox, syntactic firewall, human-in-the-loop, directory allowlist, OS-level sandboxing, and capability-scoped execution. The HITL layer (permission gating, QR + PIN, biometric, single-use tickets, fail-closed) is documented in detail on the Security page.
Visual Sandbox
src/lib/Security.tsSyntactic Firewall
src/lib/SecurityValidator.jsHuman-in-the-Loop
src/core/command-validator.jsDirectory Allowlist
src/core/directory-allowlist.jsOS Sandbox (fail-closed)
src/core/sandbox-executor.jsCapability Scope
src/core/capability-controller.jsSources are in the code
Every claim on this page links to a file and line in the Aartiq browser repository. Read it yourself.
Download Aartiq