Files
immich-sdk/AGENTS.md
Joakim Hulthe 2e7db3b35a Add integration testing infrastructure with Podman Compose
- Add docker/podman-compose.yml for Immich server (no ML)
- Add test-data/sample-photos/ with 3 public domain images
- Add scripts/start-immich.sh for container startup + admin/API key creation
- Add scripts/seed-data.sh for uploading test photos and creating albums
- Add scripts/stop-immich.sh for cleanup with volume destruction
- Add scripts/run-example.sh wrapper (fixed env var export)
- Update examples to use IMMICH_URL and IMMICH_API_KEY env vars
- Add .github/workflows/integration-test.yml for CI
- Update assets.list() to use /search/metadata endpoint
- Update AGENTS.md with example running instructions
- Add 5 new examples: search_metadata, album_management, timeline_browsing,
  delete_assets, server_info
2026-04-14 20:13:30 +00:00

4.7 KiB

Agent Instructions for immich-sdk

Build & Test Commands

Quick Checks:

cargo check                    # Fast compilation check
cargo clippy                   # Run linter
cargo fmt                      # Format code
cargo test                     # Run all tests
cargo test <test_name>         # Run single test (e.g., cargo test test_client_creation)

Full verification before commit:

cargo check && cargo clippy && cargo test && cargo fmt

Running Examples

All examples should be run using the provided wrapper script:

./scripts/run-example.sh <example_name>

Available examples:

./scripts/run-example.sh basic_usage
./scripts/run-example.sh upload_photos
./scripts/run-example.sh download_asset
./scripts/run-example.sh thumbnail

The wrapper handles everything automatically:

  • Starts Immich containers (if not running)
  • Creates admin user and API key
  • Seeds test data (photos, albums)
  • Loads credentials
  • Runs the example

When adding new examples:

  1. Read IMMICH_URL and IMMICH_API_KEY from environment variables
  2. Test with: ./scripts/run-example.sh <name>
  3. Verify it works with the seeded test data (3 photos, 1 album)

Code Style Guidelines

Imports

  • Group by: std, external crates, internal modules (crate::)
  • Use use crate:: for internal modules, not relative paths
  • Example:
    use std::path::Path;
    use std::sync::Arc;
    
    use crate::{
        Client,
        error::{ImmichError, Result},
        models::AssetId,
    };
    

Types & Naming

  • Prefer using newtypes or type aliases instead of Strings or integers For example: AssetId (Uuid alias), not String for asset IDs
  • Model types: PascalCase with Response or Request suffix
  • Enum variants: Use serde rename_all attributes for API compatibility
  • Builders: FooBuilder for constructing Foo operations
  • Type aliases for IDs: pub type AssetId = uuid::Uuid;

Error Handling

  • Use crate::error::Result<T> alias
  • Use thiserror for error enums
  • Prefer ImmichError::Validation(String) for user input errors
  • Convert external errors: #[from] reqwest::Error

API Design Patterns

  • Builder pattern: All API operations use builders
    client.assets().upload().file("path").execute().await?;
    
  • Cheap cloning: Client wraps data in Arc<ClientInner>
  • API modules take Client by value
  • Store Client in builders, not references

OpenAPI

Refer to openapi-spec.yaml for documentation regarding immich API. Note that some type definitions in this file are incorrect with regards to nullability. The file is big, so prefer to use nushell to query the things you need:

# List all api paths
open openapi-spec.yaml | get paths | transpose key val | get key

# Read the details about a particular path
open openapi-spec.yaml | get paths.'/workflows' | to yaml

Documentation

  • All public items must have doc comments
  • Module-level docs explaining purpose
  • Example code in docs should compile (use no_run or ignore if needed)
  • Include # Errors section for fallible methods

Rust Edition Features

  • Edition 2024 (use latest idioms)
  • Minimum Rust version: 1.85
  • Use const fn where possible
  • Prefer impl Into<String> for string parameters iff the function requires ownership of the String

Project Structure

src/
  lib.rs          # Re-exports, module declarations
  client.rs       # Client struct with Arc<ClientInner>
  error.rs        # Error types with thiserror
  models/         # Data models, types
  apis/           # API modules (albums, assets, etc.)
examples/         # Usage examples
tests/            # Integration tests

Lint Configuration

From Cargo.toml - DO NOT SUPPRESS THESE:

  • unused_async = "deny" - No async fn without await
  • wildcard_dependencies = "deny" - No wildcard deps
  • non_ascii_idents = "forbid" - ASCII only
  • rust_2018_idioms = "deny" - Modern Rust idioms

Agile agentic workflow

  • You are responsible for high-level architecture.
  • You may (and should) read code to understand the architecture.
  • You should AVOID doing implementation work and testing. Use the task tool to spawn subagents for this.
  • You should also use the task tool to spawn subagents to for code review.
  • Prefer splitting subagent-tasks into small incremental bits of work.
  • Subagents must NEVER exit with compilation errors, but warnings due to stubbed implementations (todo!()) are fine.

Never Do

  • Never use unsafe without asking first
  • Never ignore clippy warnings (fix them)
  • Never suppress warnings with #[allow(...)]
  • Never use panic! or unwrap() in library code
  • Never break the builder pattern chain
  • Never write pointless tests to simply get more code coverage