Leads with a 3-step beginner path: install the plugin from Obsidian's
Community plugins browser, install one AI coding CLI (Claude Code, Codex,
opencode, Ollama) with copy-paste installers and official links, then open
the panel. Reframes "Install in a Vault" so the community browser is the
primary path. Docs only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The node-pty -> python bridge -> pipe fallback chain is normal operation
when the optional native node-pty module isn't installed, but its
[proxy-warn]/[proxy-info] lines (plus node-pty's multi-line "Require stack")
cluttered the terminal on every launch. Route those diagnostics through a
verbosity-gated logger in pty-proxy.js: info/warn are silent by default,
while error/fatal are always shown so real failures aren't hidden. Add a
"Verbose proxy logs" toggle (Advanced settings, off by default) that passes
a verbose flag through the proxy payload to restore full diagnostics.
Bump to 0.2.15.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the hard-coded ACTIVITY_IDLE_MS constant with a new "Idle timeout
(seconds)" setting (idleTimeoutSeconds, default 10) in the Automations
section. It controls when a session counts as finished — the gray tab dot
and the idle auto-close. Bump to 0.2.14.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The idle auto-close (and gray dot) fired too quickly on automation tabs.
Bump ACTIVITY_IDLE_MS to 10s so a session is only "finished" after the CLI
has been quiet for ~10s, reducing premature closes during task pauses.
Bump to 0.2.13.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The session tab status dot now reflects live CLI activity rather than just
whether the process is alive: green = a manual session's AI is working,
purple = an automation session's AI is working, gray = the CLI is idle
(finished its turn) or stopped. CliSession tracks activity continuously —
output flowing = working, quiet for ~5s = idle — and notifies the view via
onActivityChange to repaint the dot.
Add a new opt-in setting "Auto-close automation sessions when idle": closes
an automation tab once its CLI goes quiet after the prompt ran, even if the
process stays interactive (Claude/Codex). It complements the existing
on-exit close (renamed "...on exit"); both are kept. Idle-close is armed only
after the prompt is sent and driven by real CLI output, so boot and slow
first responses don't close the tab early.
Extract the pure tabDotClass helper to session-utils.ts with tests. Update
README. Bump to 0.2.11.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Refactor the sidebar panel from a single-process view into a tabbed
multi-session view: each tab is an independent CliSession with its own
PTY process and xterm terminal. A New session / + control opens a session
from any configured runtime; multiple sessions of the same runtime are
allowed and labels are disambiguated. Stop/Restart/Clear and the @file/
@folder buttons act on the active tab; a single ResizeObserver refits only
the visible terminal and re-fits on tab activation.
Automations now spawn their own session tab for the declared runtime (or
the default when none is declared), await CLI readiness, then send the
prompt — replacing the old skip-if-not-running/runtime-mismatch logic.
Add settings autoCloseAutomationSessions and maxConcurrentSessions; the
Automations modal "Run now" button is always enabled.
Extract pure helpers to session-utils.ts (resolveRuntimeForAutomation,
runtimeMatches, nextSessionLabel, canOpenSession) with unit tests. Update
README and the generated example automation. Bump to 0.2.9 (manifest,
versions.json, package.json, prompt-hub version).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The opening description covered runtimes and mentions but not the
Automations feature; add a sentence on scheduled/manual prompt files with
exportable per-run history. Docs only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Generates a documented hello-world.md (every frontmatter field explained
with inline comments, plus a simple "say hello and tell me the time"
prompt) into the configured automations folder. Creates the folder if it
doesn't exist, avoids clobbering an existing file by suffixing the name,
reloads the automation cache, and opens the new file. Shows a clear notice
when no automations folder is configured.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PTY-attached raw-mode TUIs (Claude, Codex, any TUI that reads keypresses
directly) only recognize \r as the Enter key — \n just sits in the input
buffer. Cooked-mode shells also accept \r because the tty line discipline
translates it, so \r is the safe universal Enter for any PTY child.
The prompt body was being typed correctly but the run never fired because
the Enter never registered. Swap the suffix from \n to \r.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A new "Automations" affordance reads markdown files from a configurable
vault folder, parses a frontmatter schedule (`interval` minutes or 5-field
`cron`) plus optional `enabled`/`runtime`/`appendNewline`/`name`, and fires
the file body into the running CLI on schedule or manually from a modal.
Each fire (or skip / error) is logged to a ring-buffer history capped at
200 entries; the modal exposes the entries with status, last/next run, a
per-row Run now button, and a History tab with Clear / Export-as-markdown.
The scheduler runs at the plugin level (`activeWindow.setInterval`, 30 s
tick) and stays alive whether the panel is open or not. The folder cache
live-updates on vault create/modify/delete/rename. Runs skip cleanly when
no CLI is running — the plugin never auto-starts a runtime.
Implementation: pure logic in automation.ts (28 vitest cases), wiring in
main.ts, AutomationsModal in automations-modal.ts. Adds `cron-parser`
(runtime) and `yaml` (dev).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Since 0.1.46, main.js embeds pty-proxy.js and pty-bridge.py via esbuild
define and writes them next to the plugin on first Start. That makes
the zip-side copies redundant: the staging step previously bundled 8
files (`manifest.json`, `main.js`, `styles.css`, `versions.json`,
`pty-proxy.js`, `pty-bridge.py`, `package.json`, `package-lock.json`),
but only the three official ones actually need to end up in the plugin
folder for the panel to start.
Trim:
- Zip now contains only `manifest.json`, `main.js`, `styles.css` —
the canonical Obsidian plugin folder layout.
- Standalone release assets keep the four files Obsidian's plugin
update protocol and BRAT actually fetch: `manifest.json`, `main.js`,
`styles.css`, `versions.json`.
- `versions.json` is no longer inside the zip — Obsidian fetches it
directly from the release URL, not from the plugin folder.
- `package.json` / `package-lock.json` are no longer shipped at all
(advanced users can download them from the repo for the matching
tag if they want to opt into the native node-pty backend).
Reworked the release notes body to lead with the community-store
install path and document the embedded-source bootstrap. Aligned the
README `Release` and `Required files` sections with the new layout.
Bumped manifest/version metadata to 0.1.47.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Obsidian's community-store auto-install only downloads main.js,
manifest.json, and styles.css. This plugin also needs pty-proxy.js
(spawned as a child process) and pty-bridge.py (Python PTY fallback)
alongside main.js, so community-store installs broke immediately on
Start with `Missing proxy script: ...`.
Fix:
- esbuild.config.mjs now reads pty-proxy.js and pty-bridge.py at build
time and injects their full content as build-time JS string constants
PTY_PROXY_SOURCE / PTY_BRIDGE_SOURCE via the `define` substitution.
- main.ts declares the two constants and adds ensureProxyFiles(dir),
which writes both files into the plugin folder only when they're
missing or their content drifted from the embedded copy. The helper
is called from spawnPtyProxy before the existence check, so the very
first Start auto-bootstraps the proxy without any zip-side files.
- README `Required files` reworked to reflect that main.js now carries
the auxiliary sources; pty-proxy.js / pty-bridge.py move to an
`auto-generated on first run` tier.
Verified the bundled main.js contains the embedded markers from both
files (spawnPythonBridge from proxy, decode_payload / TIOCSWINSZ /
pty.fork from bridge). Build size grows by ~22 KB.
Bumped manifest/version metadata to 0.1.46.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After auditing each file, classified them by whether the plugin can
start without them:
- Required (panel will not start): manifest.json, main.js, pty-proxy.js
- Recommended (panel loads but degraded): styles.css, pty-bridge.py
- Optional (only inside zip): versions.json (backwards-compat install
matching only, not runtime), package.json + package-lock.json
(only needed for the optional `npm install --omit=dev` native
node-pty backend)
The release workflow now attaches only the five Required + Recommended
files as standalone assets next to the zip. The other three remain
bundled in the zip so users opting into native node-pty still get them
in one shot, but they don't clutter the release page as if they were
load-bearing.
Reworked the release notes body and the README `Required files`
section to lead with this Required/Recommended/Optional split instead
of presenting every file as "indispensable".
Bumped manifest/version metadata to 0.1.44.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The plugin's panel spawns a child process and needs more than the
typical Obsidian main.js / manifest.json / styles.css triple — the
Node proxy (pty-proxy.js) and the Python PTY fallback (pty-bridge.py)
must also be present in the plugin folder, plus versions.json (for
backwards-compatible install matching) and package.json /
package-lock.json (for the optional native node-pty backend).
The release workflow already bundled all of these inside the zip but
only attached the standard triple as standalone files. Switch to
uploading every runtime-required file at the release root so users
who fix one corrupt file or pin a specific component (e.g. swapping
in a custom pty-proxy.js for debugging) can grab it directly without
re-downloading the whole zip.
Reworked the release notes body template to spell out what each file
is for and to flag that the three-file triple is NOT sufficient for
this plugin (BRAT / Obsidian auto-update only fetches those three,
which is why the bundled zip stays the recommended install path).
Mirrored the same explanation in the README `Required files` section.
Bumped manifest/version metadata to 0.1.43.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The README still presented the plugin as a Claude-Code-only sidebar
even though the plugin now ships a customizable runtime list, two
mention buttons, and a sidebar dropdown. Updated to reflect what the
plugin actually does:
- Renamed the README title from "Obsidian Any AI Code" to "Any AI CLI"
so it matches the manifest plugin name. Updated the banner alt and
the Community Plugins enable path accordingly.
- Replaced the intro with a single paragraph that covers the multi-
runtime model (declarative list of name + launch command, sidebar
dropdown to switch, active file/folder mention buttons, vault folder
as cwd) instead of pitching Claude Code as the only runtime.
- Reworked the Features list to lead with the customizable runtime
list, mention buttons, process controls, and the four-tier PTY
fallback chain.
- Updated Requirements: Obsidian 1.7.2+ (matches manifest minAppVersion)
and "any AI coding CLI on PATH" instead of mandating Claude Code.
- Rewrote the Usage section as a numbered walkthrough of the new
toolbar layout (runtime dropdown, then Start/Stop/Restart/Clear,
then @active file / @active folder on row two) and the correct
command palette name ("Open panel").
- Reorganized Plugin Settings into General / Runtimes / Advanced
groups matching the actual settings tab; removed the dedicated
"Switching runtime from the sidebar" subsection (now folded into
Usage).
- Generalized the `command not found: claude` troubleshooting entry
so it covers any configured CLI.
Validated locally: lint, build, tsc and the 27 vitest cases still
pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Install the official Obsidian ESLint plugin (with eslint v9 and
@typescript-eslint/parser) and add an eslint.config.mjs flat config
that wires the recommended ruleset to TS files only, with a small
override turning off hardcoded-config-path for the tests directory
(those literal `.obsidian` strings are unit-test fixtures, not real
Obsidian configuration usage). Add an `npm run lint` script and call
it from the CI workflow before tests so guideline violations surface
on every push and PR.
Resolved every reported violation:
- UI text sentence case: button labels @Active file/@Active folder ->
@active file/@active folder; "(no runtime configured)" placeholder
capitalised; ribbon tooltip "Open Any AI CLI" -> "Open AI CLI panel";
command-list placeholders, descriptions, and the runtimes-section
empty state reworded to drop ambiguous mid-sentence acronyms (PTY,
CLIs, Node) and quoted button names.
- commands/no-plugin-name-in-command-name: command palette name
"Open Any AI CLI" -> "Open panel" (Obsidian shows the plugin name
next to the command, repeating it is redundant).
- prefer-active-doc on globalThis: replace the inline crypto fallback
in runtime-utils.ts with `import { randomUUID } from "node:crypto"`.
- no-unsupported-api on Workspace.revealLeaf: bump manifest.json
minAppVersion to 1.7.2 (the version that introduced revealLeaf) and
await the call. versions.json maps 0.1.38 -> 1.7.2 while older
entries stay at 1.5.0 so existing downloads keep resolving.
Lint, build, tsc and the 27 vitest cases are all clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Obsidian submission bot rejected obsidian-any-ai-cli because the
guideline asks plugins not to include "obsidian" in their id (the id
becomes the plugin folder name; brevity helps sorting). Verified
any-ai-cli is free in the public community-plugins.json, then renamed
the id everywhere it surfaces:
- manifest.json (id) and bumped to 0.1.36
- versions.json (added 0.1.36 entry)
- package.json (npm name) and package-lock.json (re-synced)
- .github/workflows/release.yml (PLUGIN_ID env var → release zip name)
- README.md install paths and zip filename references
Existing personal installs must rename their plugin folder to
.obsidian/plugins/any-ai-cli before this version.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The plugin was rebranded to "Any AI CLI" earlier in this branch, but
the manifest id remained obsidian-any-ai-code from the original name.
Aligning the id ahead of the community-store submission so the
community-plugins.json entry, the manifest id, the plugin folder name
and the release zip filename all match.
Updated:
- manifest.json id and version
- versions.json (added 0.1.35)
- package.json name and version
- package-lock.json (re-synced)
- .github/workflows/release.yml PLUGIN_ID env var
- README.md install paths and release-zip filename references
GitHub repo URLs (blamouche/obsidian-any-ai-code) are intentionally
unchanged — the repo itself is not being renamed at this time.
Existing local installs must rename their plugin folder from
.obsidian/plugins/obsidian-any-ai-code to .obsidian/plugins/obsidian-any-ai-cli
to keep the plugin discoverable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The new sidebar button sits next to @Active file on the secondary
toolbar row and inserts the parent folder of the currently active note
(vault-relative path with trailing slash) into the running CLI's stdin.
Files at the vault root fall back to inserting @./ so the action still
maps to the working directory the runtime was launched in.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Settings now expose a list of CLI runtimes (each with a display name and
launch command) instead of two hardcoded entries. Users can add as many
runtimes as they want from the settings panel, remove unused ones (the
list always keeps at least one entry), and pick the default runtime
through a dropdown listing every configured entry.
The sidebar toolbar replaces the previous Claude/Codex toggle buttons
with a dropdown populated from the same configured list, so switching
runtime is a single action and reflects user-added entries.
A migration helper converts legacy `command`, `codexCommand`, and
`runtime` settings into the new `runtimes` + `selectedRuntimeId` shape
on first load, and the Codex-specific terminal workarounds (no-color
env, terminal reset) are now triggered by `isCodexLikeCommand` so they
keep working regardless of the entry id.
Adds vitest coverage for the migration and codex-like command helpers.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The banner sits under the title and is stored in a dedicated img/
folder so future visual assets have a consistent home.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Now that node-pty is optional in the proxy, unzipping the release into
.obsidian/plugins/ and enabling the plugin is enough — no shell command
required. README's install section is reorganized around the release zip
flow with `npm install --omit=dev` demoted to an optional native-PTY
upgrade. The release workflow body template mirrors the same wording.
Also adds a README `Release` section describing the tag-driven workflow,
and updates the troubleshooting note for `Cannot find module 'node-pty'`.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>