---
title: AutoHotkey integration (edit, reload, index .ahk scripts)
---

# AutoHotkey integration (edit, reload, index .ahk scripts)

## What it is

Omniscio's AutoHotkey integration lets you edit your `.ahk` script files directly inside Omniscio with a full Monaco editor (same as VS Code), auto-reload AHK on every save, and generate AI-powered navigation documents that map your entire script. Unlike most Omniscio projects, the AHK project is **folder-backed** — it's a real Windows folder you pick once, and Omniscio treats it like a regular project in the sidebar (so agents can also read/edit the files via normal tools). The integration solves the classic AHK pain points: editing in Notepad or SciTE (no autocomplete), manually reloading after each save (lose state), and getting lost in a 3000-line script with no outline. All three are fixed here.

## Where to find it

### How to use it

1. **Enable + pick your script.** Open Settings → **AutoHotkey**. Flip **Enable AutoHotKey Integration**. Click **Browse** next to "AHK file" and pick your main script. If the AutoHotkey executable is installed in a standard path, Omniscio auto-detects it (checks the registry App Paths, InstallDir, `C:\Program Files\AutoHotkey`, and PATH) — otherwise point it at `AutoHotkey.exe` manually.
2. **Edit in the linked project.** Open the AHK project from the sidebar (it's named after your file) → click any `.ahk` file → the Monaco editor opens with AutoHotkey syntax highlighting, autocomplete, and a minimap. Font size (14–32 px), word wrap, and minimap visibility are all settable — and they stay on at every file size; the editor is never feature-stripped. **Memory while you're elsewhere:** a huge script's editor model can hold hundreds of MB, and the editor stays mounted for the whole session, so after you've been off the AHK tab for a couple of minutes (with nothing unsaved) Omniscio quietly unloads the editor to free that memory, then reloads it the instant you come back (about half a second). Your unsaved edits always keep it loaded. **Press Ctrl+W (or E when you're not typing in the editor) to close the editor and go right back to wherever you were before you opened it** — it's the standard archive/close key, and on the AHK editor surface it returns you to your previous spot (falling back to the main inbox only if there's nowhere to return to) instead of doing nothing.
3. **Save and watch it reload.** Hit Save (Ctrl+S). Omniscio writes a `reload` signal file that a small `SetTimer` loop in your AHK script polls for (every ~1000 ms) — on finding it, your script calls `Reload` and deletes it. Omniscio writes the signal to **two** places so a script watching **either** reloads: your per-user temp folder (`%A_Temp%\ahk-reload.signal`, the secure default — use this in new scripts) **and**, for backward compatibility, the legacy shared `C:\tmp\ahk-reload.signal` that older scripts still poll. (On a shared multi-user PC, set `AMC_AHK_RELOAD_NO_LEGACY_CTMP=1` to suppress the legacy `C:\tmp` write.) It works via a signal file — not a direct message — because Windows UIPI blocks Omniscio from sending reload messages to an elevated AHK process, but either side can read/write a file.
4. **Generate the AI script index.** In the linked project, click **Generate Script Index**. Omniscio runs a two-stage pipeline: bash-extract every function/hotkey/class into a compact structure, then ask Claude to produce three markdown documents — a structure index, a hotkey reference, and a list of still-available key combinations you haven't claimed yet. The three files land in the script's directory and sit in the sidebar as regular project docs.
5. **Reload-on-save is optional.** Flip **ahkReloadOnSave** off if you'd rather trigger reloads manually. You can still generate the index without reload-on-save.

## How it behaves

### How it works

The in-core `ahk*` settings (`ahkEnabled`, `ahkFilePath`, `ahkExePath`, `ahkFontSize`, `ahkWordWrap`, `ahkMinimap`, `ahkReloadOnSave`) were retired along with the in-core feature — the bundled AutoHotkey plugin owns its own settings now, so there is nothing to turn on in Settings for them. Note that AHK is **not** a virtual project constant like Gmail or SMS; it's a real project row that happens to point at the folder you picked. Reload is handled by /src/main/services/ahk/ahk-reload-service.ts, which also implements the AHK executable auto-detection. File changes are watched with 200ms debounce by /src/main/services/ahk/ahk-watcher.ts. The two-stage index pipeline runs in /src/main/services/ahk/ahk-extraction-service.ts: stage 1 spawns `resources/ahk-extract.sh` with a 60-second timeout (falling back to Git-for-Windows bash if `/usr/bin/bash` isn't found); stage 2 pipes the extracted structure through three separate Claude API calls and writes the markdown to the script directory. IPC surface is 6 invokes + 2 push events (`AHK_PICK_FILE`, `AHK_DETECT_EXE`, `AHK_READ_FILE`, `AHK_SAVE_FILE`, `AHK_GENERATE_INDEX`, `AHK_READ_INDEX_FILE`; `AHK_FILE_CHANGED`, `AHK_INDEX_PROGRESS`) registered by /src/main/ipc/ahk-handlers.ts. The Monaco wrapper is /src/renderer/src/features/ahk/AhkEditor.tsx. Landing page: [/docs/intro-sandbox/autohotkey.html](../intro-sandbox/autohotkey.html).

**Editor memory release (hidden-tab).** The editor is **permanently mounted** (never unmounts on tab switch, only `display`-toggles — see the AHK focus-chain postmortem), so whatever Monaco model it holds stays resident for the whole app run. The user's real script is ~6.3 MB / ~254K lines; a live heap snapshot showed its model holds ~250K `ModelLineProjection` objects + ~300 MB of arrays, so leaving it resident dominated the renderer heap and stretched routine GCs into multi-second freezes under memory pressure. The fix keeps **every editor feature** (an earlier attempt that disabled minimap/word-wrap/folding/bracket-colorization for big files was rejected — it degrades the editor the user actually works in). Instead `AhkEditor.tsx` UNMOUNTS the `<Editor>` (disposing its model) once the tab has been hidden for `AHK_EDITOR_RELEASE_DELAY_MS` (120 s) with no unsaved edits — `shouldRenderEditor = isVisible || isDirty || !editorReleased` — then re-mounts + re-seeds from `store.content` (`defaultValue`) on return. Never released while dirty (Monaco owns the live buffer — I1). `editorReleased` starts `false` so Monaco still pre-mounts on app start (instant-first-open fast path preserved). Test-locked + full rationale: [ahk-plugin-contract.md](/.claude/memory/contracts/ahk-plugin-contract.md) invariant I8.

**AutoHotkey Manager (in development).** Alongside the raw editor there is a no-code **Manager** (gated behind Settings → Features → AutoHotkey Manager while in development): structured hotstrings / hotkeys / snippets stored in the app's database and compiled into ONE Omniscio-owned .ahk file you #Include from your master script. It supports tagging + tag filtering, search, view sorting, one-click starter presets (a dynamic `fff` → today's date, `@@` → your email, current time, date+time — the date/time ones expand at typing time via `{date}`/`{time}`/`{datetime}` placeholders), and an import wizard that scans an existing .ahk script and brings its one-line hotstrings over in bulk (with duplicate detection and a batch tag). **Tagging is unlimited and infinitely nestable**: an entry can carry any number of tags, and a tag with `/` (like `work/email/signatures`) becomes a nested path rendered as a collapsible tree with per-node counts — clicking a node filters to everything tagged at or under it. Multi-select checkboxes give bulk Tag…/Untag… over the selection, and each tree node's ⋯ menu offers prefix-aware "Rename everywhere" and "Delete everywhere" (renaming `work` also renames `work/email`; deleting removes nested tags too, entries stay). Tags never appear in the generated .ahk file — tag edits don't even trigger a rewrite. Current truth + invariants: [ahk-plugin-contract.md](/.claude/memory/contracts/ahk-plugin-contract.md).

**AI text correction (in the Manager).** A **gear (settings) button** in the Manager's header opens the **AI text correction** settings in a small popover (the gear shows a warning dot if one of the combos clashes with a hotkey in your own script). Turn it on and Omniscio writes two hotkeys straight into the managed .ahk: a **proofread** key (default `Ctrl+Alt+W`) that fixes the spelling and grammar of your current selection, and a **shorthand** key (default `Ctrl+Alt+E`) that turns a misspelling or abbreviation into the intended word (e.g. `sihped` → `shipped`, `apscript` → `Apps Script`). Press the key to **review** the fix in a small box before it pastes, or hold **Shift** with it to **auto-paste** without reviewing. Both combos are configurable (a bad combo is rejected in the UI and can never break your other hotstrings). Unlike a hand-rolled AutoHotkey script that calls a provider directly with a hardcoded key, the correction runs through Omniscio's **managed AI** — no API key lives in your script, and it inherits Omniscio's retries, provider fallback, cost tracking, and daily spend cap. The hotkey block reads your local control-server token from `~/.amc/cli-token` at run time (never baked into the file) and calls `POST /ahk/correct-text`; if Omniscio is offline or the correction fails, it pastes your **original text unchanged** so auto-paste can never drop an error into your document. Requires the AutoHotkey Manager feature to be on. Current truth + invariants: [ahk-text-correction-contract.md](/.claude/memory/contracts/ahk-text-correction-contract.md).

**Add a hotstring from anywhere — Quick Launch → AI Text Correction.** Press your AI Text Correction hotkey (Ctrl+Alt+W or Ctrl+Alt+H by default) with a word selected. Omniscio proofreads it, and the panel now carries an **Add as hotstring** button (Alt+S): what you typed becomes the trigger, the corrected text becomes the expansion, and three toggles set the AutoHotkey hotstring options: **Expand immediately** (`*` — fire the moment you finish typing the shorthand, without waiting for a space, ON by default), **Inside words** (`?` — fire even when the trigger is typed inside a longer word) and **Match case** (`C` — only fire when you type it with exactly this capitalization). The last two are OFF by default, which is what the generated file emits for an unset option. Saving writes the entry into the AutoHotkey plugin's own store, regenerates your managed `.ahk` file, and drops a reload signal so the new shorthand works right away — you never have to open the AutoHotkey panel for it. If the trigger already exists it is UPDATED rather than added twice (a duplicate `::x::` would never fire). When something stops it — the plugin is off, no AutoHotkey folder has been chosen yet, or the file is locked — the panel says so, and it distinguishes “saved, but the file could not be rewritten” from “nothing happened”, so you are never pushed into adding the same hotstring twice. This restores the capture→correct→save flow that the old in-Manager quick-add popup provided before the in-core AutoHotkey feature moved into the plugin. Current truth + invariants: [ahk-plugin-contract.md](/.claude/memory/contracts/ahk-plugin-contract.md)
`core-quick-adds-only-through-the-plugins-rpcs`, `core-performs-the-write-and-the-reload-signal`,
`an-existing-trigger-is-updated-not-duplicated`.

**Plugin port (in progress).** The Manager AND the raw code editor are being ported to a first-class marketplace **plugin** at [/src/plugins/autohotkey/](/src/plugins/autohotkey/), built on the plugin webview→backend RPC. **Slice 1 (Foundation MVP)**, **Slice 2 (UI parity)**, **Slice 2b (the raw Monaco editor)**, and **Slice 3's backend (AI correction + indexing)** have shipped as a **disabled-by-default builtin**: a v2 worker backend owns the entry CRUD, the `.ahk` serialization, and the tag / import / preset operations over `ctx.rpc` (reusing the same shared pure AHK logic as the in-tree Manager, no re-roll), entries live in the plugin's own storage, and a webview manager writes the generated file via `AgentMC.fs` (the sandboxed worker can't reach the user's folder, so file I/O is webview-side). Slice 2 brings the webview close to the in-tree Manager: the nested tag tree with filtering + prefix-aware rename/delete-everywhere, multi-select bulk tagging, the import wizard (scan → dedupe → batch import), one-click presets, and a live collision warning that flags managed hotkeys clashing with your own script. **Slice 2b** folds in the same Monaco code editor as above: because Monaco has to be bundled, the plugin webview migrated from hand-written vanilla JS to a **bundled React/Vite** build (source in `webview/`, committed output in `ui/`), preserving every Manager feature and adding a folder-backed raw `.ahk` editor with the identical uncontrolled-buffer typing model and the big-script memory release. Reload-on-save is sandbox-safe: the webview drops a signal file next to your script (in a folder you grant) and gives you a one-time v1/v2 poll snippet — no shared temp folder needed. **Slice 3** then ships the AI text-correction block + the 3-document AI indexing (`ai.generateIndex`) in the plugin **backend** — the bash script-scanner rewritten in pure TypeScript (bash is denylisted for plugins), reusing the shared correction/prompt logic (no re-roll), with the shared `/ahk/correct-text` route widened so plugin-only users reach correction (sign-in / rate-limit / spend-cap unchanged); its on-screen AI-correction settings + "Generate Index" button are **deferred** to mount on the 2b webview's `app-ai-slot`. Slice 4 then retires the in-tree manager + core raw editor. Current truth + invariants: [ahk-plugin-contract.md](/.claude/memory/contracts/ahk-plugin-contract.md).

## Related

- [cli-control.md](cli-control.md) — pair AHK with CLI Control to bind hotkeys that launch Omniscio sessions
- [deep-links.md](deep-links.md) — `omniscio://` URLs are easy to open from an AHK hotkey
