⏳ This skill is pending AI review.
Scores will appear once the review pipeline completes.
example-skill
Example skill that demonstrates the gitagent skills system. Use this to test skill loading and script execution.
// RATINGS
// README
Why Gitagent?
Most agent frameworks treat configuration as code scattered across your application. Gitagent flips this — your agent IS a git repository:
agent.yaml— model, tools, runtime configSOUL.md— personality and identityRULES.md— behavioral constraintsmemory/— git-committed memory with full historytools/— declarative YAML tool definitionsskills/— composable skill moduleshooks/— lifecycle hooks (script or programmatic)
Fork an agent. Branch a personality. git log your agent's memory. Diff its rules. This is agents as repos.
One-Command Install
Copy, paste, run. That's it — no cloning, no manual setup. The installer handles everything:
bash <(curl -fsSL "https://raw.githubusercontent.com/open-gitagent/gitagent/main/install.sh?$(date +%s)")
This will:
- Install gitagent globally via npm
- Walk you through API key setup (Quick or Advanced mode)
- Launch the voice UI in your browser at
http://localhost:3333
Requirements: Node.js 18+, npm, git
Or install manually:
# Slim CLI + SDK (recommended in sandboxed/CI environments where supply-chain
# scanners reject larger bundles)
npm install -g @open-gitagent/gitagent
# Add voice mode + web UI (the same web UI install.sh launches at :3333)
npm install -g @open-gitagent/voice
install.sh installs both packages by default. Set GITAGENT_SLIM=1 before
the curl-bash to skip voice.
Migrating from 1.x → 2.0
Voice mode lives in @open-gitagent/voice now. The reason: as a single bundle,
the package was being blocked by some supply-chain scanners that flagged its
3,800-line dist/voice/ui.html and the unused baileys dependency. Splitting
voice out drops the slim-core tarball from ~180 kB to ~85 kB and removes the
scanner triggers entirely.
# If you were on v1.x and used voice:
npm install -g @open-gitagent/gitagent@latest @open-gitagent/voice
# If you only use the SDK / non-voice CLI:
npm install -g @open-gitagent/gitagent@latest
The gitagent command and @open-gitagent/gitagent SDK exports are unchanged.
gitagent --voice dynamically loads @open-gitagent/voice; without it
installed, it prints a one-line install hint and exits cleanly.
Quick Start
Run your first agent in one line:
export OPENAI_API_KEY="sk-..."
gitagent --dir ~/my-project "Explain this project and suggest improvements"
That's it. Gitagent auto-scaffolds everything on first run — agent.yaml, SOUL.md, memory/ — and drops you into the agent.
Local Repo Mode
Clone a GitHub repo, run an agent on it, auto-commit and push to a session branch:
gitagent --repo https://github.com/org/repo --pat ghp_xxx "Fix the login bug"
Resume an existing session:
gitagent --repo https://github.com/org/repo --pat ghp_xxx --session gitagent/session-a1b2c3d4 "Continue"
Token can come from env instead of --pat:
export GITHUB_TOKEN=ghp_xxx
gitagent --repo https://github.com/org/repo "Add unit tests"
CLI Options
| Flag | Short | Description |
|---|---|---|
--dir <path> | -d | Agent directory (default: cwd) |
--repo <url> | -r | GitHub repo URL to clone and work on |
--pat <token> | GitHub PAT (or set GITHUB_TOKEN / GIT_TOKEN) | |
--session <branch> | Resume an existing session branch | |
--model <provider:model> | -m | Override model (e.g. anthropic:claude-sonnet-4-5-20250929) |
--sandbox | -s | Run in sandbox VM |
--prompt <text> | -p | Single-shot prompt (skip REPL) |
--env <name> | -e | Environment config |
SDK
import { query } from "gitagent";
// Simple query
for await (const msg of query({
prompt: "List all TypeScript files and summarize them",
dir: "./my-agent",
model: "openai:gpt-4o-mini",
})) {
if (msg.type === "delta") process.stdout.write(msg.content);
if (msg.type === "assistant") console.log("\n\nDone.");
}
// Local repo mode via SDK
for await (const msg of query({
prompt: "Fix the login bug",
model: "openai:gpt-4o-mini",
repo: {
url: "https://github.com/org/repo",
token: process.env.GITHUB_TOKEN!,
},
})) {
if (msg.type === "delta") process.stdout.write(msg.content);
}
SDK
The SDK provides a programmatic interface to Gitagent agents. It mirrors the Claude Agent SDK pattern but runs in-process — no subprocesses, no IPC.
query(options): Query
Returns an AsyncGenerator<GCMessage> that streams agent events.
import { query } from "gitagent";
for await (const msg of query({
prompt: "Refactor the auth module",
dir: "/path/to/agent",
model: "anthropic:claude-sonnet-4-5-20250929",
})) {
switch (msg.type) {
case "delta": // streaming text chunk
process.stdout.write(msg.content);
break;
case "assistant": // complete response
console.log(`\nTokens: ${msg.usage?.totalTokens}`);
break;
case "tool_use": // tool invocation
console.log(`Tool: ${msg.toolName}(${JSON.stringify(msg.args)})`);
break;
case "tool_result": // tool output
console.log(`Result: ${msg.content}`);
break;
case "system": // lifecycle events & errors
console.log(`[${msg.subtype}] ${msg.content}`);
break;
}
}
tool(name, description, schema, handler): GCToolDefinition
Define custom tools the agent can call:
import { query, tool } from "gitagent";
const search = tool(
"search_docs",
"Search the documentation",
{
properties: {
query: { type: "string", description: "Search query" },
limit: { type: "number", description: "Max results" },
},
required: ["query"],
},
async (args) => {
const results = await mySearchEngine(args.query, args.limit ?? 10);
return { text: JSON.stringify(results), details: { count: results.length } };
},
);
for await (const msg of query({
prompt: "Find docs about authentication",
tools: [search],
})) {
// agent can now call search_docs
}
Hooks
Programmatic lifecycle hooks for gating, logging, and control:
for await (const msg of query({
prompt: "Deploy the service",
hooks: {
preToolUse: async (ctx) => {
// Block dangerous operations
if (ctx.toolName === "cli" && ctx.args.command?.includes("rm -rf"))
return { action: "block", reason: "Destructive command blocked" };
// Modify arguments
if (ctx.toolName === "write" && !ctx.args.path.startsWith("/safe/"))
return { action: "modify", args: { ...ctx.args, path: `/safe/${ctx.args.path}` } };
return { action: "allow" };
},
onError: async (ctx) => {
console.error(`Agent error: ${c
// HOW IT'S BUILT
KEY FILES