diff --git a/AGENTS.md b/AGENTS.md index cdefab2..f205134 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -213,7 +213,7 @@ All tools use the same MCP server config. The only difference is where the confi | Tool | Config location | |------|----------------| | **Cursor** | `.cursor/mcp.json` (project) or `~/.cursor/mcp.json` (global) | -| **Claude Code** | `.mcp.json` (project) or via `claude mcp add vfs -- vfs mcp` | +| **Claude Code** | `claude mcp add vfs -- vfs mcp` (recommended) or `.mcp.json` (project) | | **Claude Desktop** | `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) | | **Antigravity** | MCP settings panel, or project MCP config. Also reads `AGENTS.md` / `GEMINI.md` | | **Windsurf** | `.windsurf/mcp.json` (project) or global via Windsurf settings | @@ -222,6 +222,33 @@ All tools use the same MCP server config. The only difference is where the confi | **Zed** | `~/.config/zed/settings.json` under `context_servers` | | **Any HTTP client** | Point to `http://localhost:8080/mcp` after running `vfs up` (use `--port` for custom port) | +### Claude Code setup + +**Recommended:** Use the CLI command (registers in `~/.claude.json` under project scope): + +```bash +claude mcp add vfs -- vfs mcp +``` + +This is the most reliable method. Claude Code reads MCP configs from its own settings file (`~/.claude.json`), not from `.mcp.json`. Using `claude mcp add` ensures the server is registered in the right place. + +**Alternative:** Add a `.mcp.json` file at the project root: + +```json +{ + "mcpServers": { + "vfs": { + "command": "vfs", + "args": ["mcp"] + } + } +} +``` + +> **Note:** Claude Code uses stdio transport for local MCP servers. Do NOT use `"type": "sse"` or `"type": "http"` — those are for HTTP-based tools like Cursor. If `.mcp.json` is not being picked up, use `claude mcp add` instead. + +### Other tools (Cursor, Windsurf, Cline, etc.) + The stdio config (works for most tools): ```json diff --git a/VERSION b/VERSION index 9579e1f..d79a5f8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.2.13 \ No newline at end of file +1.2.14 \ No newline at end of file diff --git a/cmd/vfs/stats_cmd.go b/cmd/vfs/stats_cmd.go index e413896..2b40fc7 100644 --- a/cmd/vfs/stats_cmd.go +++ b/cmd/vfs/stats_cmd.go @@ -1,13 +1,16 @@ package main import ( + "encoding/json" "fmt" + "os" "github.com/TrNgTien/vfs/internal/stats" "github.com/spf13/cobra" ) var statsReset bool +var statsJSON bool var statsCmd = &cobra.Command{ Use: "stats", @@ -17,6 +20,7 @@ var statsCmd = &cobra.Command{ func init() { statsCmd.Flags().BoolVar(&statsReset, "reset", false, "clear all history") + statsCmd.Flags().BoolVar(&statsJSON, "json", false, "output as JSON") } func runStats(cmd *cobra.Command, args []string) error { @@ -39,6 +43,12 @@ func runStats(cmd *cobra.Command, args []string) error { s := stats.Summarize(entries) + if statsJSON { + enc := json.NewEncoder(os.Stdout) + enc.SetIndent("", " ") + return enc.Encode(s) + } + fmt.Println("--- vfs lifetime stats ---") fmt.Printf("Invocations: %d\n", s.Invocations) fmt.Printf("Total tokens saved: ~%s\n", formatTokenCount(s.TotalSaved)) diff --git a/internal/stats/stats.go b/internal/stats/stats.go index bd87447..189bb72 100644 --- a/internal/stats/stats.go +++ b/internal/stats/stats.go @@ -26,21 +26,21 @@ type Entry struct { } type Summary struct { - Invocations int - TotalRawBytes int64 - TotalRawLines int - TotalVFSBytes int64 - TotalVFSLines int - TotalSaved int64 - AvgReduction float64 - FirstRecorded time.Time - LastRecorded time.Time - - Searches int - Extracts int - AvgDurationMs float64 - SearchHitRate float64 - EmptySearches int + Invocations int `json:"invocations"` + TotalRawBytes int64 `json:"total_raw_bytes"` + TotalRawLines int `json:"total_raw_lines"` + TotalVFSBytes int64 `json:"total_vfs_bytes"` + TotalVFSLines int `json:"total_vfs_lines"` + TotalSaved int64 `json:"total_saved"` + AvgReduction float64 `json:"avg_reduction"` + FirstRecorded time.Time `json:"first_recorded"` + LastRecorded time.Time `json:"last_recorded"` + + Searches int `json:"searches"` + Extracts int `json:"extracts"` + AvgDurationMs float64 `json:"avg_duration_ms"` + SearchHitRate float64 `json:"search_hit_rate"` + EmptySearches int `json:"empty_searches"` } func historyPath() string {