
Security News
How Enterprise Security Is Adapting to AI-Accelerated Threats
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.
@posthog/agent
Advanced tools
TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog
TypeScript agent framework that wraps the Claude Agent SDK for PostHog's Array desktop app. Features a Git-based task execution system that stores task artifacts alongside your code.
bun install
bun run example
.posthog/ folders and committed to GitTaskRun records for easy pollingimport { Agent, PermissionMode } from '@posthog/agent';
import type { AgentEvent } from '@posthog/agent';
const agent = new Agent({
workingDirectory: "/path/to/repo",
posthogApiUrl: "https://app.posthog.com",
posthogApiKey: process.env.POSTHOG_API_KEY, // Used for both API and MCP
posthogProjectId: 1,
onEvent: (event) => {
// Streamed updates for responsive UIs
if (event.type !== 'token') {
handleLiveEvent(event);
}
},
});
// Run a task
const taskId = "task_abc123";
const task = await agent.getPostHogClient()?.fetchTask(taskId);
await agent.runTask(task, {
repositoryPath: "/path/to/repo",
permissionMode: PermissionMode.ACCEPT_EDITS,
isCloudMode: false,
createPR: true, // Optional: create PR after build. This setting has no effect if running in cloud mode.
autoProgress: true,
});
For local MCP development:
const agent = new Agent({
workingDirectory: "/path/to/repo",
posthogMcpUrl: 'http://localhost:8787/mcp',
});
Each task execution creates Git branches and follows a 3-phase approach:
.posthog/{id}/plan.md on branch posthog/task-{id}-planningposthog/task-{id}-implementationyour-repo/
├── .posthog/
│ ├── README.md
│ ├── .gitignore
│ └── {task-id}/
│ ├── plan.md
│ ├── questions.json (if research phase generated questions)
│ └── context.md (optional)
└── (your code)
Progress for each task execution is persisted to PostHog's TaskRun model, so UIs can poll for updates without relying on streaming hooks:
const agent = new Agent({
workingDirectory: repoPath,
posthogApiUrl: "https://app.posthog.com",
posthogApiKey: process.env.POSTHOG_KEY,
posthogProjectId: 1,
});
const poller = setInterval(async () => {
const runs = await agent.getPostHogClient()?.listTaskRuns(taskId);
const latestRun = runs?.sort((a, b) =>
new Date(b.created_at).getTime() - new Date(a.created_at).getTime()
)[0];
if (latestRun) {
renderProgress(latestRun.status, latestRun.log);
}
}, 3000);
try {
await agent.runTask(task, { repositoryPath: repoPath });
} finally {
clearInterval(poller);
}
// Live stream still available through the onEvent hook
function handleLiveEvent(event: AgentEvent) {
switch (event.type) {
case 'status':
// optimistic UI update
break;
case 'error':
notifyError(event.message);
break;
default:
break;
}
}
Prefer streaming updates? Pass an
onEventhandler when constructing the agent to keep receiving real-time events while progress is also written to PostHog.
@anthropic-ai/claude-agent-sdkYou can customize behavior using TaskExecutionOptions:
await agent.runTask(task, {
repositoryPath: "/path/to/repo",
permissionMode: PermissionMode.ACCEPT_EDITS, // or PLAN, DEFAULT, BYPASS
isCloudMode: false, // local execution with pauses between phases
autoProgress: true, // automatically progress through phases
queryOverrides: {
model: 'claude-sonnet-4-5-20250929',
temperature: 0.7
}
});
For advanced control over agent actions, you can provide a canUseTool callback that intercepts every tool use during the build phase (for task execution) or direct run calls. This allows you to implement custom approval flows, logging, or restrictions.
See the Claude Agent SDK Permissions docs for more details.
Apply the same permission hook to all task executions and direct runs:
import { Agent } from '@posthog/agent';
import type { PermissionResult } from '@posthog/agent';
const agent = new Agent({
workingDirectory: "/path/to/repo",
posthogApiUrl: "https://app.posthog.com",
posthogApiKey: process.env.POSTHOG_API_KEY,
posthogProjectId: 1,
canUseTool: async (toolName, input, { signal, suggestions }) => {
// Block destructive commands
if (toolName === 'Bash' && input.command?.includes('rm -rf')) {
return {
behavior: 'deny',
message: 'Destructive rm -rf commands are not allowed',
interrupt: true
};
}
// Allow everything else
return {
behavior: 'allow',
updatedInput: input
};
}
});
Override permissions for specific tasks (only applied during build phase):
await agent.runTask(task, {
repositoryPath: "/path/to/repo",
permissionMode: PermissionMode.DEFAULT,
canUseTool: async (toolName, input, { signal, suggestions }) => {
// Custom approval UI
const approved = await showApprovalDialog({
tool: toolName,
input: input,
suggestions: suggestions // Permission updates for "always allow"
});
if (approved.action === 'allow') {
return {
behavior: 'allow',
updatedInput: approved.modifiedInput || input,
updatedPermissions: approved.rememberChoice ? suggestions : undefined
};
}
return {
behavior: 'deny',
message: approved.reason || 'User denied permission',
interrupt: !approved.continueWithGuidance
};
}
});
For one-off queries with custom permissions:
const result = await agent.run("Fix the authentication bug", {
repositoryPath: "/path/to/repo",
permissionMode: PermissionMode.DEFAULT,
canUseTool: async (toolName, input, { signal }) => {
console.log(`Agent wants to use ${toolName}:`, input);
// Simple approval logic
if (toolName === 'Write' || toolName === 'Edit') {
const allowedFiles = ['src/', 'tests/'];
const filePath = input.file_path || input.path;
const isAllowed = allowedFiles.some(prefix => filePath?.startsWith(prefix));
if (!isAllowed) {
return {
behavior: 'deny',
message: `Can only modify files in: ${allowedFiles.join(', ')}`
};
}
}
return { behavior: 'allow', updatedInput: input };
}
});
The canUseTool callback receives one of these tool names:
Read, Glob, Grep, WebFetch, WebSearch, ListMcpResources, ReadMcpResourceWrite, Edit, NotebookEditBash, BashOutput, KillBash, TaskExitPlanMode, TodoWriteNote: Research and planning phases have fixed, read-only tool sets. The canUseTool hook only applies to the build phase and direct run calls.
FAQs
TypeScript agent framework wrapping Claude Agent SDK with Git-based task execution for PostHog
We found that @posthog/agent demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 14 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Socket CTO Ahmad Nassri discusses why supply chain attacks now target developer machines and what AI means for the future of enterprise security.

Security News
Learn the essential steps every developer should take to stay secure on npm and reduce exposure to supply chain attacks.

Security News
Experts push back on new claims about AI-driven ransomware, warning that hype and sponsored research are distorting how the threat is understood.