Node.js wrapper for the Aider tool using a self-contained Python environment via uv.
This package allows you to easily integrate Aider's AI coding capabilities into your Node.js projects without needing to manage Python environments or dependencies manually.
- Provides a simple
runAider(options)
function. - Automatically downloads the
uv
binary during installation. - Creates an isolated Python virtual environment using
uv
. - Installs
aider-chat
within the isolated environment. - Handles communication with the Aider process.
npm install @dguttman/aider-js
The postinstall
script will automatically download the necessary uv
binary for your platform and set up the Python environment with aider-chat
.
API Keys:
-
Default Behavior: By default,
runAider
expects API keys (e.g.,OPENAI_API_KEY
,OPENROUTER_API_KEY
,ANTHROPIC_API_KEY
) to be set as environment variables in the Node.js process. These are automatically passed down to the underlying Aider Python process. -
Using
apiBase
: If you provide the optionalapiBase
option (for proxies or custom endpoints like OpenRouter), you have two choices for the API key:-
Set
OPENAI_API_KEY
Environment Variable: IfapiBase
is provided and theapiKey
option (see below) is not used, theOPENAI_API_KEY
environment variable must be set. Aider uses this specific environment variable whenapiBase
is involved, even for non-OpenAI models. -
Use
apiKey
Option: Alternatively, ifapiBase
is provided, you can also provide the optionalapiKey
string directly in therunAider
options. If you do this, the value of theapiKey
option will be used as theOPENAI_API_KEY
for the Python process for that specific call, overriding anyOPENAI_API_KEY
environment variable that might also be set.
-
Set
In summary: Use environment variables for keys by default. Only use the apiKey
option if you are also using apiBase
and you want to specify the key directly for that call instead of relying on the OPENAI_API_KEY
environment variable.
Example Environment Setup:
# Set API key(s) as environment variables
export OPENAI_API_KEY=sk-...
export OPENROUTER_API_KEY=sk-or-...
# Run your Node.js script
node your_script.js
Example runAider
Call:
const { runAider } = require('@dguttman/aider-js');
const path = require('path'); // For constructing paths
async function main() {
try {
// --- Options ---
// See descriptions below the example
const result = await runAider({
// --- Required ---
prompt: 'Refactor the main function in app.js based on the architecture doc.',
modelName: 'openai/gpt-4o-mini',
repoPath: path.resolve('../path/to/your/git/repository'),
// --- Files (Relative to repoPath) ---
editableFiles: ['src/app.js', 'src/utils.js'],
readOnlyFiles: ['docs/architecture.md'],
// --- Optional: Custom Endpoint ---
apiBase: 'https://openrouter.ai/api/v1',
apiKey: 'sk-or-xxxxxx', // Only needed if using apiBase AND overriding OPENAI_API_KEY env var.
// --- Optional: Behavior ---
autoCommits: false, // Default: false
showDiffs: false, // Default: false
stream: false, // Default: false (Note: Streaming currently not fully supported by Node wrapper)
chatLanguage: 'english', // Default: 'english'
verbose: false // Default: false
});
// Output from the aider process
console.log('Aider completed successfully.');
// Aider's stdout (contains diffs, chat messages, etc.)
console.log('Stdout:\n', result.stdout);
// Aider's stderr (contains informational logs, warnings, errors from Python)
console.log('Stderr:\n', result.stderr);
} catch (error) {
console.error('Error running Aider:', error);
// error.stderr and error.stdout might contain additional context
if (error.stderr) {
console.error('Stderr from failed run:\n', error.stderr);
}
}
}
main();
The runAider
function accepts an options object with the following properties:
-
prompt
(string, required): The natural language instruction for Aider. -
modelName
(string, required): The identifier for the LLM model Aider should use (e.g.,'openai/gpt-4o'
,'anthropic/claude-3-5-sonnet-20240620'
). -
repoPath
(string, required): An absolute or relative path to the root of the Git repository Aider should operate within. -
editableFiles
(array of strings, optional): A list of file paths (relative torepoPath
or absolute) that Aider is allowed to modify. Defaults to[]
. -
readOnlyFiles
(array of strings, optional): A list of file paths (relative torepoPath
or absolute) that Aider can read for context but cannot modify. Defaults to[]
. -
apiBase
(string, optional): The base URL for a custom LLM API endpoint (e.g., for using proxies, local LLMs, or services like OpenRouter). See API Key section above for crucial details. -
apiKey
(string, optional): The API key. This is primarily used whenapiBase
is also provided, allowing you to specify the key directly for the call, overriding theOPENAI_API_KEY
environment variable. See API Key section above. -
autoCommits
(boolean, optional): Iftrue
, Aider will automatically commit changes it makes. Defaults tofalse
. -
showDiffs
(boolean, optional): Iftrue
, Aider will include diffs of proposed changes in its output. Defaults tofalse
. -
stream
(boolean, optional): Iftrue
, instructs Aider to attempt streaming responses. Note: While the option is passed to Aider, the current Node.js wrapper implementation buffers the output, so you won't see true streaming behavior yet. Defaults tofalse
. -
chatLanguage
(string, optional): Specifies the language for Aider's chat interactions (e.g.,'spanish'
,'french'
). Defaults to'english'
. -
verbose
(boolean, optional): Iftrue
, enables more detailed logging output from the underlying Aider process (sent to stderr). Defaults tofalse
.
The function returns a Promise that resolves with an object containing stdout
and stderr
from the Aider process, or rejects with an error if the process fails.
-
Postinstall: Installs
uv
and Python dependencies (aider-chat
) into.venv/
. -
Execution (
runAider
):- Gathers options (
prompt
,modelName
,repoPath
,editableFiles
,readOnlyFiles
,apiBase
,apiKey
,autoCommits
,showDiffs
,stream
,chatLanguage
,verbose
). -
Validation:
- Checks
repoPath
exists and is a directory. - If
apiBase
is provided, ensures eitherapiKey
option orOPENAI_API_KEY
env var is present.
- Checks
-
Model Prefixing: Prepends
openai/
tomodelName
ifapiBase
is provided. -
Environment Setup: Prepares environment variables for the child process:
- Inherits all
process.env
. - If
apiBase
andapiKey
are both provided, setsOPENAI_API_KEY
in the child environment to the value of theapiKey
option.
- Inherits all
-
JSON Payload: Bundles options (including
repoPath
, excludingapiKey
itself) into a JSON string. -
Spawn: Executes
python/aider_entrypoint.py
using the Python in.venv/
, passing the JSON payload as an argument and the prepared environment variables. Crucially, it also sets thecwd
(current working directory) of the Python process to the providedrepoPath
.
- Gathers options (
-
Python Script (
aider_entrypoint.py
):- Parses the JSON configuration (it still receives
repoPath
in the JSON, though it's primarily used by Node for settingcwd
). - Initializes Aider
Coder
with model, files, etc. (does not explicitly passgit_dname
). - Aider implicitly detects the Git repository context from the process's current working directory, which was set to
repoPath
by Node.js. - Aider reads API keys from the environment variables provided by Node.js (using
OPENAI_API_KEY
ifapiBase
was involved). - Runs
coder.run(prompt)
. - Captures stdout/stderr back to Node.js.
- Parses the JSON configuration (it still receives
-
Cleanup:
npm run cleanup
(removes downloadeduv
and the.venv
directory) -
Running Tests:
npm test
-
Test Recording:
- Tests use
echoproxia
to record and replay HTTP interactions with the LLM API (e.g., OpenRouter). This allows tests to run without live API calls after the initial recording. - To create or update recordings, run the tests with the
RECORD_MODE
environment variable set totrue
and ensure your API key (e.g.,OPENROUTER_API_KEY
) is also set in the environment:export RECORD_MODE=true export OPENROUTER_API_KEY=sk-or-... # Replace with your actual key npm test
-
Important: When
RECORD_MODE
istrue
, the existing contents of thetest/__recordings__
directory will be deleted before new recordings are made for the current test run.
- Tests use
Contributions are welcome! Please open an issue or submit a pull request.