@nanocollective/nanocoder
Version:
A local-first CLI coding agent that brings the power of agentic coding tools like Claude Code and Gemini CLI to local models or controlled APIs like OpenRouter
144 lines (141 loc) • 5.59 kB
JavaScript
import { jsx as _jsx } from "react/jsx-runtime";
import { render } from 'ink';
import { createRequire } from 'module';
import App from './app/index.js';
import { parseContextLimit } from './app/utils/handlers/context-max-handler.js';
import { setSessionContextLimit } from './models/index.js';
const require = createRequire(import.meta.url);
const { version } = require('../package.json');
// Parse CLI arguments
const args = process.argv.slice(2);
// Handle --version/-v flag
if (args.includes('--version') || args.includes('-v')) {
console.log(version);
process.exit(0);
}
// Handle --help/-h flag
if (args.includes('--help') || args.includes('-h')) {
console.log(`
Usage: nanocoder [options] [command]
Commands:
copilot login [provider-name] Log in to GitHub Copilot (device flow). Saves credentials for the "GitHub Copilot" provider.
Options:
-v, --version Show version number
-h, --help Show help
--vscode Run in VS Code mode
--vscode-port Specify VS Code port
--provider Specify AI provider (must be configured in agents.config.json)
--model Specify AI model (must be available for the provider)
--context-max Set maximum context length in tokens (supports k/K suffix, e.g. 128k)
run Run in non-interactive mode
Examples:
nanocoder --provider openrouter --model google/gemini-3.1-flash run "analyze src/app.ts"
nanocoder --provider ollama --model llama3.1 --context-max 128k
nanocoder run --provider openrouter "refactor database module"
`);
process.exit(0);
}
const vscodeMode = args.includes('--vscode');
// Extract VS Code port if specified
let vscodePort;
const portArgIndex = args.findIndex(arg => arg === '--vscode-port');
if (portArgIndex !== -1 && args[portArgIndex + 1]) {
const port = parseInt(args[portArgIndex + 1], 10);
if (!isNaN(port) && port > 0 && port < 65536) {
vscodePort = port;
}
}
// Extract --provider if specified
let cliProvider;
const providerArgIndex = args.findIndex(arg => arg === '--provider');
if (providerArgIndex !== -1 && args[providerArgIndex + 1]) {
cliProvider = args[providerArgIndex + 1];
}
// Extract --model if specified
let cliModel;
const modelArgIndex = args.findIndex(arg => arg === '--model');
if (modelArgIndex !== -1 && args[modelArgIndex + 1]) {
cliModel = args[modelArgIndex + 1];
}
// Extract --context-max if specified
const contextMaxArgIndex = args.findIndex(arg => arg === '--context-max');
if (contextMaxArgIndex !== -1 && args[contextMaxArgIndex + 1]) {
const limit = parseContextLimit(args[contextMaxArgIndex + 1]);
if (limit !== null) {
setSessionContextLimit(limit);
}
else {
console.error(`Invalid --context-max value: "${args[contextMaxArgIndex + 1]}". Use a positive number, e.g. 8192 or 128k`);
process.exit(1);
}
}
// Check for non-interactive mode (run command)
let nonInteractivePrompt;
const runCommandIndex = args.findIndex(arg => arg === 'run');
const afterRunArgs = runCommandIndex !== -1 ? args.slice(runCommandIndex + 1) : [];
if (runCommandIndex !== -1 && args[runCommandIndex + 1]) {
// Filter out known flags after 'run' when constructing the prompt
const promptArgs = [];
for (let i = 0; i < afterRunArgs.length; i++) {
const arg = afterRunArgs[i];
if (arg === '--vscode') {
continue; // skip this flag
}
else if (arg === '--vscode-port') {
i++; // skip this flag and its value
continue;
}
else if (arg === '--provider') {
i++; // skip this flag and its value
continue;
}
else if (arg === '--model') {
i++; // skip this flag and its value
continue;
}
else if (arg === '--context-max') {
i++; // skip this flag and its value
continue;
}
else {
promptArgs.push(arg);
}
}
nonInteractivePrompt = promptArgs.join(' ');
}
const nonInteractiveMode = runCommandIndex !== -1;
// Handle copilot login from CLI (no App)
if (args[0] === 'copilot' && args[1] === 'login') {
const providerName = args[2]?.trim() || 'GitHub Copilot';
(async () => {
try {
const { runCopilotLoginFlow } = await import('./auth/github-copilot.js');
console.log('Starting GitHub Copilot login...');
await runCopilotLoginFlow(providerName, {
onShowCode(verificationUri, userCode) {
console.log('');
console.log(' 1. Open this URL in your browser:');
console.log('');
console.log(' ' + verificationUri);
console.log('');
console.log(' 2. Enter this code when prompted:');
console.log('');
console.log(' ' + userCode);
console.log('');
console.log('Waiting for you to complete login...');
},
});
console.log('\nLogged in. Credential saved for "' + providerName + '".');
process.exit(0);
}
catch (err) {
console.error(err instanceof Error ? err.message : err);
process.exit(1);
}
})();
}
else {
render(_jsx(App, { vscodeMode: vscodeMode, vscodePort: vscodePort, nonInteractivePrompt: nonInteractivePrompt, nonInteractiveMode: nonInteractiveMode, cliProvider: cliProvider, cliModel: cliModel }));
}
//# sourceMappingURL=cli.js.map