diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..aa1da645 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,19 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +See [CONTRIBUTING.md](CONTRIBUTING.md) for build commands, testing, code style, and development workflow. + +## Workspace Structure + +- **ldk-server** - Main daemon server (entry point: `src/main.rs`) +- **ldk-server-cli** - CLI client using clap +- **ldk-server-client** - Reqwest-based client library +- **ldk-server-protos** - Protocol buffer definitions and generated Rust code + +## Development Rules + +- Always ensure tests pass and lints are fixed before committing +- Run `cargo fmt --all` after every code change +- Never add new dependencies unless explicitly requested +- Please always disclose the use of any AI tools in commit messages and PR descriptions diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..9a783dfb --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,65 @@ +# Contributing to LDK Server + +Contributions are welcome and encouraged! Whether you're fixing bugs, adding features, improving documentation, or +helping with testing, we appreciate your help! + +## Building + +```bash +cargo build # Build all crates +cargo build --release # Production build (LTO enabled) +``` + +## Running + +```bash +cargo run --bin ldk-server ./ldk-server/ldk-server-config.toml +``` + +## Testing + +```bash +cargo test # Run all tests +cargo test --all-features # Run tests with all features +``` + +## Code Quality + +```bash +cargo fmt --all # Format code +cargo fmt --all -- --check # Check formatting +cargo clippy --all-features -- -D warnings -A clippy::drop_non_drop # Lint (CI uses this on MSRV) +``` + +## Code Style + +- MSRV: Rust 1.85.0 +- Hard tabs, max width 100 chars +- Imports grouped: std, external crates, local crates + +## Protocol Buffer Generation + +```bash +RUSTFLAGS="--cfg genproto" cargo build -p ldk-server-protos +cargo fmt --all +``` + +## Adding a New API Endpoint + +1. Define request/response messages in `ldk-server-protos/src/proto/api.proto` +2. Regenerate protos (see above) +3. Create handler in `ldk-server/src/api/` (follow existing patterns) +4. Add route in `ldk-server/src/service.rs` +5. Add CLI command in `ldk-server-cli/src/main.rs` + +## Configuration + +- Config template with all options: `ldk-server/ldk-server-config.toml` +- When updating config options, also update the tests in `ldk-server/src/util/config.rs` + +## Before Submitting + +- Ensure all tests pass +- Ensure all lints are fixed +- Run `cargo fmt --all` +- Please disclose the use of any AI tools in commit messages and PR descriptions diff --git a/README.md b/README.md index 8497da57..10f0c609 100644 --- a/README.md +++ b/README.md @@ -70,3 +70,7 @@ eval "$(ldk-server-cli completions zsh)" # Fish (add to ~/.config/fish/config.fish) ldk-server-cli completions fish | source ``` + +## Contributing + +Contributions are welcome! Please see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines on building, testing, code style, and development workflow. diff --git a/ldk-server-protos/build.rs b/ldk-server-protos/build.rs index 32b9f6b0..35066fc7 100644 --- a/ldk-server-protos/build.rs +++ b/ldk-server-protos/build.rs @@ -11,7 +11,20 @@ extern crate prost_build; #[cfg(genproto)] -use std::{env, fs, path::Path}; +use std::{env, fs, io::Write, path::Path}; + +#[cfg(genproto)] +const COPYRIGHT_HEADER: &str = + "// This file is Copyright its original authors, visible in version control +// history. +// +// This file is licensed under the Apache License, Version 2.0 or the MIT license +// , at your option. +// You may not use this file except in accordance with one or both of these +// licenses. + +"; /// To generate updated proto objects, run `RUSTFLAGS="--cfg genproto" cargo build` fn main() { @@ -38,13 +51,13 @@ fn generate_protos() { &["src/proto/"], ) .expect("protobuf compilation failed"); - println!("OUT_DIR: {}", &env::var("OUT_DIR").unwrap()); - let from_path = Path::new(&env::var("OUT_DIR").unwrap()).join("api.rs"); - fs::copy(from_path, "src/api.rs").unwrap(); - let from_path = Path::new(&env::var("OUT_DIR").unwrap()).join("types.rs"); - fs::copy(from_path, "src/types.rs").unwrap(); - let from_path = Path::new(&env::var("OUT_DIR").unwrap()).join("events.rs"); - fs::copy(from_path, "src/events.rs").unwrap(); - let from_path = Path::new(&env::var("OUT_DIR").unwrap()).join("error.rs"); - fs::copy(from_path, "src/error.rs").unwrap(); + let out_dir = env::var("OUT_DIR").unwrap(); + println!("OUT_DIR: {}", &out_dir); + for file in &["api.rs", "types.rs", "events.rs", "error.rs"] { + let from_path = Path::new(&out_dir).join(file); + let content = fs::read(&from_path).unwrap(); + let mut dest = fs::File::create(Path::new("src").join(file)).unwrap(); + dest.write_all(COPYRIGHT_HEADER.as_bytes()).unwrap(); + dest.write_all(&content).unwrap(); + } }