{"id":46317997,"url":"https://github.com/basher83/forgeflare-hooks","last_synced_at":"2026-03-12T06:00:29.023Z","repository":{"id":341142846,"uuid":"1157834121","full_name":"basher83/forgeflare-hooks","owner":"basher83","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-12T00:35:28.000Z","size":1690,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-03-12T02:15:20.812Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/basher83.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-02-14T11:22:46.000Z","updated_at":"2026-03-12T00:35:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/basher83/forgeflare-hooks","commit_stats":null,"previous_names":["basher83/forgeflare-hooks"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/basher83/forgeflare-hooks","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basher83%2Fforgeflare-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basher83%2Fforgeflare-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basher83%2Fforgeflare-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basher83%2Fforgeflare-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/basher83","download_url":"https://codeload.github.com/basher83/forgeflare-hooks/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/basher83%2Fforgeflare-hooks/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30416724,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-12T04:41:02.746Z","status":"ssl_error","status_checked_at":"2026-03-12T04:40:12.571Z","response_time":114,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-03-04T14:32:41.760Z","updated_at":"2026-03-12T06:00:29.005Z","avatar_url":"https://github.com/basher83.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ForgeFlare\n\nA streaming coding agent powered by Claude, built as a single Rust binary. ForgeFlare wraps the Anthropic Messages API with tool dispatch, a programmable hook system for controlling agent behavior, and convergence tracking for autonomous operation.\n\n## Quick Start\n\n```bash\ngit clone git@github.com:basher83/forgeflare-hooks.git\ncd forgeflare-hooks\ncargo build\n```\n\nOn the tailnet (default, no API key needed):\n\n```bash\ncargo run\n```\n\nOff tailnet with a direct API key:\n\n```bash\nANTHROPIC_API_KEY=sk-... cargo run -- --api-url https://api.anthropic.com\n```\n\n## Architecture\n\nForgeFlare runs an agentic loop: read user input, call the Claude API with streaming SSE, dispatch tool calls, and repeat until the model stops or a convergence signal fires. Five tools are available to the agent (Read, Glob, Bash, Edit, Grep), with pure tools (Read, Glob, Grep) executing concurrently and mutating tools (Bash, Edit) running sequentially.\n\nThe hook system is the distinguishing feature. External shell scripts can gate tool execution (guard hooks block dangerous commands), observe agent activity, signal convergence, and run cleanup on stop. Hooks communicate via JSON on stdin/stdout, with guard hooks fail-closed and observe/post/stop hooks fail-open.\n\n```text\nsrc/\n  main.rs       Agentic loop, context trimming, retry logic\n  api.rs        Anthropic Messages API client with SSE streaming\n  tools/mod.rs  Tool schemas (via macro) and dispatch router\n  hooks.rs      Hook runner: guard/observe/post/stop lifecycle\n  session.rs    Session transcript writer (JSONL + metadata)\n```\n\n## Hook System\n\nHooks are configured in `.forgeflare/hooks.toml` and run as shell executables that receive JSON on stdin and return JSON on stdout. Three lifecycle events are supported:\n\n**PreToolUse** runs before each tool call in two phases. Guard hooks can block tool execution (fail-closed: timeouts, crashes, and invalid JSON all result in blocking). Observe hooks run after guards with the guard outcome as context (fail-open).\n\n**PostToolUse** runs after each tool completes. Hooks can return a `signal` action to indicate convergence. Observations accumulate in `.forgeflare/convergence.json`.\n\n**Stop** fires when the agent turn ends, receiving the stop reason and token totals. The convergence file gets a `final` entry with the termination state.\n\n```toml\n# .forgeflare/hooks.toml\n[[hooks]]\nevent = \"PreToolUse\"\nphase = \"guard\"\ncommand = \"/path/to/guard.sh\"\nmatch_tool = \"Bash\"\ntimeout_ms = 5000\n\n[[hooks]]\nevent = \"PostToolUse\"\ncommand = \"/path/to/convergence-checker.sh\"\n\n[[hooks]]\nevent = \"Stop\"\ncommand = \"/path/to/cleanup.sh\"\n```\n\n## Convergence Tracking\n\nPostToolUse hooks can signal convergence by returning `{\"action\": \"signal\", \"signal\": \"converged\", \"reason\": \"...\"}`. These observations accumulate in `.forgeflare/convergence.json` with atomic writes (temp file + rename). When the agent turn ends, a `final` entry records the stop reason, tool iterations, total tokens, and timestamp.\n\nThis makes ForgeFlare suitable as the inner engine for autonomous loops where a bash supervisor needs to detect when the agent has converged and should stop.\n\n## Specs\n\nFeature specs live in `specs/` and document the design rationale and acceptance criteria for each capability. See `specs/README.md` for the full index and implementation order.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbasher83%2Fforgeflare-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbasher83%2Fforgeflare-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbasher83%2Fforgeflare-hooks/lists"}