Private Repo Refactor & Test — Fully Local
An agentic coding workflow powered by GitHub Copilot SDK + Foundry Local.
Scans code, detects bugs, applies safe refactors, runs tests, and produces a PR-style summary —
all on-device, no cloud model required.
Getting Started • Web Dashboard • What Does It Do? • Architecture • Troubleshooting • Contributing
This is a working demo of an AI-powered coding agent that can:
- Read your repository files
- Find bugs and code smells
- Fix them automatically
- Run your tests to verify the fixes
- Write a PR-style summary of what it changed
The twist? Everything runs on your machine. No code is sent to the cloud. No API keys to OpenAI or Anthropic. Just your laptop, a local AI model, and two open-source SDKs wired together.
- Developers exploring agentic coding workflows
- Teams who need AI assistance but can't send code to external services
- Anyone curious about GitHub Copilot SDK and Foundry Local
| Technology | What it does |
|---|---|
| GitHub Copilot SDK | Provides the agent runtime — handles planning, tool invocation, streaming, and the orchestration loop |
| Foundry Local | Runs an AI model on your device — exposes an OpenAI-compatible API on a dynamic localhost port (auto-detected by the SDK) |
| BYOK (Bring Your Own Key) | A single config object that routes all SDK inference to Foundry Local instead of the cloud |
| Node.js + TypeScript | The application language — modern ESM, fully typed |
Before you start, make sure these three things are installed on your machine:
Download from nodejs.org. Pick the LTS version.
Verify it's installed:
node --version
# Should print v18.x.x or higherFoundry Local is Microsoft's tool for running AI models locally.
Windows:
winget install Microsoft.FoundryLocalmacOS:
brew install foundrylocalVerify it's installed:
foundry --version📖 Full install guide: Foundry Local — Get Started
The GitHub Copilot SDK communicates with the GitHub Copilot CLI in server mode.
Install it by following the GitHub Copilot CLI install guide.
Verify it's installed:
copilot --versionNote: You need a GitHub Copilot subscription (Individual, Business, or Enterprise) or you can use BYOK mode.
We provide setup scripts that install dependencies, start Foundry Local, and download the AI model for you.
Windows (PowerShell):
.\setup.ps1macOS / Linux:
chmod +x setup.sh
./setup.shWhen setup finishes, you'll see:
━━━ Setup complete! ━━━
You're ready to go. Run one of these commands:
npm run demo CLI agent (terminal output)
npm run ui Web dashboard (http://localhost:3000)
If you prefer to set things up yourself:
Step 1 — Install npm packages:
npm install
cd demo-repo && npm install --ignore-scripts && cd ..Step 2 — Start Foundry Local and download the model:
foundry service start
foundry model run qwen2.5-coder-1.5bThe first model download takes a few minutes. After that it runs from cache — no internet needed.
Step 3 — Copy the environment file:
cp .env.example .envStep 4 — Run the agent:
npm run demoFor convenience, you can also use the launcher scripts:
| Command | What it does |
|---|---|
start.cmd (Windows) / ./start.sh (macOS/Linux) |
Run the CLI demo |
start.cmd ui / ./start.sh ui |
Start the web dashboard |
start.cmd setup / ./start.sh setup |
Run the full setup |
A real-time web UI is included for a more visual experience.
npm run ui
# Open http://localhost:3000 in your browserThe dashboard shows:
- Phase progress sidebar — which phase is running, completed, or errored
- Live streaming output — model responses appear in real-time via WebSocket
- Tool call log — every tool invocation logged with phase context
- Phase timing table — how long each phase took
- Environment info — model, endpoint, and repo path at a glance
Browser (http://localhost:3000)
│
│ WebSocket (real-time events)
▼
Express server (src/server.ts)
│
│ runAgent() callback
▼
web-agent.ts → GitHub Copilot SDK → Foundry Local (on-device)
The agent runs a four-phase loop on a small demo repository (demo-repo/)
that contains an intentional bug and duplicated code.
| Phase | What the agent does | Tools used |
|---|---|---|
| 1. PLAN | Scans every source and test file. Identifies bugs, code smells, and duplication. Outputs a numbered fix plan. | list_files, read_file |
| 2. EDIT | Applies each fix by rewriting the affected files. Corrects the bug, removes duplication. | write_file |
| 3. VERIFY | Runs npm test and npm run lint. If tests fail, tries to fix and re-run. |
run_command |
| 4. SUMMARY | Produces a PR-style Markdown report: what changed, why, and what to do next. | (none — text generation) |
The demo-repo/ is a tiny banking utility library. It has two problems:
-
Calculation bug —
calculateInterest()inaccount.jsdivides instead of multiplies:// BUG: should be principal * (annualRate / 100) return principal / annualRate;
This causes 3 of 9 tests to fail.
-
Code duplication —
formatCurrency()is copy-pasted inaccount.jsandtransaction.js, even though a canonical version already exists inutils.js.
The agent finds both problems, fixes them, verifies all tests pass, and writes a summary.
┌─────────────────────────────────────────────────────────┐
│ Your Terminal / Web UI │
│ npm run demo / npm run ui │
└──────────────┬──────────────────────────────────────────┘
│
┌──────────────▼──────────────────────────────────────────┐
│ src/agent.ts (this project) │
│ │
│ ┌────────────────────────────┐ ┌──────────────────────────┐ │
│ │ GitHub Copilot SDK │ │ Agent Tools │ │
│ │ (CopilotClient) │ │ list_files, read_file, │ │
│ │ BYOK → Foundry │ │ write_file, run_command │ │
│ └────────┬───────────────────┘ └──────────────────────────┘ │
│ │ │
└────────────┼─────────────────────────────────────────────┘
│ JSON-RPC
┌────────────▼─────────────────────────────────────────────┐
│ GitHub Copilot CLI (server mode) │
│ Agent orchestration layer │
└────────────┬─────────────────────────────────────────────┘
│ POST /v1/chat/completions (BYOK)
┌────────────▼─────────────────────────────────────────────┐
│ Foundry Local (on-device inference) │
│ Model: qwen2.5-coder-1.5b via ONNX Runtime │
│ Endpoint: auto-detected (dynamic port) │
└───────────────────────────────────────────────────────────┘
Foundry Local (as of v0.5) can hang on stream: true requests. The project includes a lightweight HTTP proxy (streaming-proxy.ts) that transparently converts streaming requests to non-streaming, then re-encodes the single response as SSE chunks — the format the OpenAI SDK expects. Non-streaming and non-chat-completions requests pass through unchanged.
Small on-device models (e.g. qwen2.5-coder-1.5b) often output tool calls as JSON text rather than using OpenAI-style function calling. The SDK won't fire tool.execution_start events for these, so both agent.ts and web-agent.ts include a regex-based detector that scans streamed text for tool-name patterns and emits tool_start events. This keeps the dashboard tool call counter and the CLI log accurate regardless of whether the model uses native function calling or text output.
The entire connection between the GitHub Copilot SDK and Foundry Local is one config object:
const session = await client.createSession({
model: modelId,
provider: {
type: "openai", // Foundry Local speaks OpenAI's API format
baseUrl: proxyBaseUrl, // streaming proxy → Foundry Local
apiKey: manager.apiKey,
wireApi: "completions", // Chat Completions API
},
streaming: true,
tools: [ /* your tools */ ],
});This tells the GitHub Copilot SDK: "Don't call the cloud — send everything to my local model (via the streaming proxy)."
All settings are via environment variables. Edit .env (or use the defaults):
| Variable | Default | What it does |
|---|---|---|
FOUNDRY_LOCAL_ENDPOINT |
auto-detected | Override the Foundry Local API endpoint |
FOUNDRY_LOCAL_API_KEY |
auto-detected | Override the API key |
FOUNDRY_MODEL |
qwen2.5-coder-1.5b |
Which model to use from the Foundry Local catalog |
FOUNDRY_TIMEOUT_MS |
180000 (3 min) |
How long each agent phase can run before timing out |
FOUNDRY_NO_PROXY |
— | Set to 1 to disable the streaming proxy |
PORT |
3000 |
Port for the web dashboard |
# Use a different model
FOUNDRY_MODEL=phi-3-mini npm run demoIncrease the timeout so the model has more time per phase:
# 5 minutes per phase
FOUNDRY_TIMEOUT_MS=300000 npm run demolocal-repo-patch-agent/
│
├── setup.ps1 / setup.sh # One-command setup scripts
├── start.cmd / start.sh # Quick-launch scripts
├── package.json # npm scripts: demo, ui, setup, preflight
├── tsconfig.json # TypeScript config
├── .env.example # Environment variable template
├── LICENSE # MIT License
├── SECURITY.md # Security policy
├── CONTRIBUTING.md # How to contribute
├── blog_post.md # Developer blog post / walkthrough
├── README.md # ← You are here
│
├── src/ # Application source
│ ├── agent.ts # CLI agent: 4-phase loop + GitHub Copilot SDK + BYOK
│ ├── web-agent.ts # Web UI agent: same workflow, emits events via callback
│ ├── server.ts # Express + WebSocket server for the dashboard
│ ├── streaming-proxy.ts # Converts streaming requests to non-streaming + re-encodes as SSE
│ ├── tools.ts # Agent tools: list_files, read_file, write_file, run_command
│ ├── helpers.ts # sendMessage helper (handles Foundry Local streaming quirks)
│ └── tests/ # Diagnostic scripts for debugging SDK / Foundry integration
│ └── README.md # Describes each test script and how to run them
│
├── public/ # Web dashboard static assets
│ ├── index.html # Dashboard HTML
│ ├── styles.css # GitHub-dark themed responsive styles
│ └── app.js # Client-side WebSocket + event rendering
│
├── docs/images/ # Dashboard screenshots (idle, running, complete)
│
└── demo-repo/ # Toy repo the agent operates on
├── package.json # Test/lint/build scripts
├── src/
│ ├── account.js # BUG: calculateInterest uses / instead of *
│ ├── transaction.js # CODE SMELL: duplicated formatCurrency
│ └── utils.js # Canonical formatCurrency (currently unused)
└── test/
├── account.test.js # 6 tests — 3 FAIL until the bug is fixed
└── transaction.test.js # 3 tests — all pass
This project was built with security in mind:
- 100% local — No code, prompts, or responses leave your machine
- Command allowlist — The agent can only run
npm test,npm run lint, andnpm run build - Path sandboxing — File tools are locked to
demo-repo/— path traversal is blocked - File size limits —
read_filerejects files over 256 KB - Recursion limits —
list_filescaps directory depth at 20 levels
See SECURITY.md for the full security policy.
-
"GitHub Copilot SDK gives us an agent runtime" — Planning, tool invocation, file edits, and streaming out of the box. We define four simple tools and the SDK orchestrates everything.
-
"Foundry Local runs the model on-device" — An OpenAI-compatible API on
localhost(dynamic port, auto-detected). Privacy, compliance, offline — all handled. -
"BYOK wires them together" — One config object in
createSession()routes inference to Foundry Local. That's the entire integration. -
"The result" — An agent that reads a repo, finds a real bug, fixes it, refactors duplicated code, runs tests, and produces a PR-ready summary — without a single byte leaving the machine.
The src/tests/ folder contains standalone scripts for debugging SDK and Foundry Local integration issues. See src/tests/README.md for a full reference table.
Quick examples:
# Debug-level SDK event logging
npx tsx src/tests/test-debug.ts
# Test non-streaming inference
npx tsx src/tests/test-nostream.ts
# Raw fetch to Foundry Local (bypasses SDK)
npx tsx src/tests/test-stream-direct.ts
# Start the traffic-inspection proxy
npx tsx src/tests/test-proxy.ts| Problem | Solution |
|---|---|
foundry: command not found |
Install Foundry Local — see Prerequisites |
copilot: command not found |
Install GitHub Copilot CLI — see Prerequisites |
| Agent times out on every phase | Increase FOUNDRY_TIMEOUT_MS (e.g., 300000 for 5 min). CPU-only machines are slower. |
| Port 3000 already in use | Set PORT=3001 npm run ui |
| Model download is slow | First download can take 5-10 min depending on connection. Subsequent runs use the cache. |
Cannot find module errors |
Run npm install again, then cd demo-repo && npm install --ignore-scripts |
| Tests still fail after agent runs | The agent edits files in demo-repo/. Reset with git checkout demo-repo/ and run again. |
PowerShell blocks setup.ps1 |
Run Set-ExecutionPolicy -Scope Process Bypass first, then .\setup.ps1 |
| Resource | Link |
|---|---|
| Foundry Local site | https://www.foundrylocal.ai/ |
| Foundry Local repo | https://github.com/microsoft/Foundry-Local |
| Foundry Local get-started | https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-local/get-started |
| Foundry Local SDK reference | https://learn.microsoft.com/en-us/azure/ai-foundry/foundry-local/reference/reference-sdk |
| GitHub Copilot SDK + Foundry Local sample | https://github.com/microsoft/Foundry-Local/tree/main/samples/js/copilot-sdk-foundry-local |
| GitHub Copilot SDK | https://github.com/github/copilot-sdk |
| GitHub Copilot SDK BYOK docs | https://github.com/github/copilot-sdk/blob/main/docs/auth/byok.md |
| GitHub Copilot SDK getting started | https://github.com/github/copilot-sdk/blob/main/docs/getting-started.md |
MIT — see LICENSE for details.


