Skip to content

AkaShark/AgentFlow

Repository files navigation

AgentFlow

English Β· δΈ­ζ–‡

Local web dashboard to visualize how AI agent skills, subagents, commands, and hooks are wired together and triggered at runtime.

AgentFlow points at any project that uses an AI coding agent (Claude Code first, more to come) and gives you three views:

  • πŸ“ Static Flowchart β€” force-directed graph of every skill / agent / command / hook and how they relate
  • ⏱ Runtime Timeline β€” real events captured via injected hooks, replayed on a horizontal axis
  • πŸ“‹ Resource Table β€” every resource with trigger counts, sortable

Stack

Layer Tech
Monorepo pnpm workspaces
Backend Node 20 Β· Express Β· TypeScript Β· Prisma Β· PostgreSQL 15
Frontend Vue 3 Β· Vite Β· TypeScript Β· Pinia Β· Naive UI Β· AntV G6 v5
Runtime Hook-injected JSONL β†’ file watcher β†’ Postgres β†’ WebSocket
Container Docker Compose (Podman compatible via wrapper)

1. Prerequisites

  • Node.js β‰₯ 20 β€” nvm install 20 && nvm use
  • pnpm β‰₯ 9 β€” npm i -g pnpm or corepack enable
  • Container engine: Docker Desktop / OrbStack or Podman 4.4+
  • A real Claude Code project to point at (anything with a .claude/ directory)

Check versions:

node -v        # v20.x
pnpm -v        # 9.x
docker --version || podman --version

2. First-time setup

# 1. install all workspace deps
pnpm install

# 2. start postgres (auto-detects docker or podman)
pnpm compose:up

# 3. configure server env
cp packages/server/.env.example packages/server/.env

# 4. apply database migrations
pnpm db:migrate

The pnpm db:migrate step:

  • Runs prisma migrate deploy against the Postgres in your container
  • Generates the Prisma client
  • The initial migration lives at packages/server/prisma/migrations/20260414000000_init/

If you change schema.prisma, generate a new migration with:

cd packages/server
pnpm exec prisma migrate dev --name describe_your_change

3. Daily development

Start everything

pnpm dev

This runs pnpm -r --parallel run dev, which starts:

Process Port Purpose
@agentflow/server (tsx watch) 4000 Express API + WebSocket + JSONL ingester
@agentflow/web (vite) 5173 Vue dashboard with HMR
@agentflow/core (tsc -w) β€” Type-checks shared types in watch mode
@agentflow/adapter-claude-code (tsc -w) β€” Same

Open http://localhost:5173.

Add and scan a project

  1. Open the Projects page (it's the default landing view)
  2. Click + Add Project
  3. Paste an absolute path to a Claude Code project (must contain .claude/ or CLAUDE.md)
  4. Optional: leave Install hook instrumentation now checked (default) to also wire up runtime capture in one step
  5. Click Add & scan β€” AgentFlow runs adapter detection, scans resources, optionally installs hooks, and selects the project
  6. Open the Flowchart tab β†’ click any node β†’ DetailDrawer slides in with full metadata

Capture runtime events

There are two ways to install the hook forwarder:

Option A β€” auto-install during Add Project (default, recommended)

The Add Project modal has a Install hook instrumentation now checkbox (on by default). When checked, AgentFlow will:

  • Create the project record
  • Run the static scan
  • Immediately apply the instrumentation plan

After this, just restart your Claude Code session in that project directory and events start flowing.

Option B β€” manual via the dashboard

If you want to review what gets written first (or you skipped the checkbox above):

  1. Select the project, click Install Hooks in the header
  2. The modal shows every file and every JSON patch AgentFlow will write
  3. Click Apply when you're satisfied
  4. Restart your Claude Code session

What gets written

In both cases AgentFlow writes the same two things to your project root:

  • <project>/.agentflow/hook-forwarder.mjs β€” a small Node.js script (~80 lines) with your AgentFlow projectId baked in. It reads each hook event payload from stdin and appends a JSON line to ~/.agentflow/events/<projectId>.jsonl.
  • Patches <project>/.claude/settings.json β€” adds entries to the hooks field for PreToolUse, PostToolUse, UserPromptSubmit, SessionStart, SessionEnd. Existing hooks are preserved (deep merge, not overwrite).

Nothing is touched outside your project root and ~/.agentflow/. No global state, no env-var wiring, no daemon.

How the capture actually works

AgentFlow does not inject anything into a running Claude Code process. It cooperates with Claude Code's native hook mechanism:

Claude Code session
      β”‚ (you ask Claude to do something)
      β–Ό
Claude calls a tool (Read / Bash / Edit / ...)
      β”‚
      β”‚ matches PreToolUse hook in settings.json
      β–Ό
Claude Code spawns: node .agentflow/hook-forwarder.mjs PreToolUse
      β”‚
      β”‚ stdin: {"tool_name":"Read","tool_input":{...},"session_id":"..."}
      β–Ό
forwarder appends one JSONL line, exits in ~3ms
      β”‚
      β–Ό
~/.agentflow/events/<projectId>.jsonl
      β”‚
      β”‚ chokidar file-watch
      β–Ό
AgentFlow Ingester β†’ adapter.parseEvent() β†’ Postgres
      β”‚
      β”œβ”€β†’ /api/events for the Timeline view
      └─→ WebSocket /ws/events for live updates

Important: hooks are loaded at session start

Claude Code reads .claude/settings.json once when a session starts. After installing hooks, the currently running session won't capture events β€” it doesn't know about the new hooks. You must:

  • Quit and restart Claude Code in that project, or
  • Open a fresh terminal and start a new session β€” both sessions can run in parallel and only the new one captures events

Uninstall

There is no Uninstall Hooks button (yet). To remove instrumentation manually:

cd /path/to/your/project
git checkout .claude/settings.json     # if tracked
# or hand-edit and remove the AgentFlow entries
rm -rf .agentflow/

AgentFlow never modifies anything outside .claude/settings.json and .agentflow/, so cleanup is local to the project.

Future install paths (planned)

Method Status Use case
Dashboard auto-install (Add Project checkbox) βœ… shipped Most users
Dashboard manual (Install Hooks button + preview) βœ… shipped Cautious users / re-install
npx agentflow init CLI πŸ”œ v0.2 "Init from project dir" workflow without opening the dashboard
Claude Code plugin (claude plugins install agentflow) πŸ”œ v1+ Zero-config, ships with the agent ecosystem

Container engine

pnpm compose:* auto-detects docker compose β†’ podman compose β†’ podman-compose. Force one:

AGENTFLOW_ENGINE=podman pnpm compose:up

4. Debugging

4.1 Backend (@agentflow/server)

# logs
pnpm --filter @agentflow/server dev   # tsx watch with stack traces

# typecheck only
pnpm --filter @agentflow/server typecheck

# inspect requests
curl http://localhost:4000/health
curl http://localhost:4000/api/projects
curl "http://localhost:4000/api/resources?projectId=<id>"
curl "http://localhost:4000/api/graph?projectId=<id>"

To attach a Node debugger, change the dev script in packages/server/package.json:

"dev": "tsx watch --inspect=9229 src/index.ts"

Then attach VS Code or Chrome DevTools to localhost:9229.

4.2 Database

# open a psql shell against the container
docker exec -it agentflow-postgres psql -U agentflow -d agentflow
# or
podman exec -it agentflow-postgres psql -U agentflow -d agentflow

# Prisma Studio (visual table browser)
cd packages/server && pnpm exec prisma studio

Useful queries:

SELECT id, name, "rootPath", "adapterId" FROM "Project";
SELECT type, count(*) FROM "Resource" GROUP BY type;
SELECT type, count(*) FROM "Event"  GROUP BY type ORDER BY 2 DESC;
SELECT "sessionId", count(*) FROM "Event" GROUP BY 1 ORDER BY 2 DESC LIMIT 10;

Wipe everything and re-migrate:

pnpm compose:down
docker volume rm agentflow_agentflow-pgdata    # or: podman volume rm ...
pnpm compose:up
pnpm db:migrate

4.3 Frontend (@agentflow/web)

  • Vite HMR is on by default β€” save and the browser updates

  • Vue DevTools (browser extension) shows the Pinia stores live: project, selection

  • Network panel shows requests routed via the Vite proxy (/api β†’ :4000, /ws β†’ ws on :4000)

  • Type-check separately:

    pnpm --filter @agentflow/web typecheck

Common gotchas:

  • CORS errors: the Vite proxy must be running. If you call the API directly, the server allows all origins via cors().
  • WebSocket disconnect: check the server log; the Ingester crashes are usually the cause.
  • Naive UI dark theme not applied: confirm <NConfigProvider :theme="darkTheme"> wraps the app in App.vue.

4.4 Hook instrumentation

The hardest part to debug because it runs inside the target Claude Code session.

Sanity check the forwarder:

echo '{"hook_event_name":"PreToolUse","tool_name":"Bash"}' \
  | AGENTFLOW_PROJECT_ID=test node <project>/.agentflow/hook-forwarder.mjs PreToolUse

# now check the file:
cat ~/.agentflow/events/test.jsonl

If a line appears, the forwarder works. If the dashboard still shows nothing, check:

  1. The Ingester is watching the right directory:

    • Server log line: [agentflow] watching events at /...
    • Override with AGENTFLOW_EVENTS_DIR=/abs/path in packages/server/.env
  2. The projectId in the JSONL matches a real Project.id in Postgres

  3. The Adapter's parseEvent returns a non-null event for that line β€” you can test:

    pnpm --filter @agentflow/adapter-claude-code exec node -e \
      'import("./dist/parseEvent.js").then(m => console.log(m.parseClaudeEvent("LINE_HERE")))'

Tail events live:

tail -f ~/.agentflow/events/<projectId>.jsonl | jq .

Uninstall hooks: edit your project's .claude/settings.json and remove the hooks block, or use git checkout. AgentFlow will not auto-revert.

4.5 Adapter changes

Iterate on packages/adapters/claude-code/:

pnpm --filter @agentflow/adapter-claude-code dev   # tsc --watch

The server imports it as workspace:*, so changes propagate after the next server restart (which tsx watch does automatically when imports change).

To re-scan after adapter logic changes:

curl -X POST http://localhost:4000/api/projects/<id>/scan

5. Project layout

AgentFlow/
β”œβ”€β”€ docs/
β”‚   β”œβ”€β”€ architecture.md         five-layer architecture, data flows
β”‚   β”œβ”€β”€ agent-adapter.md        AgentAdapter interface contract
β”‚   └── event-schema.md         JSONL envelope spec
β”œβ”€β”€ packages/
β”‚   β”œβ”€β”€ core/                   shared types + Scanner / Ingester / GraphBuilder / AdapterRegistry
β”‚   β”œβ”€β”€ adapters/
β”‚   β”‚   └── claude-code/        ClaudeCodeAdapter + relation inference + hook forwarder source
β”‚   β”œβ”€β”€ server/                 Express + Prisma + WebSocket + instrumentation service
β”‚   β”‚   └── prisma/
β”‚   β”‚       β”œβ”€β”€ schema.prisma
β”‚   β”‚       └── migrations/20260414000000_init/migration.sql
β”‚   └── web/                    Vue 3 dashboard (3 views, Pinia stores, G6 graph)
β”œβ”€β”€ docker/
β”‚   β”œβ”€β”€ docker-compose.yml      postgres / server / web services
β”‚   β”œβ”€β”€ Dockerfile.server
β”‚   β”œβ”€β”€ Dockerfile.web
β”‚   └── nginx.conf              reverse proxies /api and /ws
β”œβ”€β”€ scripts/
β”‚   └── compose.sh              docker / podman wrapper
β”œβ”€β”€ package.json                workspace root with `pnpm dev`, `pnpm compose:*`, `pnpm db:*`
β”œβ”€β”€ pnpm-workspace.yaml
β”œβ”€β”€ tsconfig.base.json
└── README.md                   ← you are here

6. API reference

Method Path Notes
GET /health Liveness probe
GET /api/projects List projects
POST /api/projects Create β€” body: { rootPath, name? }
POST /api/projects/:id/scan Re-scan and return graph
GET /api/projects/:id/instrumentation-plan Preview the InstrumentationPlan
POST /api/projects/:id/instrument Apply the plan (writes files)
GET /api/resources?projectId= List resources
GET /api/resources/:id Resource detail
GET /api/events?projectId=&sessionId=&limit= Recent events (default 200)
GET /api/events/sessions?projectId= Sessions summary
GET /api/graph?projectId= Nodes + edges
WS /ws/events Live event stream

7. Common issues

Symptom Likely cause Fix
pnpm install complains about peer deps Wrong Node version Use Node 20 (nvm use 20)
prisma migrate hangs Postgres not running pnpm compose:up first
ECONNREFUSED 5432 DATABASE_URL points at the wrong host In Docker the host is postgres, locally it's localhost
Dashboard empty after Add Project Adapter didn't detect Make sure the path actually contains .claude/
Timeline always empty Hook forwarder writing to a different dir Check AGENTFLOW_EVENTS_DIR matches on both sides
G6 nodes invisible Container has zero height The card needs min-height β€” already set, but check parent layout
EADDRINUSE :4000 Old server still running lsof -i :4000 then kill

8. Roadmap (post-MVP)

  • More adapters: Cursor, Cline, OpenCode, Gemini CLI
  • Session replay: scrub a slider to step through events
  • Zombie detection: highlight resources never triggered in N days
  • Multi-project workspace
  • Export graph as PNG / SVG
  • Dark/light theme toggle (currently dark only)

9. Docs

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors