{"owner":"pgdogdev","repo":"pgdog","hasSkills":true,"totalSkillsCount":8,"totalTokensCount":2793,"categories":["claude-rule","anthropic-skill","root-instruction","plugin-manifest"],"hasMcp":false,"mcpConfig":null,"found":["CLAUDE.md",".claude/skills/bash/SKILL.md","AGENTS.md","pgdog-config/AGENTS.md","pgdog/CLAUDE.md",".claude/skills/rust/SKILL.md","plugins/README.md","pgdog-config/CLAUDE.md"],"skills":{"CLAUDE.md":"# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n\n\n## Running tests\n\nUnit tests:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a test fails, run it directly by name. Integration tests require Postgres configured via `bash integration/setup.sh` first.\n\nThe integration harness is multi-language: each suite lives in `integration/<lang>/`.\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `elixir`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`,\n`plugins`, `schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...)\nmust be run directly via their own `run.sh`.\n\n```sh\nbash integration/run.sh           # python + ruby + java + sql\nbash integration/go/run.sh        # Go suite\nbash integration/elixir/run.sh    # Elixir/Postgrex suite\n```\n\nFormat before committing: `cargo fmt`. Run `cargo clippy` where practical.",".claude/skills/bash/SKILL.md":"---\nname: bash\ndescription: How to use the shell successfully\nallowed-tools: Bash\n---\n\nExecute shell commands inside their own bash shell, like so:\n\n```bash\nbash -c 'command'\n```\n\nThis makes sure the shell is polluted by any outside state.\n","AGENTS.md":"\nRead `CLAUDE.md` and `.claude/skills/rust/SKILL.md`.\n\n## Tool usage\n\nPrefer the dedicated Read, Grep, and Glob tools for file searching and reading. Bash is permitted as a fallback when dedicated tools can't accomplish the task, but excessive Bash tool calls for search/read operations will be denied.\n\n\n## Running tests\n\nUnit and integration tests use `cargo-nextest`:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a single test fails, run it directly by name to isolate the failure.\n\nIntegration tests live under `integration/<lang>/`. The harness is multi-language;\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`, `plugins`,\n`schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...) must be run\ndirectly via their own `run.sh`. All suites require a running Postgres instance\nconfigured by `bash integration/setup.sh`.\n\n```sh\nbash integration/run.sh          # python + ruby + java + sql\n```\n\nOr a specific suite:\n\n```sh\nbash integration/go/run.sh\n```\n\nAlways run `cargo fmt` before submitting changes. Run `cargo clippy` where practical.","pgdog-config/AGENTS.md":"# pgdog-config\n\nFollow [CONTRIBUTING.md](CONTRIBUTING.md) for all changes in this directory.\n","pgdog/CLAUDE.md":"# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n",".claude/skills/rust/SKILL.md":"---\nname: rust\ndescription: Rust coding best practices for idiomatic, efficient, and maintainable code. Use when writing Rust code, reviewing code, or learning Rust patterns.\nallowed-tools: Read, Edit, Write, Bash, Grep, Glob, Task\n---\n\n# Rust Best Practices\n\nGuidelines for writing idiomatic, efficient, and maintainable Rust code.\n\n## Core Principles\n\n1. **Leverage the type system** - Make invalid states unrepresentable\n2. **Prefer compile-time checks** - Catch errors before runtime\n3. **Be explicit about ownership** - Don't fight the borrow checker\n4. **Write code that passes fmt/clippy first** - Not after fixing\n\n## Code health\n\n1. Prefer smaller files, refactor large files into multi-file modules\n2. Refactor large modules into several\n3. Prefer re-usable functions. Don't create separate functions if re-use is not planned.\n\n## Error Handling\n\nUse `thiserror`\n\n```rust\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum ConfigError {\n    #[error(\"Failed to read config: {0}\")]\n    Io(#[from] std::io::Error),\n\n    #[error(\"Failed to parse config: {0}\")]\n    Parse(#[from] toml::de::Error),\n\n    #[error(\"Invalid configuration: {message}\")]\n    Invalid { message: String },\n}\n```\n\n### Never Use `.unwrap()`\n\n```rust\n// BAD\nlet value = map.get(\"key\").unwrap();\n\n// GOOD\nlet value = map.get(\"key\").ok_or_else(|| Error::MissingKey(\"key\"))?;\n\n// GOOD (when None is truly impossible)\nlet value = map.get(\"key\").expect(\"key always present after init\");\n```\n\n## Ownership & Borrowing\n\n### Prefer Borrowing Over Cloning\n\n```rust\n// BAD - unnecessary clone\nfn process(data: String) { ... }\nprocess(my_string.clone());\n\n// GOOD - borrow when possible\nfn process(data: &str) { ... }\nprocess(&my_string);\n```\n\n### Use `Cow` for Flexible Ownership\n\n```rust\nuse std::borrow::Cow;\n\nfn process(data: Cow<'_, str>) -> Cow<'_, str> {\n    if data.contains(\"bad\") {\n        Cow::Owned(data.replace(\"bad\", \"good\"))\n    } else {\n        data  // No allocation if unchanged\n    }\n}\n```\n\n### Return Owned Data from Constructors\n\n```rust\n// GOOD - clear ownership\nimpl User {\n    pub fn new(name: impl Into<String>) -> Self {\n        Self { name: name.into() }\n    }\n}\n```\n\n## API Design\n\n### Builder Pattern for Complex Configuration\n\n```rust\n#[derive(Default)]\npub struct ServerBuilder {\n    host: Option<String>,\n    port: Option<u16>,\n    timeout: Option<Duration>,\n}\n\nimpl ServerBuilder {\n    pub fn host(mut self, host: impl Into<String>) -> Self {\n        self.host = Some(host.into());\n        self\n    }\n\n    pub fn port(mut self, port: u16) -> Self {\n        self.port = Some(port);\n        self\n    }\n\n    pub fn build(self) -> Result<Server, ConfigError> {\n        Ok(Server {\n            host: self.host.unwrap_or_else(|| \"localhost\".into()),\n            port: self.port.ok_or(ConfigError::MissingPort)?,\n            timeout: self.timeout.unwrap_or(Duration::from_secs(30)),\n        })\n    }\n}\n```\n\n### Newtype Pattern for Type Safety\n\n```rust\n// BAD - easy to mix up\nfn transfer(from: i64, to: i64, amount: i64) { ... }\n\n// GOOD - compile-time safety\npub struct AccountId(i64);\npub struct Amount(i64);\n\nfn transfer(from: AccountId, to: AccountId, amount: Amount) { ... }\n```\n\n### Use `#[must_use]` for Important Returns\n\n```rust\n#[must_use]\npub fn validate(&self) -> Result<(), ValidationError> {\n    // ...\n}\n```\n\n## Collections & Iterators\n\n### Prefer Iterators Over Loops\n\n```rust\n// BAD\nlet mut results = Vec::new();\nfor item in items {\n    if item.is_valid() {\n        results.push(item.transform());\n    }\n}\n\n// GOOD\nlet results: Vec<_> = items\n    .into_iter()\n    .filter(|item| item.is_valid())\n    .map(|item| item.transform())\n    .collect();\n```\n\n### Use `collect()` Type Inference\n\n```rust\n// Collect into Vec\nlet vec: Vec<_> = iter.collect();\n\n// Collect into HashMap\nlet map: HashMap<_, _> = iter.collect();\n\n// Collect Results\nlet results: Result<Vec<_>, _> = iter.collect();\n```\n\n## Async Patterns\n\n### Use `tokio` for Async Runtime\n\n```rust\n#[tokio::main]\nasync fn main() -> Result<()> {\n    let result = fetch_data().await?;\n    Ok(())\n}\n```\n\n### Avoid Blocking in Async Code\n\n```rust\n// BAD - blocks the runtime\nasync fn bad() {\n    std::thread::sleep(Duration::from_secs(1));\n}\n\n// GOOD - async sleep\nasync fn good() {\n    tokio::time::sleep(Duration::from_secs(1)).await;\n}\n\n// GOOD - spawn blocking for CPU-intensive work\nasync fn compute() -> i32 {\n    tokio::task::spawn_blocking(|| expensive_computation()).await.unwrap()\n}\n```\n\n## Testing\n\n### Unit Tests in Same File\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_basic() {\n        assert_eq!(add(1, 2), 3);\n    }\n\n    #[test]\n    fn test_edge_case() {\n        assert!(validate(\"\").is_err());\n    }\n}\n```\n\n### Integration Tests in `tests/`\n\n```rust\n// tests/integration_test.rs\nuse my_crate::public_api;\n\n#[test]\nfn test_full_workflow() {\n    let result = public_api::process(\"input\");\n    assert!(result.is_ok());\n}\n```\n\n### Use `assert!` Macros Effectively\n\n```rust\nassert!(condition);\nassert_eq!(left, right);\nassert_ne!(left, right);\nassert!(result.is_ok());\nassert!(result.is_err());\nassert_matches!(value, Pattern::Variant { .. });\n```\n\n## Performance\n\n### Avoid Premature Allocation\n\n```rust\n// BAD - allocates even if not needed\nfn maybe_string() -> String {\n    String::from(\"default\")\n}\n\n// GOOD - return static str when possible\nfn maybe_string() -> &'static str {\n    \"default\"\n}\n```\n\n### Use `Vec::with_capacity` for Known Sizes\n\n```rust\n// BAD - multiple reallocations\nlet mut vec = Vec::new();\nfor i in 0..1000 {\n    vec.push(i);\n}\n\n// GOOD - single allocation\nlet mut vec = Vec::with_capacity(1000);\nfor i in 0..1000 {\n    vec.push(i);\n}\n```\n\n### Import instead of using absolute paths\n\n```rust\n/// BAD\nlet v = tokio::net::TcpStream::connect(\"localhost:8080\");\n\n/// GOOD\nuse tokio::net::TcpStream;\nlet v = TcpStream::connect(\"localhost:8080\");\n```\n\n### Profile Before Optimizing\n\n```bash\ncargo build --release\ncargo flamegraph  # requires cargo-flamegraph\n```\n\n## Module Organization\n\n### Keep Modules Focused\n\n```rust\n// src/lib.rs\npub mod config;\npub mod client;\npub mod error;\n\n// Re-export public API\npub use config::Config;\npub use client::Client;\npub use error::Error;\n```\n\n### Use `pub(crate)` for Internal APIs\n\n```rust\n// Public to crate, not external users\npub(crate) fn internal_helper() { ... }\n```\n\n## Documentation\n\n### Document Public APIs\n\n```rust\n/// Creates a new client with the given configuration.\n///\n/// # Arguments\n///\n/// * `config` - The client configuration\n///\n/// # Errors\n///\n/// Returns an error if the configuration is invalid.\n///\n/// # Examples\n///\n/// ```\n/// let client = Client::new(Config::default())?;\n/// ```\npub fn new(config: Config) -> Result<Self> {\n    // ...\n}\n```\n\n## Anti-Patterns to Avoid\n\n| Anti-Pattern | Better Approach |\n|--------------|-----------------|\n| `.unwrap()` everywhere | Use `?` operator |\n| `clone()` to satisfy borrow checker | Restructure ownership |\n| `String` parameters | Use `&str` or `impl Into<String>` |\n| Boolean parameters | Use enums |\n| Long function bodies | Extract to smaller functions |\n| Deep nesting | Use early returns |\n| Magic numbers | Use named constants |\n\n## Quick Reference\n\n```bash\n# Quality gates\ncargo fmt -- --check && cargo clippy -- -D warnings && cargo test\n\n# Common cargo commands\ncargo check           # Fast syntax/type check\ncargo build           # Debug build\ncargo build --release # Release build\ncargo nextest run     # Run tests\ncargo doc --open      # Generate and view docs\ncargo clippy --fix    # Auto-fix lint issues\n```\n","plugins/README.md":"# PgDog plugins\n\nThis directory contains plugins that ship with PgDog and are built by original author(s) or by the community. You can use these as-is or modify them to your needs.\n\n## Plugins\n\n### `pgdog-example-plugin`\n\nExample plugin that can be used as reference by the community. It currently records\nwhen a write was made to a table and, for the next 5 seconds after the write, redirects\nall `SELECT` queries that touch table to the primary.\n\nIt's a simple workaround for Postgres replica lag, if you're using batch writes.\n","pgdog-config/CLAUDE.md":"Treat @AGENTS.md the same way you would CLAUDE.md\n"},"files":{"CLAUDE.md":"# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n\n\n## Running tests\n\nUnit tests:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a test fails, run it directly by name. Integration tests require Postgres configured via `bash integration/setup.sh` first.\n\nThe integration harness is multi-language: each suite lives in `integration/<lang>/`.\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `elixir`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`,\n`plugins`, `schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...)\nmust be run directly via their own `run.sh`.\n\n```sh\nbash integration/run.sh           # python + ruby + java + sql\nbash integration/go/run.sh        # Go suite\nbash integration/elixir/run.sh    # Elixir/Postgrex suite\n```\n\nFormat before committing: `cargo fmt`. Run `cargo clippy` where practical.",".claude/skills/bash/SKILL.md":"---\nname: bash\ndescription: How to use the shell successfully\nallowed-tools: Bash\n---\n\nExecute shell commands inside their own bash shell, like so:\n\n```bash\nbash -c 'command'\n```\n\nThis makes sure the shell is polluted by any outside state.\n","AGENTS.md":"\nRead `CLAUDE.md` and `.claude/skills/rust/SKILL.md`.\n\n## Tool usage\n\nPrefer the dedicated Read, Grep, and Glob tools for file searching and reading. Bash is permitted as a fallback when dedicated tools can't accomplish the task, but excessive Bash tool calls for search/read operations will be denied.\n\n\n## Running tests\n\nUnit and integration tests use `cargo-nextest`:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a single test fails, run it directly by name to isolate the failure.\n\nIntegration tests live under `integration/<lang>/`. The harness is multi-language;\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`, `plugins`,\n`schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...) must be run\ndirectly via their own `run.sh`. All suites require a running Postgres instance\nconfigured by `bash integration/setup.sh`.\n\n```sh\nbash integration/run.sh          # python + ruby + java + sql\n```\n\nOr a specific suite:\n\n```sh\nbash integration/go/run.sh\n```\n\nAlways run `cargo fmt` before submitting changes. Run `cargo clippy` where practical.","pgdog-config/AGENTS.md":"# pgdog-config\n\nFollow [CONTRIBUTING.md](CONTRIBUTING.md) for all changes in this directory.\n","pgdog/CLAUDE.md":"# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n",".claude/skills/rust/SKILL.md":"---\nname: rust\ndescription: Rust coding best practices for idiomatic, efficient, and maintainable code. Use when writing Rust code, reviewing code, or learning Rust patterns.\nallowed-tools: Read, Edit, Write, Bash, Grep, Glob, Task\n---\n\n# Rust Best Practices\n\nGuidelines for writing idiomatic, efficient, and maintainable Rust code.\n\n## Core Principles\n\n1. **Leverage the type system** - Make invalid states unrepresentable\n2. **Prefer compile-time checks** - Catch errors before runtime\n3. **Be explicit about ownership** - Don't fight the borrow checker\n4. **Write code that passes fmt/clippy first** - Not after fixing\n\n## Code health\n\n1. Prefer smaller files, refactor large files into multi-file modules\n2. Refactor large modules into several\n3. Prefer re-usable functions. Don't create separate functions if re-use is not planned.\n\n## Error Handling\n\nUse `thiserror`\n\n```rust\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum ConfigError {\n    #[error(\"Failed to read config: {0}\")]\n    Io(#[from] std::io::Error),\n\n    #[error(\"Failed to parse config: {0}\")]\n    Parse(#[from] toml::de::Error),\n\n    #[error(\"Invalid configuration: {message}\")]\n    Invalid { message: String },\n}\n```\n\n### Never Use `.unwrap()`\n\n```rust\n// BAD\nlet value = map.get(\"key\").unwrap();\n\n// GOOD\nlet value = map.get(\"key\").ok_or_else(|| Error::MissingKey(\"key\"))?;\n\n// GOOD (when None is truly impossible)\nlet value = map.get(\"key\").expect(\"key always present after init\");\n```\n\n## Ownership & Borrowing\n\n### Prefer Borrowing Over Cloning\n\n```rust\n// BAD - unnecessary clone\nfn process(data: String) { ... }\nprocess(my_string.clone());\n\n// GOOD - borrow when possible\nfn process(data: &str) { ... }\nprocess(&my_string);\n```\n\n### Use `Cow` for Flexible Ownership\n\n```rust\nuse std::borrow::Cow;\n\nfn process(data: Cow<'_, str>) -> Cow<'_, str> {\n    if data.contains(\"bad\") {\n        Cow::Owned(data.replace(\"bad\", \"good\"))\n    } else {\n        data  // No allocation if unchanged\n    }\n}\n```\n\n### Return Owned Data from Constructors\n\n```rust\n// GOOD - clear ownership\nimpl User {\n    pub fn new(name: impl Into<String>) -> Self {\n        Self { name: name.into() }\n    }\n}\n```\n\n## API Design\n\n### Builder Pattern for Complex Configuration\n\n```rust\n#[derive(Default)]\npub struct ServerBuilder {\n    host: Option<String>,\n    port: Option<u16>,\n    timeout: Option<Duration>,\n}\n\nimpl ServerBuilder {\n    pub fn host(mut self, host: impl Into<String>) -> Self {\n        self.host = Some(host.into());\n        self\n    }\n\n    pub fn port(mut self, port: u16) -> Self {\n        self.port = Some(port);\n        self\n    }\n\n    pub fn build(self) -> Result<Server, ConfigError> {\n        Ok(Server {\n            host: self.host.unwrap_or_else(|| \"localhost\".into()),\n            port: self.port.ok_or(ConfigError::MissingPort)?,\n            timeout: self.timeout.unwrap_or(Duration::from_secs(30)),\n        })\n    }\n}\n```\n\n### Newtype Pattern for Type Safety\n\n```rust\n// BAD - easy to mix up\nfn transfer(from: i64, to: i64, amount: i64) { ... }\n\n// GOOD - compile-time safety\npub struct AccountId(i64);\npub struct Amount(i64);\n\nfn transfer(from: AccountId, to: AccountId, amount: Amount) { ... }\n```\n\n### Use `#[must_use]` for Important Returns\n\n```rust\n#[must_use]\npub fn validate(&self) -> Result<(), ValidationError> {\n    // ...\n}\n```\n\n## Collections & Iterators\n\n### Prefer Iterators Over Loops\n\n```rust\n// BAD\nlet mut results = Vec::new();\nfor item in items {\n    if item.is_valid() {\n        results.push(item.transform());\n    }\n}\n\n// GOOD\nlet results: Vec<_> = items\n    .into_iter()\n    .filter(|item| item.is_valid())\n    .map(|item| item.transform())\n    .collect();\n```\n\n### Use `collect()` Type Inference\n\n```rust\n// Collect into Vec\nlet vec: Vec<_> = iter.collect();\n\n// Collect into HashMap\nlet map: HashMap<_, _> = iter.collect();\n\n// Collect Results\nlet results: Result<Vec<_>, _> = iter.collect();\n```\n\n## Async Patterns\n\n### Use `tokio` for Async Runtime\n\n```rust\n#[tokio::main]\nasync fn main() -> Result<()> {\n    let result = fetch_data().await?;\n    Ok(())\n}\n```\n\n### Avoid Blocking in Async Code\n\n```rust\n// BAD - blocks the runtime\nasync fn bad() {\n    std::thread::sleep(Duration::from_secs(1));\n}\n\n// GOOD - async sleep\nasync fn good() {\n    tokio::time::sleep(Duration::from_secs(1)).await;\n}\n\n// GOOD - spawn blocking for CPU-intensive work\nasync fn compute() -> i32 {\n    tokio::task::spawn_blocking(|| expensive_computation()).await.unwrap()\n}\n```\n\n## Testing\n\n### Unit Tests in Same File\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_basic() {\n        assert_eq!(add(1, 2), 3);\n    }\n\n    #[test]\n    fn test_edge_case() {\n        assert!(validate(\"\").is_err());\n    }\n}\n```\n\n### Integration Tests in `tests/`\n\n```rust\n// tests/integration_test.rs\nuse my_crate::public_api;\n\n#[test]\nfn test_full_workflow() {\n    let result = public_api::process(\"input\");\n    assert!(result.is_ok());\n}\n```\n\n### Use `assert!` Macros Effectively\n\n```rust\nassert!(condition);\nassert_eq!(left, right);\nassert_ne!(left, right);\nassert!(result.is_ok());\nassert!(result.is_err());\nassert_matches!(value, Pattern::Variant { .. });\n```\n\n## Performance\n\n### Avoid Premature Allocation\n\n```rust\n// BAD - allocates even if not needed\nfn maybe_string() -> String {\n    String::from(\"default\")\n}\n\n// GOOD - return static str when possible\nfn maybe_string() -> &'static str {\n    \"default\"\n}\n```\n\n### Use `Vec::with_capacity` for Known Sizes\n\n```rust\n// BAD - multiple reallocations\nlet mut vec = Vec::new();\nfor i in 0..1000 {\n    vec.push(i);\n}\n\n// GOOD - single allocation\nlet mut vec = Vec::with_capacity(1000);\nfor i in 0..1000 {\n    vec.push(i);\n}\n```\n\n### Import instead of using absolute paths\n\n```rust\n/// BAD\nlet v = tokio::net::TcpStream::connect(\"localhost:8080\");\n\n/// GOOD\nuse tokio::net::TcpStream;\nlet v = TcpStream::connect(\"localhost:8080\");\n```\n\n### Profile Before Optimizing\n\n```bash\ncargo build --release\ncargo flamegraph  # requires cargo-flamegraph\n```\n\n## Module Organization\n\n### Keep Modules Focused\n\n```rust\n// src/lib.rs\npub mod config;\npub mod client;\npub mod error;\n\n// Re-export public API\npub use config::Config;\npub use client::Client;\npub use error::Error;\n```\n\n### Use `pub(crate)` for Internal APIs\n\n```rust\n// Public to crate, not external users\npub(crate) fn internal_helper() { ... }\n```\n\n## Documentation\n\n### Document Public APIs\n\n```rust\n/// Creates a new client with the given configuration.\n///\n/// # Arguments\n///\n/// * `config` - The client configuration\n///\n/// # Errors\n///\n/// Returns an error if the configuration is invalid.\n///\n/// # Examples\n///\n/// ```\n/// let client = Client::new(Config::default())?;\n/// ```\npub fn new(config: Config) -> Result<Self> {\n    // ...\n}\n```\n\n## Anti-Patterns to Avoid\n\n| Anti-Pattern | Better Approach |\n|--------------|-----------------|\n| `.unwrap()` everywhere | Use `?` operator |\n| `clone()` to satisfy borrow checker | Restructure ownership |\n| `String` parameters | Use `&str` or `impl Into<String>` |\n| Boolean parameters | Use enums |\n| Long function bodies | Extract to smaller functions |\n| Deep nesting | Use early returns |\n| Magic numbers | Use named constants |\n\n## Quick Reference\n\n```bash\n# Quality gates\ncargo fmt -- --check && cargo clippy -- -D warnings && cargo test\n\n# Common cargo commands\ncargo check           # Fast syntax/type check\ncargo build           # Debug build\ncargo build --release # Release build\ncargo nextest run     # Run tests\ncargo doc --open      # Generate and view docs\ncargo clippy --fix    # Auto-fix lint issues\n```\n","plugins/README.md":"# PgDog plugins\n\nThis directory contains plugins that ship with PgDog and are built by original author(s) or by the community. You can use these as-is or modify them to your needs.\n\n## Plugins\n\n### `pgdog-example-plugin`\n\nExample plugin that can be used as reference by the community. It currently records\nwhen a write was made to a table and, for the next 5 seconds after the write, redirects\nall `SELECT` queries that touch table to the primary.\n\nIt's a simple workaround for Postgres replica lag, if you're using batch writes.\n","pgdog-config/CLAUDE.md":"Treat @AGENTS.md the same way you would CLAUDE.md\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/AGENTS.md","title":"AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"\nRead `CLAUDE.md` and `.claude/skills/rust/SKILL.md`.\n\n## Tool usage\n\nPrefer the dedicated Read, Grep, and Glob tools for file searching and reading. Bash is permitted as a fallback when dedicated tools can't accomplish the task, but excessive Bash tool calls for search/read operations will be denied.\n\n\n## Running tests\n\nUnit and integration tests use `cargo-nextest`:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a single test fails, run it directly by name to isolate the failure.\n\nIntegration tests live under `integration/<lang>/`. The harness is multi-language;\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`, `plugins`,\n`schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...) must be run\ndirectly via their own `run.sh`. All suites require a running Postgres instance\nconfigured by `bash integration/setup.sh`.\n\n```sh\nbash integration/run.sh          # python + ruby + java + sql\n```\n\nOr a specific suite:\n\n```sh\nbash integration/go/run.sh\n```\n\nAlways run `cargo fmt` before submitting changes. Run `cargo clippy` where practical.","isInternal":false,"tokens":286,"sizeBytes":1160},{"name":"AGENTS.md","path":"pgdog-config/AGENTS.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/pgdog-config/AGENTS.md","title":"pgdog-config - AI Agent Protocol & Instructions","category":"root-instruction","format":"markdown","content":"# pgdog-config\n\nFollow [CONTRIBUTING.md](CONTRIBUTING.md) for all changes in this directory.\n","isInternal":false,"tokens":26,"sizeBytes":93},{"name":"SKILL.md","path":".claude/skills/bash/SKILL.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/.claude/skills/bash/SKILL.md","title":"bash","category":"anthropic-skill","format":"markdown","content":"---\nname: bash\ndescription: How to use the shell successfully\nallowed-tools: Bash\n---\n\nExecute shell commands inside their own bash shell, like so:\n\n```bash\nbash -c 'command'\n```\n\nThis makes sure the shell is polluted by any outside state.\n","frontmatter":{"name":"bash","description":"How to use the shell successfully","allowed-tools":"Bash","allowedTools":["Bash"]},"allowedTools":["Bash"],"isInternal":false,"tokens":55,"sizeBytes":240},{"name":"SKILL.md","path":".claude/skills/rust/SKILL.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/.claude/skills/rust/SKILL.md","title":"rust","category":"anthropic-skill","format":"markdown","content":"---\nname: rust\ndescription: Rust coding best practices for idiomatic, efficient, and maintainable code. Use when writing Rust code, reviewing code, or learning Rust patterns.\nallowed-tools: Read, Edit, Write, Bash, Grep, Glob, Task\n---\n\n# Rust Best Practices\n\nGuidelines for writing idiomatic, efficient, and maintainable Rust code.\n\n## Core Principles\n\n1. **Leverage the type system** - Make invalid states unrepresentable\n2. **Prefer compile-time checks** - Catch errors before runtime\n3. **Be explicit about ownership** - Don't fight the borrow checker\n4. **Write code that passes fmt/clippy first** - Not after fixing\n\n## Code health\n\n1. Prefer smaller files, refactor large files into multi-file modules\n2. Refactor large modules into several\n3. Prefer re-usable functions. Don't create separate functions if re-use is not planned.\n\n## Error Handling\n\nUse `thiserror`\n\n```rust\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum ConfigError {\n    #[error(\"Failed to read config: {0}\")]\n    Io(#[from] std::io::Error),\n\n    #[error(\"Failed to parse config: {0}\")]\n    Parse(#[from] toml::de::Error),\n\n    #[error(\"Invalid configuration: {message}\")]\n    Invalid { message: String },\n}\n```\n\n### Never Use `.unwrap()`\n\n```rust\n// BAD\nlet value = map.get(\"key\").unwrap();\n\n// GOOD\nlet value = map.get(\"key\").ok_or_else(|| Error::MissingKey(\"key\"))?;\n\n// GOOD (when None is truly impossible)\nlet value = map.get(\"key\").expect(\"key always present after init\");\n```\n\n## Ownership & Borrowing\n\n### Prefer Borrowing Over Cloning\n\n```rust\n// BAD - unnecessary clone\nfn process(data: String) { ... }\nprocess(my_string.clone());\n\n// GOOD - borrow when possible\nfn process(data: &str) { ... }\nprocess(&my_string);\n```\n\n### Use `Cow` for Flexible Ownership\n\n```rust\nuse std::borrow::Cow;\n\nfn process(data: Cow<'_, str>) -> Cow<'_, str> {\n    if data.contains(\"bad\") {\n        Cow::Owned(data.replace(\"bad\", \"good\"))\n    } else {\n        data  // No allocation if unchanged\n    }\n}\n```\n\n### Return Owned Data from Constructors\n\n```rust\n// GOOD - clear ownership\nimpl User {\n    pub fn new(name: impl Into<String>) -> Self {\n        Self { name: name.into() }\n    }\n}\n```\n\n## API Design\n\n### Builder Pattern for Complex Configuration\n\n```rust\n#[derive(Default)]\npub struct ServerBuilder {\n    host: Option<String>,\n    port: Option<u16>,\n    timeout: Option<Duration>,\n}\n\nimpl ServerBuilder {\n    pub fn host(mut self, host: impl Into<String>) -> Self {\n        self.host = Some(host.into());\n        self\n    }\n\n    pub fn port(mut self, port: u16) -> Self {\n        self.port = Some(port);\n        self\n    }\n\n    pub fn build(self) -> Result<Server, ConfigError> {\n        Ok(Server {\n            host: self.host.unwrap_or_else(|| \"localhost\".into()),\n            port: self.port.ok_or(ConfigError::MissingPort)?,\n            timeout: self.timeout.unwrap_or(Duration::from_secs(30)),\n        })\n    }\n}\n```\n\n### Newtype Pattern for Type Safety\n\n```rust\n// BAD - easy to mix up\nfn transfer(from: i64, to: i64, amount: i64) { ... }\n\n// GOOD - compile-time safety\npub struct AccountId(i64);\npub struct Amount(i64);\n\nfn transfer(from: AccountId, to: AccountId, amount: Amount) { ... }\n```\n\n### Use `#[must_use]` for Important Returns\n\n```rust\n#[must_use]\npub fn validate(&self) -> Result<(), ValidationError> {\n    // ...\n}\n```\n\n## Collections & Iterators\n\n### Prefer Iterators Over Loops\n\n```rust\n// BAD\nlet mut results = Vec::new();\nfor item in items {\n    if item.is_valid() {\n        results.push(item.transform());\n    }\n}\n\n// GOOD\nlet results: Vec<_> = items\n    .into_iter()\n    .filter(|item| item.is_valid())\n    .map(|item| item.transform())\n    .collect();\n```\n\n### Use `collect()` Type Inference\n\n```rust\n// Collect into Vec\nlet vec: Vec<_> = iter.collect();\n\n// Collect into HashMap\nlet map: HashMap<_, _> = iter.collect();\n\n// Collect Results\nlet results: Result<Vec<_>, _> = iter.collect();\n```\n\n## Async Patterns\n\n### Use `tokio` for Async Runtime\n\n```rust\n#[tokio::main]\nasync fn main() -> Result<()> {\n    let result = fetch_data().await?;\n    Ok(())\n}\n```\n\n### Avoid Blocking in Async Code\n\n```rust\n// BAD - blocks the runtime\nasync fn bad() {\n    std::thread::sleep(Duration::from_secs(1));\n}\n\n// GOOD - async sleep\nasync fn good() {\n    tokio::time::sleep(Duration::from_secs(1)).await;\n}\n\n// GOOD - spawn blocking for CPU-intensive work\nasync fn compute() -> i32 {\n    tokio::task::spawn_blocking(|| expensive_computation()).await.unwrap()\n}\n```\n\n## Testing\n\n### Unit Tests in Same File\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_basic() {\n        assert_eq!(add(1, 2), 3);\n    }\n\n    #[test]\n    fn test_edge_case() {\n        assert!(validate(\"\").is_err());\n    }\n}\n```\n\n### Integration Tests in `tests/`\n\n```rust\n// tests/integration_test.rs\nuse my_crate::public_api;\n\n#[test]\nfn test_full_workflow() {\n    let result = public_api::process(\"input\");\n    assert!(result.is_ok());\n}\n```\n\n### Use `assert!` Macros Effectively\n\n```rust\nassert!(condition);\nassert_eq!(left, right);\nassert_ne!(left, right);\nassert!(result.is_ok());\nassert!(result.is_err());\nassert_matches!(value, Pattern::Variant { .. });\n```\n\n## Performance\n\n### Avoid Premature Allocation\n\n```rust\n// BAD - allocates even if not needed\nfn maybe_string() -> String {\n    String::from(\"default\")\n}\n\n// GOOD - return static str when possible\nfn maybe_string() -> &'static str {\n    \"default\"\n}\n```\n\n### Use `Vec::with_capacity` for Known Sizes\n\n```rust\n// BAD - multiple reallocations\nlet mut vec = Vec::new();\nfor i in 0..1000 {\n    vec.push(i);\n}\n\n// GOOD - single allocation\nlet mut vec = Vec::with_capacity(1000);\nfor i in 0..1000 {\n    vec.push(i);\n}\n```\n\n### Import instead of using absolute paths\n\n```rust\n/// BAD\nlet v = tokio::net::TcpStream::connect(\"localhost:8080\");\n\n/// GOOD\nuse tokio::net::TcpStream;\nlet v = TcpStream::connect(\"localhost:8080\");\n```\n\n### Profile Before Optimizing\n\n```bash\ncargo build --release\ncargo flamegraph  # requires cargo-flamegraph\n```\n\n## Module Organization\n\n### Keep Modules Focused\n\n```rust\n// src/lib.rs\npub mod config;\npub mod client;\npub mod error;\n\n// Re-export public API\npub use config::Config;\npub use client::Client;\npub use error::Error;\n```\n\n### Use `pub(crate)` for Internal APIs\n\n```rust\n// Public to crate, not external users\npub(crate) fn internal_helper() { ... }\n```\n\n## Documentation\n\n### Document Public APIs\n\n```rust\n/// Creates a new client with the given configuration.\n///\n/// # Arguments\n///\n/// * `config` - The client configuration\n///\n/// # Errors\n///\n/// Returns an error if the configuration is invalid.\n///\n/// # Examples\n///\n/// ```\n/// let client = Client::new(Config::default())?;\n/// ```\npub fn new(config: Config) -> Result<Self> {\n    // ...\n}\n```\n\n## Anti-Patterns to Avoid\n\n| Anti-Pattern | Better Approach |\n|--------------|-----------------|\n| `.unwrap()` everywhere | Use `?` operator |\n| `clone()` to satisfy borrow checker | Restructure ownership |\n| `String` parameters | Use `&str` or `impl Into<String>` |\n| Boolean parameters | Use enums |\n| Long function bodies | Extract to smaller functions |\n| Deep nesting | Use early returns |\n| Magic numbers | Use named constants |\n\n## Quick Reference\n\n```bash\n# Quality gates\ncargo fmt -- --check && cargo clippy -- -D warnings && cargo test\n\n# Common cargo commands\ncargo check           # Fast syntax/type check\ncargo build           # Debug build\ncargo build --release # Release build\ncargo nextest run     # Run tests\ncargo doc --open      # Generate and view docs\ncargo clippy --fix    # Auto-fix lint issues\n```\n","frontmatter":{"name":"rust","description":"Rust coding best practices for idiomatic, efficient, and maintainable code. Use when writing Rust code, reviewing code, or learning Rust patterns.","allowed-tools":"Read, Edit, Write, Bash, Grep, Glob, Task","allowedTools":["Read,","Edit,","Write,","Bash,","Grep,","Glob,","Task"]},"allowedTools":["Read,","Edit,","Write,","Bash,","Grep,","Glob,","Task"],"isInternal":false,"tokens":1920,"sizeBytes":7564},{"name":"CLAUDE.md","path":"CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/CLAUDE.md","title":"Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n\n\n## Running tests\n\nUnit tests:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a test fails, run it directly by name. Integration tests require Postgres configured via `bash integration/setup.sh` first.\n\nThe integration harness is multi-language: each suite lives in `integration/<lang>/`.\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `elixir`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`,\n`plugins`, `schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...)\nmust be run directly via their own `run.sh`.\n\n```sh\nbash integration/run.sh           # python + ruby + java + sql\nbash integration/go/run.sh        # Go suite\nbash integration/elixir/run.sh    # Elixir/Postgrex suite\n```\n\nFormat before committing: `cargo fmt`. Run `cargo clippy` where practical.","isInternal":false,"tokens":292,"sizeBytes":1181},{"name":"CLAUDE.md","path":"pgdog-config/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/pgdog-config/CLAUDE.md","title":"pgdog-config - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"Treat @AGENTS.md the same way you would CLAUDE.md\n","isInternal":false,"tokens":16,"sizeBytes":50},{"name":"CLAUDE.md","path":"pgdog/CLAUDE.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/pgdog/CLAUDE.md","title":"pgdog - Claude Agent Guidelines & System Prompt","category":"claude-rule","format":"markdown","content":"# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n","isInternal":false,"tokens":80,"sizeBytes":349},{"name":"README.md","path":"plugins/README.md","rawUrl":"https://raw.githubusercontent.com/pgdogdev/pgdog/HEAD/plugins/README.md","title":"plugins Documentation","category":"plugin-manifest","format":"markdown","content":"# PgDog plugins\n\nThis directory contains plugins that ship with PgDog and are built by original author(s) or by the community. You can use these as-is or modify them to your needs.\n\n## Plugins\n\n### `pgdog-example-plugin`\n\nExample plugin that can be used as reference by the community. It currently records\nwhen a write was made to a table and, for the next 5 seconds after the write, redirects\nall `SELECT` queries that touch table to the primary.\n\nIt's a simple workaround for Postgres replica lag, if you're using batch writes.\n","isInternal":false,"tokens":118,"sizeBytes":530}],"systemPromptSnippet":"<yakaai_skills repo=\"pgdogdev/pgdog\">\n<!-- File: AGENTS.md (Tokens: ~286 | Category: root-instruction) -->\nRead `CLAUDE.md` and `.claude/skills/rust/SKILL.md`.\n\n## Tool usage\n\nPrefer the dedicated Read, Grep, and Glob tools for file searching and reading. Bash is permitted as a fallback when dedicated tools can't accomplish the task, but excessive Bash tool calls for search/read operations will be denied.\n\n\n## Running tests\n\nUnit and integration tests use `cargo-nextest`:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a single test fails, run it directly by name to isolate the failure.\n\nIntegration tests live under `integration/<lang>/`. The harness is multi-language;\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`, `plugins`,\n`schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...) must be run\ndirectly via their own `run.sh`. All suites require a running Postgres instance\nconfigured by `bash integration/setup.sh`.\n\n```sh\nbash integration/run.sh          # python + ruby + java + sql\n```\n\nOr a specific suite:\n\n```sh\nbash integration/go/run.sh\n```\n\nAlways run `cargo fmt` before submitting changes. Run `cargo clippy` where practical.\n\n<!-- File: pgdog-config/AGENTS.md (Tokens: ~26 | Category: root-instruction) -->\n# pgdog-config\n\nFollow [CONTRIBUTING.md](CONTRIBUTING.md) for all changes in this directory.\n\n<!-- File: .claude/skills/bash/SKILL.md (Tokens: ~55 | Category: anthropic-skill) -->\n---\nname: bash\ndescription: How to use the shell successfully\nallowed-tools: Bash\n---\n\nExecute shell commands inside their own bash shell, like so:\n\n```bash\nbash -c 'command'\n```\n\nThis makes sure the shell is polluted by any outside state.\n\n<!-- File: .claude/skills/rust/SKILL.md (Tokens: ~1920 | Category: anthropic-skill) -->\n---\nname: rust\ndescription: Rust coding best practices for idiomatic, efficient, and maintainable code. Use when writing Rust code, reviewing code, or learning Rust patterns.\nallowed-tools: Read, Edit, Write, Bash, Grep, Glob, Task\n---\n\n# Rust Best Practices\n\nGuidelines for writing idiomatic, efficient, and maintainable Rust code.\n\n## Core Principles\n\n1. **Leverage the type system** - Make invalid states unrepresentable\n2. **Prefer compile-time checks** - Catch errors before runtime\n3. **Be explicit about ownership** - Don't fight the borrow checker\n4. **Write code that passes fmt/clippy first** - Not after fixing\n\n## Code health\n\n1. Prefer smaller files, refactor large files into multi-file modules\n2. Refactor large modules into several\n3. Prefer re-usable functions. Don't create separate functions if re-use is not planned.\n\n## Error Handling\n\nUse `thiserror`\n\n```rust\nuse thiserror::Error;\n\n#[derive(Error, Debug)]\npub enum ConfigError {\n    #[error(\"Failed to read config: {0}\")]\n    Io(#[from] std::io::Error),\n\n    #[error(\"Failed to parse config: {0}\")]\n    Parse(#[from] toml::de::Error),\n\n    #[error(\"Invalid configuration: {message}\")]\n    Invalid { message: String },\n}\n```\n\n### Never Use `.unwrap()`\n\n```rust\n// BAD\nlet value = map.get(\"key\").unwrap();\n\n// GOOD\nlet value = map.get(\"key\").ok_or_else(|| Error::MissingKey(\"key\"))?;\n\n// GOOD (when None is truly impossible)\nlet value = map.get(\"key\").expect(\"key always present after init\");\n```\n\n## Ownership & Borrowing\n\n### Prefer Borrowing Over Cloning\n\n```rust\n// BAD - unnecessary clone\nfn process(data: String) { ... }\nprocess(my_string.clone());\n\n// GOOD - borrow when possible\nfn process(data: &str) { ... }\nprocess(&my_string);\n```\n\n### Use `Cow` for Flexible Ownership\n\n```rust\nuse std::borrow::Cow;\n\nfn process(data: Cow<'_, str>) -> Cow<'_, str> {\n    if data.contains(\"bad\") {\n        Cow::Owned(data.replace(\"bad\", \"good\"))\n    } else {\n        data  // No allocation if unchanged\n    }\n}\n```\n\n### Return Owned Data from Constructors\n\n```rust\n// GOOD - clear ownership\nimpl User {\n    pub fn new(name: impl Into<String>) -> Self {\n        Self { name: name.into() }\n    }\n}\n```\n\n## API Design\n\n### Builder Pattern for Complex Configuration\n\n```rust\n#[derive(Default)]\npub struct ServerBuilder {\n    host: Option<String>,\n    port: Option<u16>,\n    timeout: Option<Duration>,\n}\n\nimpl ServerBuilder {\n    pub fn host(mut self, host: impl Into<String>) -> Self {\n        self.host = Some(host.into());\n        self\n    }\n\n    pub fn port(mut self, port: u16) -> Self {\n        self.port = Some(port);\n        self\n    }\n\n    pub fn build(self) -> Result<Server, ConfigError> {\n        Ok(Server {\n            host: self.host.unwrap_or_else(|| \"localhost\".into()),\n            port: self.port.ok_or(ConfigError::MissingPort)?,\n            timeout: self.timeout.unwrap_or(Duration::from_secs(30)),\n        })\n    }\n}\n```\n\n### Newtype Pattern for Type Safety\n\n```rust\n// BAD - easy to mix up\nfn transfer(from: i64, to: i64, amount: i64) { ... }\n\n// GOOD - compile-time safety\npub struct AccountId(i64);\npub struct Amount(i64);\n\nfn transfer(from: AccountId, to: AccountId, amount: Amount) { ... }\n```\n\n### Use `#[must_use]` for Important Returns\n\n```rust\n#[must_use]\npub fn validate(&self) -> Result<(), ValidationError> {\n    // ...\n}\n```\n\n## Collections & Iterators\n\n### Prefer Iterators Over Loops\n\n```rust\n// BAD\nlet mut results = Vec::new();\nfor item in items {\n    if item.is_valid() {\n        results.push(item.transform());\n    }\n}\n\n// GOOD\nlet results: Vec<_> = items\n    .into_iter()\n    .filter(|item| item.is_valid())\n    .map(|item| item.transform())\n    .collect();\n```\n\n### Use `collect()` Type Inference\n\n```rust\n// Collect into Vec\nlet vec: Vec<_> = iter.collect();\n\n// Collect into HashMap\nlet map: HashMap<_, _> = iter.collect();\n\n// Collect Results\nlet results: Result<Vec<_>, _> = iter.collect();\n```\n\n## Async Patterns\n\n### Use `tokio` for Async Runtime\n\n```rust\n#[tokio::main]\nasync fn main() -> Result<()> {\n    let result = fetch_data().await?;\n    Ok(())\n}\n```\n\n### Avoid Blocking in Async Code\n\n```rust\n// BAD - blocks the runtime\nasync fn bad() {\n    std::thread::sleep(Duration::from_secs(1));\n}\n\n// GOOD - async sleep\nasync fn good() {\n    tokio::time::sleep(Duration::from_secs(1)).await;\n}\n\n// GOOD - spawn blocking for CPU-intensive work\nasync fn compute() -> i32 {\n    tokio::task::spawn_blocking(|| expensive_computation()).await.unwrap()\n}\n```\n\n## Testing\n\n### Unit Tests in Same File\n\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n\n    #[test]\n    fn test_basic() {\n        assert_eq!(add(1, 2), 3);\n    }\n\n    #[test]\n    fn test_edge_case() {\n        assert!(validate(\"\").is_err());\n    }\n}\n```\n\n### Integration Tests in `tests/`\n\n```rust\n// tests/integration_test.rs\nuse my_crate::public_api;\n\n#[test]\nfn test_full_workflow() {\n    let result = public_api::process(\"input\");\n    assert!(result.is_ok());\n}\n```\n\n### Use `assert!` Macros Effectively\n\n```rust\nassert!(condition);\nassert_eq!(left, right);\nassert_ne!(left, right);\nassert!(result.is_ok());\nassert!(result.is_err());\nassert_matches!(value, Pattern::Variant { .. });\n```\n\n## Performance\n\n### Avoid Premature Allocation\n\n```rust\n// BAD - allocates even if not needed\nfn maybe_string() -> String {\n    String::from(\"default\")\n}\n\n// GOOD - return static str when possible\nfn maybe_string() -> &'static str {\n    \"default\"\n}\n```\n\n### Use `Vec::with_capacity` for Known Sizes\n\n```rust\n// BAD - multiple reallocations\nlet mut vec = Vec::new();\nfor i in 0..1000 {\n    vec.push(i);\n}\n\n// GOOD - single allocation\nlet mut vec = Vec::with_capacity(1000);\nfor i in 0..1000 {\n    vec.push(i);\n}\n```\n\n### Import instead of using absolute paths\n\n```rust\n/// BAD\nlet v = tokio::net::TcpStream::connect(\"localhost:8080\");\n\n/// GOOD\nuse tokio::net::TcpStream;\nlet v = TcpStream::connect(\"localhost:8080\");\n```\n\n### Profile Before Optimizing\n\n```bash\ncargo build --release\ncargo flamegraph  # requires cargo-flamegraph\n```\n\n## Module Organization\n\n### Keep Modules Focused\n\n```rust\n// src/lib.rs\npub mod config;\npub mod client;\npub mod error;\n\n// Re-export public API\npub use config::Config;\npub use client::Client;\npub use error::Error;\n```\n\n### Use `pub(crate)` for Internal APIs\n\n```rust\n// Public to crate, not external users\npub(crate) fn internal_helper() { ... }\n```\n\n## Documentation\n\n### Document Public APIs\n\n```rust\n/// Creates a new client with the given configuration.\n///\n/// # Arguments\n///\n/// * `config` - The client configuration\n///\n/// # Errors\n///\n/// Returns an error if the configuration is invalid.\n///\n/// # Examples\n///\n/// ```\n/// let client = Client::new(Config::default())?;\n/// ```\npub fn new(config: Config) -> Result<Self> {\n    // ...\n}\n```\n\n## Anti-Patterns to Avoid\n\n| Anti-Pattern | Better Approach |\n|--------------|-----------------|\n| `.unwrap()` everywhere | Use `?` operator |\n| `clone()` to satisfy borrow checker | Restructure ownership |\n| `String` parameters | Use `&str` or `impl Into<String>` |\n| Boolean parameters | Use enums |\n| Long function bodies | Extract to smaller functions |\n| Deep nesting | Use early returns |\n| Magic numbers | Use named constants |\n\n## Quick Reference\n\n```bash\n# Quality gates\ncargo fmt -- --check && cargo clippy -- -D warnings && cargo test\n\n# Common cargo commands\ncargo check           # Fast syntax/type check\ncargo build           # Debug build\ncargo build --release # Release build\ncargo nextest run     # Run tests\ncargo doc --open      # Generate and view docs\ncargo clippy --fix    # Auto-fix lint issues\n```\n\n<!-- File: CLAUDE.md (Tokens: ~292 | Category: claude-rule) -->\n# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n\n\n## Running tests\n\nUnit tests:\n\n```sh\ncargo nextest run --profile dev\n```\n\nIf a test fails, run it directly by name. Integration tests require Postgres configured via `bash integration/setup.sh` first.\n\nThe integration harness is multi-language: each suite lives in `integration/<lang>/`.\n`integration/run.sh` only dispatches the `python`, `ruby`, `java`, and `sql` suites.\nOther suites (`go`, `elixir`, `rust`, `dry_run`, `pgbench`, `toxi`, `two_pc`,\n`plugins`, `schema_sync`, `complex`, `mirror`, `load_balancer`, `copy_data`, ...)\nmust be run directly via their own `run.sh`.\n\n```sh\nbash integration/run.sh           # python + ruby + java + sql\nbash integration/go/run.sh        # Go suite\nbash integration/elixir/run.sh    # Elixir/Postgrex suite\n```\n\nFormat before committing: `cargo fmt`. Run `cargo clippy` where practical.\n\n<!-- File: pgdog-config/CLAUDE.md (Tokens: ~16 | Category: claude-rule) -->\nTreat @AGENTS.md the same way you would CLAUDE.md\n\n<!-- File: pgdog/CLAUDE.md (Tokens: ~80 | Category: claude-rule) -->\n# About the project\n\nPgDog is a connection pooler, load balancer and database sharder for PostgreSQL. It's written in async Rust. It implements the PostgreSQL network protocol: applications connect to PgDog, PgDog connects to Postgres, and neither know there is a proxy in between.\n\n## Workflow\n\nLoad the `/rust` skill. Don't follow C/C++/Go norms.\n\n<!-- File: plugins/README.md (Tokens: ~118 | Category: plugin-manifest) -->\n# PgDog plugins\n\nThis directory contains plugins that ship with PgDog and are built by original author(s) or by the community. You can use these as-is or modify them to your needs.\n\n## Plugins\n\n### `pgdog-example-plugin`\n\nExample plugin that can be used as reference by the community. It currently records\nwhen a write was made to a table and, for the next 5 seconds after the write, redirects\nall `SELECT` queries that touch table to the primary.\n\nIt's a simple workaround for Postgres replica lag, if you're using batch writes.\n</yakaai_skills>"}