~kris/hacks

sframe

ref: 02a1b32f6354d21c58f4d2bd92c608b2ec120336 sframe/.claude/CLAUDE.md -rw-r--r-- 3.5 KiB
02a1b32f — Kris Yotam Add README 6 months ago

#sframe — CLAUDE.md

#Project

sframe (Simple Frame) is a lightweight command-line tool written in C following the suckless philosophy. It extracts unique frames from video files for research purposes, using perceptual hashing to eliminate duplicates and embedding timestamps in filenames.

#Coding Standards — Suckless C Style

All code in this project MUST follow the suckless.org coding style:

#Language

  • C99 (ISO/IEC 9899:1999), no extensions
  • POSIX.1-2008 (_POSIX_C_SOURCE 200809L)

#Indentation & Whitespace

  • Tabs for indentation (1 tab = 1 level)
  • Spaces for alignment only, never for indentation
  • No tabs except at the beginning of a line
  • Maximum line length: 79 characters

#Comments

  • Use /* */ only, never //
  • Comment fallthrough cases in switch statements

#Variables

  • All declarations at the top of the block
  • Pointer * adjacent to variable name: char *p, not char* p
  • No C99 bool; use int (0/1)
  • Global/static variables not used outside TU must be static

#Functions

  • Return type on its own line
  • Function name at column 0 on next line (enables grep ^funcname)
  • Opening { on its own line for functions
  • Functions not used outside their file: static
static void
usage(void)
{
	fprintf(stderr, "usage: sframe [-t thresh] [-f fmt] video\n");
	exit(1);
}

#Braces

  • Opening { on same line for control flow (if, for, while, switch)
  • Closing } on its own line unless continuing (else, do-while)
  • Use braces even for single statements when sibling branches use them

#Naming

  • lowercase_with_underscores for functions and variables
  • UPPERCASE for macros and constants
  • CamelCase for typedef'd struct types
  • No _t suffix (reserved by POSIX)
  • Prefix module functions: dec_open(), diff_hash(), util_die()

#Control Flow

  • Space after if, for, while, switch
  • No space after ( or before )
  • Use goto for cleanup/unwind, not nested ifs
  • Return/exit early on failure
  • Test against 0, not -1: if (func() < 0)

#Error Handling

  • All allocation checked; goto cleanup on failure
  • die() for fatal errors (prints message, exits)
  • warn() for recoverable errors (prints, continues)

#File Organization Order

  1. License header
  2. System includes (alphabetical)
  3. Local includes
  4. Macros
  5. Type definitions
  6. Function declarations
  7. Global variables
  8. Function definitions (same order as declarations)

#Headers

  • System headers first, alphabetical
  • Local headers after blank line
  • No cyclic dependencies
  • Include only what is needed

#Architecture Rules

  • No global mutable state. Pass context structs explicitly.
  • No system() calls. Use fork()/execvp() or popen().
  • No hardcoded paths except sensible defaults (~/frames).
  • Separate compilation. Every .c file compiles independently.

#Module Prefixes

Module Prefix File
Main/CLI main.c
Decode dec_ decode.c
Diff diff_ diff.c
Utilities die(), warn(), ecalloc() util.c

#Build

make        # build sframe binary
make clean  # remove build artifacts
make install PREFIX=/usr/local  # install

#Dependencies

  • FFmpeg libraries: libavformat, libavcodec, libavutil, libswscale

#Git Conventions

  • No Co-Authored-By: Claude lines
  • Commit messages: imperative, <72 chars, no period
  • One logical change per commit

#CRITICAL: No Building on Moirai

NEVER run make, sudo make install, or any build command unless Kris explicitly says "build" in his message.