π€ Agents
π Table of Contents
- π€ Agents
SDLC (Software Development Lifecycle)
Planning
Analysis
Design
Development
Testing
Unit Tests
Integration Tests
Review
π Coding Convention
Explicit types > Implicitβ TypeScript types, Rust type annotations, Python type hints. AI agents rely heavily on type information to understand what values flow where. A function signature tells us more than 100 lines of body.Flat over deeply nestedβ Shallow directory trees, short functions, minimal indentation. Deeply nested code (callback hell, 5-level if pyramids) exceeds context windows faster and is harder to trace.Self-documenting identifiersβgetUserById(id)needs no comment;processData(x)needs one. Names that describe what and why (not how) are best.Don't repeat yourself (DRY)β When the same pattern appears 15 times across files, an AI will sometimes handle 14 of them and miss the 15th. Centralizing logic prevents that.Small, focused filesβ A file with one clear responsibility is easier to read fully, edit precisely, and reason about within context limits.- Functions: β€ 30 lines. An AI's effective reasoning degrades past ~2000 tokens (~60 lines). A 30-line cap halves that, keeping the full function visible in context alongside its callers. If you need to scroll to see the whole function, it's too long.
- Files: β€ 200 lines. Files longer than 200 lines force the AI to work at the edge of its attention window, making it harder to trace data flow between distant sections. If you need to search within a file to find where a variable is defined, the file is too long.
Explicit error handlingβif (err) return Err(...)rather than letting failures silently propagate. AI agents need to see error paths to handle them correctlyTest names as documentationβtest("returns 404 when user not found")tells us the expected behavior faster than reading the implementation.Consistent import/module structureβ Group imports by origin (stdlib, third-party, internal). AI agents infer dependency graphs from import blocks without scanningrequire/importcalls scattered across files.Prefer pure functions with explicit dependenciesβ Accept all inputs as parameters and return all outputs. AI agents reason about data flow without tracking hidden state or global mutation.- No global/singleton state: Dependencies passed explicitly are visible
at the call site. AI agents trace wiring without searching
init()or service locators. - Return values over side effects: Functions that mutate arguments or globals hide their impact. AI agents trust return values as the single source of truth.
- No global/singleton state: Dependencies passed explicitly are visible
at the call site. AI agents trace wiring without searching
Use conventional project layoutsβ Follow community-standard directory structures (src/,cmd/,internal/,tests/). AI agents locate files by convention rather than scanning build configs.
π Bash
- Use
set -euo pipefailat the start of every script β Catches errors early, undefined variables, and pipe failures. AI agents see the safety contract from the first line instead of guessing error handling. - Prefer
[[ ]]over[ ]for conditionals β[[ ]]avoids word splitting and has fewer surprises. AI agents parse the more reliable syntax without reasoning about edge cases. - Use
$(...)over backticks for command substitution β Backticks nest poorly and are visually ambiguous. AI agents see the intent clearly from the$()delimiters. - Quote all variable expansions β
"$var"and"${array[@]}"prevent word splitting and globbing. AI agents trust that filenames with spaces won't break the logic. - Use
localin function-scoped variables β Prevents leaking state between functions. AI agents reason about variable scope from the declaration keyword. - Prefer
printfoverechoβprintfis consistent across platforms and supports format strings. AI agents see the exact output format without scanning forechoflags. - Use
read -rfor parsing input β-rprevents backslash interpretation. AI agents trust that input won't be accidentally mangled. - Handle errors with
trapβtrap cleanup EXIT ERRensures cleanup on failure. AI agents see teardown logic in one place rather than checking exit points. - Prefer
mapfile/readarrayfor reading files into arrays β Avoidswhile readsubshell pitfalls. AI agents see the full data captured without tracking pipeline scoping. - Use
shellcheckas a lint gate β Runshellcheckin CI with--severity=style. AI agents produce fewer shellcheck warnings when rules are standardised.
π· Go (.go)
- Use
erroras the last return value β Functions that can fail should returnerroras the final return value. AI agents infer failure paths from signatures. - Handle errors explicitly, never ignore β Check every error return. Use
if err != nil { return ... }rather than\_ =. Never usemust-style panics outsideinit/main. - Prefer
varzero-initialization over:=for zero values βvar s stringis clearer thans := "". Use:=only when the value is non-zero or the type is inferred from a non-trivial expression. - Use
context.Contextas the first parameter β Passctxas the first arg in functions that do I/O, blocking calls, or propagate deadlines/cancellation. - Avoid global state β Pass dependencies explicitly via struct fields or
function parameters rather than using
init()or package-level vars. Makes testing and reasoning easier. - Favour
go fmtcompliance β Always rungo fmtbefore committing. Consistent formatting reduces noise for AI agents reading diffs. - Prefer table-driven tests β Use
tests []struct{...}slices witht.Runfor testing multiple cases. Improves readability and coverage visibility. - Use
net/httpmiddleware pattern β Compose handlers withfunc(next http.Handler) http.Handlerfor clean separation of concerns (logging, auth, tracing). - Prefer
syncprimitives over channels for state β Usesync.Mutex/sync.RWMutexfor protecting shared state; use channels for communication/coordination. - Return early, avoid deep nesting β Guard clauses
(
if err != nil { return }) keep the happy path flat and readable.
π¦Ύ cobra.go
- Use
RunEoverRunfor commands βRunEreturns an error that Cobra prints and exits with code 1. AI agents see failure paths in the signature instead of guessing fromRun's void return. - Nest subcommands via
AddCommandβrootCmd.AddCommand(subCmd)builds a parent-child tree. AI agents infer CLI structure from command registration without parsing help strings. - Use persistent flags for shared options β
rootCmd.PersistentFlags().StringVarP(...)propagates to all subcommands. Avoid duplicating flag definitions across commands that share them. - Prefer required args over manual checks β Use
Args: cobra.ExactArgs(1)instead ofif len(args) == 0 { ... }. AI agents see the contract from the struct field rather than scanning for runtime guards. - Keep
RunEfunctions thin β Delegate to business logic in a separate function/service. ARunEbody over ~10 lines is a sign the command has too much responsibility. - Use
ValidArgs+Args: cobra.OnlyValidArgsfor closed sets β Provides shell completion and validation in one place. AI agents see valid inputs as data, not conditional logic. - Register
completioncommand ininit()βrootCmd.AddCommand(cmd.GenCompletionCmd("completion", true))ships shell completion. AI agents can discover the command tree programmatically. - Use
PreRunEfor shared setup β Validate flags or establish connections inPreRunEbeforeRunEexecutes. AI agents trace lifecycle phases by name instead of scanning for setup blocks. - Favour
StringVarP/IntVarPwith short flags β--verbose, -vbinds a flag to a variable at init time. AI agents see both long and short forms in one call instead of separate declarations. - Group commands with
cmd.Groupsin v2 β Organize subcommands into logical groups for--helpoutput. AI agents parse the group structure to understand command relationships.
π£ Kotlin (.kt)
- Prefer
valovervarβ Use immutablevalby default; only usevarwhen mutation is necessary. Immutability makes data flow easier for AI agents to trace. - Use
data classfor model objects β They getequals(),hashCode(),toString(),copy(), and destructuring for free, which reduces boilerplate and improves clarity. - Use
sealed class/sealed interfacefor restricted hierarchies β Encodes exhaustive when-branches at compile time. AI agents can reason about all possible states without scanning runtime checks. - Prefer extension functions over utility classes β
fun String.isEmail(): Booleanis discoverable and composable. Avoid static-heavyStringUtils-style helpers. - Use
Flowfor reactive streams, notChannelβFlowis cold, structured-concurrent, and testable withkotlinx.coroutines.test. UseChannelonly for hot streams or bridging callback-based APIs. - Favour
whenover nestedif/elseβwhenis exhaustive (with sealed classes), reads linearly, and has no accidental fall-through. AI agents parse it more reliably than deeply nested conditionals. - Use
require()andcheck()for preconditions βrequire(amount > 0)at function entry signals invariants explicitly. AI agents see the contract without reading test code. - Prefer constructor injection with
bydelegation βclass Service(repo: Repository by RepoImpl())makes dependencies explicit while delegating implementation. Avoid reflection-heavy DI frameworks where possible. - Keep coroutine scopes explicit β Pass
coroutineScopeorviewModelScoperather than usingGlobalScope. Structured concurrency lets AI agents reason about lifecycle and cancellation. - Use
buildList,buildMap,buildStringbuilders β They optimize memory and make construction intent obvious. Prefer them over mutable accumulators that scatter reads/writes.
β¨οΈ cli.kt
- Use
data classfor command arguments βdata class Config(val name: String by argument())bundles CLI parameters into typed objects. AI agents see the full input schema without parsing help text. - Prefer
subcommandsover manual dispatch βsubcommands(Start, Stop)registers a subcommand tree. AI agents infer command hierarchy from the declaration instead of scanningwhenblocks. - Use
option()with--helpdescriptions βval verbose by option("--verbose", help = "Enable verbose output"). Self-documenting options let AI agents understand intent without reading downstream usage. - Use
int(),long(),double()for typed options βval port by int().default(8080)enforces types at the boundary. AI agents infer the expected type from the parser chain. - Prefer
group()for mutually exclusive options βgroup { "format" { "json" } "yaml" }encodes exclusivity in the DSL. AI agents see the constraint without tracing runtime validation. - Use
require()for preconditions βrequire(name.isNotBlank())inrunfails fast with user-friendly messages. AI agents see invariants as assertions, not buried logic. - Keep
runthin β Delegate to business logic after parsing. Arunbody over ~10 lines suggests the command mixes parsing with domain logic. - Use
envvarfor sensitive defaults βval token by option().envvar("API_TOKEN")reads from environment. AI agents see the config source without guessing fallback chains. - Prefer
confirmation()for destructive actions βconfirmation("Are you sure?")adds a safety prompt. AI agents infer which commands are destructive from the confirmation call. - Use
VersionOptionfor version flags βversionOption("1.0.0")generates--versionconsistently. AI agents discover the version contract from a single call instead of scanning for println.
β‘ Ktor
- Use
installfor plugins βinstall(ContentNegotiation)registers serialization, compression, auth, etc. AI agents infer feature configuration frominstallcalls without tracing plugin internals. - Prefer
routedserver overembeddedServerwith raw handlers βrouted { get("/") { ... } }creates a structured routing tree. AI agents parse endpoint hierarchy from route declarations. - Use
StatusPagesfor error handling βinstall(StatusPages) { exception { ... } }centralizes error responses. AI agents see all error mappings in one block instead of scattered try/catch. - Type-safe routes with
Routeextensions βfun Route.userRoutes()groups related endpoints into self-contained extensions. AI agents locate route groups by function name without navigating module trees. - Use
call.receive<T>()for request body parsing β Infers the type from the generic, leveragingContentNegotiation. AI agents see the expected schema at the call site without manual deserialization. - Prefer
call.respond(T)over explicit response building β Returns typed objects that Ktor serialises automatically. AI agents read the response contract from the type argument. - Use
locationsfor typed routing β@Location("/user/{id}")generates type-safe route references. AI agents see link relationships as data, not string concatenation. - Keep
Application.moduleminimal β Register plugins, then reference route modules in a singleroutedcall. AI agents trace the app structure from the entry point without scanning for scattered registrations. - Use
application.logoverprintlnβ Structured logging with configurable levels. AI agents infer observability from the logger API rather than guessing from stdout noise. - Test with
testApplication+TestHostBuilderβtestApplication { client.get("/") }validates endpoints without a running server. AI agents see test setup as declarative configuration, not infrastructure orchestration.
π± Compose
- Use
@Composablefor UI components β Declare UI with the@Composableannotation. AI agents see UI boundaries from the annotation. - Prefer
Column,Row,Boxfor layout β Compose layouts with declarative containers instead of XML. AI agents read hierarchy from composable nesting. - Use
rememberfor local state β Scopes state to composition lifecycle. AI agents trace state initialisation fromremembercalls. - Use
LaunchedEffectfor side effects βLaunchedEffect(key) { ... }runs coroutines scoped to composition. AI agents see lifecycle-aware effects from the key parameter. - Use
StateandMutableStatefor reactivity β Compose re-renders when state reads change. AI agents infer reactive boundaries from state references. - Use
Modifierfor styling and interaction β Chain.padding(),.clickable {},.background()onModifier. AI agents read the full styling pipeline from one chain. - Use
MaterialThemefor theming β Define colours, typography, and shapes centrally. AI agents infer design tokens fromMaterialThemereferences. - Use
NavHostfor navigation βNavHost(navController, startDestination = ...)declares the nav graph. AI agents infer screen flow from the navigation structure. - Use
ViewModelwithcollectAsState()β ViewModels survive config changes;collectAsState()bridges to Compose. AI agents trace data flow from ViewModel to UI through state. - Use
@Previewfor previsualisation β Annotate composables with@Previewfor IDE rendering. AI agents see component isolation from preview annotations.
π Python (.py)
- Use type hints for all function signatures β
def get_user(id: int) -> User:tells an AI agent the contract without reading the body. Runmypyorpyrightin CI. - Prefer
dataclassesover manual__init__β@dataclassauto-generates__init__,__repr__,__eq__, and__hash__. Reduces boilerplate and makes data shapes transparent. - Use
Pathoveros.pathβpathlib.Pathis composable, readable, and cross-platform. AI agents infer file operations more easily from.read_text()than fromopen()+ context managers. - Prefer
typing.Protocolfor duck types βProtocoldefines structural subtypes explicitly. AI agents can check interface conformance without hunting through MROs. - Use
Enumover string constants βclass Status(Enum): ACTIVE = "active"prevents typos and enables exhaustive checks. AI agents see a closed set of values rather than magic strings. - Favour
try/exceptnarrowly β Catch specific exception types and minimise the guarded block. Broadexcept Exceptionhides failure paths from AI agents. - Use
__future__annotations βfrom __future__ import annotationsmakes all hints lazy (PEP 563/649). Avoids circular imports and lets AI agents read types without evaluating them. - Prefer generators over lists for large sequences β
yielditems one at a time rather than building entire lists in memory. AI agents reason about streaming without tracking buffer size. - Use
typing.Unionor|syntax for optional types βstr | Noneis clearer thanOptional[str]and consistent with other modern languages. AI agents parse|unions reliably. - Keep
__init__.pyminimal or empty β Avoid import-time side effects. AI agents reason about module boundaries cleanly when init files are transparent.
πΌ pandas
- Use
query()over boolean indexing βdf.query("age > 30")is more readable and avoids repeateddf[...]brackets. AI agents parse the expression string as a self-contained filter. - Prefer
loc[]/iloc[]over chained indexing βdf.loc[df["age"] > 30, ["name", "age"]]is a single operation. Chained indexing can produce unpredictable copies, confusing AI agents tracing side effects. - Use
agg()for multiple aggregations βdf.groupby("city").agg({"price": ["mean", "std"], "qty": "sum"})names outputs explicitly. AI agents see the full aggregation schema in one call. - Favour
merge()overjoin()βpd.merge(df1, df2, on="id", how="left")is explicit about keys and join type. AI agents infer the join contract from parameters rather than index assumptions. - Use
apply()sparingly β Vectorised operations (df["a"] + df["b"]) are faster and clearer thandf.apply(lambda row: ...). AI agents trace element-wise operations more easily through column expressions. - Prefer
to_datetime()for date handling βpd.to_datetime(df["date"])parses and standardises timestamps. AI agents trust that comparisons and resampling work correctly. - Use
value_counts()for categorical summaries βdf["status"].value_counts(normalize=True)returns proportions or counts in one call. AI agents read distribution summaries without scanning groupby chains. - Use
fillna()with explicit values βdf.fillna({"age": df["age"].median(), "name": "unknown"})documents default choices per column. AI agents see imputation strategy as data rather than guesswork. - Prefer
pd.Categoricalfor ordered categories βpd.Categorical(df["size"], categories=["S", "M", "L"], ordered=True)encodes sort order. AI agents infer ordinal relationships without custom mapping logic. - Use
assign()for derived columns βdf.assign(bmi=lambda d: d["weight"] / d["height"] ** 2)chains transformations without mutating the original. AI agents trace data lineage through consecutiveassigncalls.
π¦ Rust (.rs)
- Use
Result<T, E>for fallible functions, neverpanic!βResultencodes failure in the type system. AI agents see which paths can fail from the signature alone. - Prefer
Option<T>over sentinel values β UseOptioninstead of-1,null, or empty strings for absent values. The type system forces the caller to handle both cases. - Use
impl Traitin argument positions βfn process(items: impl Iterator<Item = u8>)accepts any matching type without boxing. AI agents infer the trait bound without reading turbofish gymnastics. - Prefer
matchoverif letchains βmatchis exhaustive and compiler-verified. AI agents see every branch explicitly rather than deducing missed cases from context. - Use
thiserror/anyhowfor error handling βthiserrorfor libraries (custom error types),anyhowfor applications (opaque errors). Both producestd::error::Errortypes that AI agents can follow. - Favour iterators over indexed loops β
items.iter().filter_map(|x| x.to_owned())expresses intent without indexing logic. AI agents read the pipeline rather than simulating loop state. - Use
#[derive(Debug, Clone, PartialEq)]liberally β These traits enable logging, copying, and comparison. AI agents assume structs have these traits unless told otherwise. - Prefer
&strover&Stringin function params β&straccepts both&Stringand&strslices. More flexible and avoids accidental cloning. AI agents infer this from the parameter type. - Use
clippyas a lint gate β Runcargo clippyin CI with--deny warnings. Consistent lint rules let AI agents focus on logic rather than style variations. - Keep
unsafein small, audited blocks β Encapsulateunsafein safe abstractions with minimal surface area. Document safety invariants in// SAFETY:comments so AI agents can verify them.
π clap.rs
- Use
deriveAPI over builder API β#[derive(Parser)]generates argument parsing from struct fields. AI agents see the full CLI schema as type annotations instead of scanning builder chains. - Use
#[command()]for metadata β#[command(name = "app", version = "1.0")]documents the CLI in one place. AI agents discover command metadata without running--help. - Use
#[arg()]for per-field config β#[arg(short, long, default_value = "8080")]colocates flag config with the field. AI agents see all properties in a single attribute. - Prefer
ValueEnumover manual parsing β#[derive(ValueEnum)] enum Mode { Fast, Slow }generates parser and completion. AI agents see valid enum variants without matching strings. - Use
Subcommandenum for nested commands β#[derive(Subcommand)] enum Command { Start(StartArgs), Stop }encodes the command tree as types. AI agents infer hierarchy from enum variants. - Use
default_valueinstead ofOption<T>for optional flags β#[arg(default_value = "80")]documents the fallback at compile time. AI agents see defaults as data, not runtime logic. - Use
conflicts_withandrequiresfor arg relationships β#[arg(conflicts_with = "daemon")]encodes exclusivity declaratively. AI agents infer constraints from attributes rather than validation code. - Use
envfor environment variable fallback β#[arg(env = "PORT")]reads from env when flag is absent. AI agents see the config source without guessing lookup order. - Use
hide(true)for internal args β#[arg(hide = true)]excludes debug/internal flags from help. AI agents focus on user-facing API without noise from implementation details. - Prefer
colorandstylesfor rich output βcli.style.set_color(true)enables coloured help. AI agents infer that UX polish exists without searching for formatting calls.
Back to Table of Table of Contents
π axum
- Use
Router::new()with.route()for all API endpoints β Declare routes by chaining.route("/path", method_handler)on aRouter. AI agents infer the full routing tree from the builder chain instead of scanning for macro invocations. - Use extractors in handler signatures β
State,Path,Query,Jsonas function parameters declare dependencies explicitly. AI agents see what a handler needs (DB, URL params, body) from its signature alone. - Prefer
impl IntoResponsereturn types β ReturnJson<T>,StatusCode, or(StatusCode, Json<T>)tuples rather than buildingResponsemanually. AI agents infer response shape from the return type. - Use
with_state()for shared application state β PassArc<AppState>via.with_state()and extract it withState<Arc<AppState>>. AI agents trace dependency injection from the router setup to each handler. - Use
.layer()for middleware β Apply middleware (auth, logging, rate-limit) via.layer(middleware_layer). AI agents see the middleware stack as a linear chain rather than nested wrappers. - Use
.merge()to compose sub-routers β Break large route tables intoRouter::new().merge(sub_router)calls. AI agents locate related endpoints by following merge boundaries. - Use
axum::servewith graceful shutdown βaxum::serve(listener, app).with_graceful_shutdown(signal)for clean teardown. AI agents see the full server lifecycle in one call instead of scattered tokio spawns. - Use
tokio::select!for concurrent concerns β Handle shutdown signals and other concurrent tasks withtokio::select!rather than manual channel coordination. AI agents trace branching from the macro. - Use
tower::ServiceBuilderfor layered middleware β Composetower::ServiceBuilder::new().layer(A).layer(B).into_service()instead of nesting.layer()calls. AI agents read middleware composition as a flat list. - Prefer
thiserrorfor error types returned from handlers β Defineenum ApiErrorwith#[derive(thiserror::Error)]and implementIntoResponse. AI agents see all error variants and their HTTP mappings in one place.
π₯οΈ Tauri
- Use
tauri::Builderfor app configuration β Chain.plugin(),.invoke_handler(),.setup()ontauri::Builder::default(). AI agents trace the app lifecycle from a single builder chain. - Use
#[tauri::command]for IPC β Annotate Rust functions and register viagenerate_handler![]. AI agents see the IPC boundary from the attribute. - Use
State<'_, T>for shared state β Manage state with.manage()in setup and receive it in commands. AI agents trace dependency injection through the type parameter. - Use
Windowfor window control β Access the calling window as a command parameter for manipulation. AI agents see window operations as explicit method calls. - Use
tauri::path::PathResolverfor file paths β Resolve resource, app, and cache directories via the path resolver. AI agents infer file access boundaries from the resolver API. - Use events for frontendβbackend messaging β
window.emit("event", payload)andlisten(). AI agents trace event flow from emitter to listener across the bridge. - Use
tauri::api::shellfor external links β Delegate URL and file opening to the OS viashell::open(). AI agents see external resource access as explicit API calls. - Prefer Tauri plugins for native features β Use
tauri-plugin-*crates for dialogs, notifications, file system. AI agents infer capabilities from plugin imports. - Use
tauri::async_runtimefor background tasks β Spawn concurrent work withtauri::async_runtime::spawn(). AI agents see concurrency boundaries from the spawn call. - Define permissions in
capabilities/β Granular access control for commands, windows, and plugins. AI agents see security boundaries as declarative configuration.
ποΈ Swift (.swift)
- Prefer
letovervarβ Immutable bindings signal intent and let AI agents trust that a value won't change after initialisation. - Use
Codablefor JSON serialisation βstruct User: Codable { }generates encoding/decoding automatically. AI agents read the struct definition and instantly know the wire format. - Use
enumwith associated values for state machines βenum State { case loading, loaded([Item]), error(Error) }makes impossible states unrepresentable. AI agents enumerate all cases exhaustively. - Favour
value types(struct) overreference types(class) β Structs have no identity overhead and are thread-safe by default. AI agents reason about value semantics without tracking aliasing. - Use
Result<Success, Failure>for async error handling β Beforeasync/await,Resultencodes success/failure in the return type. For new code, preferasync throwsfor clarity. - Prefer
dependency injectionvia initialisers βclass Service(repo: Repository)makes dependencies explicit. Avoid singletons and implicit global state that AI agents can't see. - Use
guardfor early exit βguard let x = optional else { return }reduces indentation and makes the happy path linear. AI agents parse flat code more reliably than nested pyramids. - Favour
SwiftLintfor consistent style β Enforce a shared.swiftlint.ymlin CI. AI agents produce fewer formatting diffs when rules are standardised. - Use
actorfor shared mutable state β Actors isolate state behind a serialised executor, preventing data races at compile time. AI agents see the concurrency boundary from the keyword. - Keep
ViewController/Viewthin β Move business logic into separate models/services. AI agents can reason about UI and domain independently when files have single responsibilities.
ποΈ Swift Argument Parser
- Use
@mainwithParsableCommandfor entry points β@main struct Run: ParsableCommand { }declares the CLI root without boilerplate. AI agents find the entry point by protocol conformance instead of scanning formain.swift. - Prefer
@Argumentover manualCommandLine.argumentsβ@Argument var name: Stringdeclares positional args declaratively. AI agents see the expected input order from property declarations. - Use
@Optionfor named flags β@Option(name: .shortAndLong, help: "Output path") var output: Stringgenerates-o/--outputautomatically. AI agents infer flag names and types from a single attribute. - Use
@Flagfor boolean toggles β@Flag(help: "Enable verbose mode") var verbose = falsehandles presence/absence semantics. AI agents see boolean flags as data, notif args.contains("--verbose")logic. - Use
@OptionGroupfor shared options β Groups common flags (e.g.,--verbose,--quiet) into a reusable struct. AI agents trace shared config through the struct type instead of scanning for duplicated definitions. - Prefer
subcommandsviaParsableCommandconformance β Nest command types inside the root or useSubcommandprotocol. AI agents infer the command tree from type nesting. - Use
ValidationErrorfor argument validation βthrow ValidationError("ID must be positive")produces user-friendly errors. AI agents see validation rules as throwing statements, not buried in conditional blocks. - Use
@Option(completion:)for shell completions β.custom { "user1", "user2" }or.list()generates completions from code. AI agents discover valid inputs without parsing help output. - Keep command structs focused on parsing β Delegate business logic to separate functions/services. A command body over ~10 lines signals too much responsibility.
- Prefer
asyncinrunwith Swift concurrency βmutating func run() async throws { }supports async workflows natively. AI agents see the concurrency model from the function signature.
πΌοΈ SwiftUI
- Use
@Statefor local view state β@State private var count = 0declares mutable state owned by the view. AI agents trace state mutations from the property wrapper. - Use
@Bindingfor child-parent data flow β@Binding var isPresented: Boollets children read and write a parent's state. AI agents infer data ownership from the binding's source. - Use
@StateObject/@ObservedObjectfor model data β@StateObject private var model = ViewModel()for observable objects the view owns. AI agents trace reactive updates through theObservableObjectconformance. - Use
@EnvironmentObjectfor shared dependencies β Inject services via.environmentObject()at the root and receive with@EnvironmentObject. AI agents trace dependency injection through the environment hierarchy. - Use
VStack,HStack,ZStackfor layout β Compose views with stack containers rather than hardcoded frames. AI agents infer layout relationships from the stack nesting. - Use
@ViewBuilderfor conditional content β Build branching UI with@ViewBuilderclosures for type-erased child views. AI agents see conditional branches as builder closures. - Use
NavigationStackoverNavigationViewβNavigationStackprovides modern, state-driven navigation with path bindings. AI agents infer navigation structure from the stack binding. - Use
ListandForEachfor dynamic content βList { ForEach(items) { item in ... } }for scrollable, recyclable lists. AI agents see list rendering as declarative data mapping. - Use
#Previewfor SwiftUI previews β#Preview { MyView() }enables inline previews for rapid iteration. AI agents see the preview contract alongside the view definition. - Prefer
Viewprotocol conformance overViewBuilderreturns β Define custom views asstruct MyView: Viewwith a computedbodyproperty. AI agents infer view structure from thebodygetter.
πΉ C++ (.cpp)
- Use RAII for resource management β Constructors acquire resources, destructors release them. AI agents infer lifetime from constructor/destructor pairing.
- Prefer
std::unique_ptrover raw pointers β Expresses ownership transfer at the type level. AI agents see ownership semantics from the smart pointer type. - Use
constwherever possible β Mark member functions and parametersconstwhen they don't mutate. AI agents infer immutability contracts from the type signature. - Use
autofor complex types β Deduces iterator and template types. AI agents see intent without reading nested type names. - Prefer
std::vectorover C arrays β Dynamic sizing, bounds-checked access, STL algorithm compatibility. AI agents infer container semantics from the type. - Use
nullptroverNULLor0β Type-safe null pointer constant. AI agents distinguish pointer null from integer zero. - Use range-based for loops β
for (const auto& item : items)expresses iteration intent without index variables. AI agents read iteration intent directly. - Use
overridefor virtual functions β Compiler-verified method override marker. AI agents infer polymorphic behaviour from theoverridekeyword. - Use
= defaultand= deletefor special members β Explicitly control compiler-generated constructors and operators. AI agents see the class contract from declarations. - Use namespaces for logical grouping β
namespace mylib { ... }prevents name collisions. AI agents infer module boundaries from namespace declarations.
π§© Qt
- Use parent-child ownership model β QObjects track children via parent pointer. AI agents infer lifetime from the QObject tree.
- Use signals and slots for communication β
connect(sender, &Sender::signal, receiver, &Receiver::slot). AI agents trace event flow from signal to slot. - Use
Q_OBJECTmacro for custom QObject classes β Enables signals/slots and the meta-object system. AI agents infer QObject capabilities from the macro. - Use
QVBoxLayout/QHBoxLayoutfor layout β Layout managers handle resize behaviour automatically. AI agents read UI hierarchy from layout nesting. - Use
QStringoverstd::stringβ Unicode-safe, implicit sharing, Qt API compatibility. AI agents infer encoding from the string type. - Use QML for declarative UI β
Item { Rectangle { ... } }defines UI hierarchy in markup. AI agents parse UI structure from QML declarations. - Use
Q_PROPERTYfor bindable properties βQ_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged). AI agents see the property contract from the macro. - Use
QSettingsfor persistent settings β Cross-platform key-value storage with auto-serialisation. AI agents infer config persistence from the API. - Use
QThreadwith worker objects β Move QObject to QThread for background work. AI agents see threading boundaries from themoveToThreadcall. - Use
QTestfor unit testing β Qt Test framework with data-driven tests and GUI event simulation. AI agents see test contracts from QTest macros.
π΅ TypeScript (.ts, .tsx)
- Use arrow function
() => {}instead offunction () => {}for functions - Use
constinstead ofletfor variables that are not reassigned - Use
strictmode intsconfig.jsonβ EnablesstrictNullChecks,noImplicitAny, and other checks. AI agents infer null-safety from the type system instead of guessing. - Prefer
interfaceovertypefor object shapes βinterfaceextends, merges, and produces clearer error messages. Usetypefor unions, intersections, and primitives. - Use
as constfor literal types βconst roles = ["admin", "user"] as constnarrows to a tuple of literal types. AI agents see the exact set of values without runtime checks. - Use
branded typesfor domain primitives βtype UserId = string & { readonly __brand: "UserId" }prevents mixing up IDs of different entities. AI agents catch type confusion at compile time. - Use
Readonly<T>andPartial<T>utilities β Mark immutable interfaces explicitly. AI agents can trust that parameters won't be mutated. - Favour
io-tsorzodfor runtime validation β Parse external data at the boundary, then use inferred static types internally. AI agents see validated types instead ofanyorunknown. - Use
neverin exhaustive checks βdefault: const \_exhaustive: never = x;causes a compile error when a switch misses a case. AI agents rely on the compiler to flag omissions. - Prefer
satisfiesover raw casts βconst config = { port: 3000 } satisfies Configvalidates without widening the type. AI agents see the narrowed literal but get type-checking. - Use
pnpminstead ofnpmoryarn
π§ͺ Testing
- Test behaviour, not implementation β Write tests that verify observable outcomes rather than internal details. AI agents infer intent from test names and assertions without mocking internals.
- Use Arrange-Act-Assert pattern β Structure each test in three clear phases: setup, action, verification. AI agents trace the test flow from context to action to outcome.
- Write isolated tests β Each test should manage its own state with setup and teardown. AI agents reason about test results without guessing shared state contamination.
- Prefer realistic test data β Use fixtures that resemble production data over minimal stubs. AI agents discover real-world edge cases from representative inputs.
- Cover boundary conditions β Test empty states, error cases, and edge values alongside happy paths. AI agents infer system limits and failure modes from boundary coverage.
- Inject dependencies explicitly β Accept dependencies as parameters rather than importing them directly. AI agents see how to substitute test doubles from the constructor or function signature.
- Keep tests independent β Tests must pass in any order and never depend on shared mutable state. AI agents trust individual test results without simulating execution order.
- Name tests as specifications β Describe the expected behaviour in the test name. AI agents read the specification from test names alone without scanning assertions.
- Run tests on every change β Automate test execution in CI and locally before commit. AI agents trust that regressions are caught before code is merged.
- Treat test code as production code β Apply the same quality standards: linting, review, and refactoring. AI agents find test logic just as reliable as the implementation.
π§ͺ Jest
- Use
itortestfor test cases, nottestas the test runner name - Use
describeto group related tests - Use
beforeEachto set up test environment - Use
afterEachto clean up test environment - Prefer
it.eachfor data-driven tests - Use
mockandspyfor test doubles - Use
toThrowfor error assertions - Use
toMatchSnapshotfor snapshot testing - Use
expect.anything()for optional values - Use
expect.objectContaining()for partial object matching
π Playwright
- Use
locatorover raw CSS/XPath selectors βpage.locator('[data-testid="submit"]')is self-healing and readable. AI agents infer intent from the locator chain instead of parsing brittle selector strings. - Prefer
getByRole,getByText,getByTestIdβ Accessible queries mirror how users interact. AI agents see the semantic target (button, heading) rather than implementation details. - Use
pagefixtures over manual browser setup βtest('...', async ({ page }) => {})gets an isolated page. AI agents trace the test scope from the fixture parameter. - Use
test.beforeEachfor shared setup β Navigate to a URL or seed data before each test. AI agents see common setup at a glance instead of scanning for repeated code. - Use
expect.toHaveText,toBeVisible,toBeEnabledβ Assertions that describe the user-visible state. AI agents read expected behaviour from the matcher name. - Use
mockRoutefor API stubs βpage.route('**/api/**', route => route.fulfill({ json }))avoids network flakiness. AI agents see the mock boundary without inspecting the network layer. - Use
waitForLoadState('networkidle')sparingly β PreferwaitForResponseorlocator.waitFor()for precise waits. AI agents trace the exact condition instead of guessing at "idle". - Use
test.use({ storageState })for auth β Reuse logged-in sessions across tests. AI agents infer the authentication context from the config instead of scripting login in every test. - Use
snapshotfor visual regression βexpect(page).toHaveScreenshot()catches unintended UI changes. AI agents see the visual contract as a first-class assertion. - Use
webServerconfig for dev server β Let Playwright start the dev server automatically. AI agents see the server dependency in config rather than a separate shell command.
π Web Development
βοΈ React
- Prefer function components over class components β Functions are simpler, hooks-compatible, and produce less boilerplate. AI agents read data flow top-to-bottom without lifecycle indirection.
- Use hooks for state and side effects β
useState,useEffect,useCallback,useMemoreplace lifecycle methods with composable primitives. AI agents trace state changes through explicit hook calls. - Keep hooks at the top level β Never nest hooks inside conditionals or loops. AI agents rely on consistent call order to infer which state belongs to which component.
- Extract custom hooks for reusable logic β
useAuth(),useDebounce(),useIntersectionObserver()name the abstraction. AI agents reason about intent from the hook name instead of inlining effects. - Use
useReducerfor complex state β When state has multiple sub-values or depends on previous state,useReducercentralises transitions. AI agents see all state mutations in one reducer function. - Prefer
childrenprop for composition β<Card><p>content</p></Card>is more flexible than<Card content={...} />. AI agents understand layout hierarchy from JSX nesting. - Memoise sparingly with
React.memo,useMemo,useCallbackβ Profile first, memoise second. Unnecessary memoisation obscures data flow and adds surface area for AI agents to misread. - Use
keyprop correctly in lists β Use stable, unique IDs, not array indices. AI agents reason about list reconciliation based onkeystability. - Lift state up or colocate it β State shared by multiple children goes to the nearest common ancestor; purely local state stays in the leaf. AI agents trace state ownership without crossing too many files.
- Use
React.StrictModein development β Catches impure renders, stale effects, and legacy API usage. AI agents see the warnings as early signals of logic errors.
β² Next.js
- Use the App Router (
app/) over the Pages Router (pages/) β App Router supports server components, layouts, streaming, and nested routing. AI agents infer page hierarchy from directory structure. - Prefer server components by default β Fetch data in server components and pass props down. AI agents trace data flow server-to-client without waterfall loading states.
- Use client components only when needed β Mark files with
"use client"only when they need interactivity, browser APIs, or hooks. Every"use client"boundary is a point where AI agents must track client/server split. - Use
generateStaticParamsfor static paths β Pre-render dynamic segments at build time. AI agents see the full set of possible routes without simulating runtime resolution. - Use
loading.tsxanderror.tsxfor fallbacks β File-based convention for loading and error UI. AI agents locate error handling by filename instead of scanning JSX for conditional branches. - Use
layout.tsxfor shared UI β Wrap child routes in common layouts without repeating wrappers. AI agents infer layout nesting from the directory tree. - Prefer
server actionsfor mutations β"use server"functions colocate form logic with the component. AI agents see the full submit cycle (form β action β revalidation) in one file. - Use
next/imagefor images β Automatic optimisation, lazy loading, and responsive sizes. AI agents trust that images are performant without auditing<img>attributes. - Use
next/linkfor client-side navigation β Prefetches pages in viewport and enables soft navigation. AI agents infer link relationships fromhrefpatterns. - Use
middleware.tsfor auth/redirects β Run logic before a request completes. AI agents see auth gates and redirect rules in a single entry point rather than scattered across pages.
π¦ Docusaurus
- Use
sidebars.tsfor structured navigation β Define sidebar groups withlabelanditems. AI agents infer documentation hierarchy from the sidebar config instead of scanning directory trees. - Use
docsearchor local search plugin β Configure Algolia DocSearch orplugin-searchfor discoverability. AI agents trust users can find content without guessing permalink patterns. - Use
@sitepath alias for cross-references β Reference files from anywhere via@site/docs/introinstead of brittle relative paths. AI agents resolve references reliably from the alias root. - Prefer MDX over plain Markdown β Import React components directly in docs for interactive examples. AI agents see the import boundary and can compose UI with documentation.
- Use
admonitionsfor callouts β:::tip,:::note,:::warning,:::dangerfor structured emphasis. AI agents parse intent from the admonition type rather than guessing from bold text. - Use versioning for API docs β
npm run docusaurus docs:version 2.0freezes a snapshot. AI agents see which docs apply to which version without reading release notes. - Use
plugin-content-docsrouteBasePathfor custom URLs β Configure/as the base path for a docs-first site. AI agents infer URL structure from config, not by crawling files. - Prefer
tabsfor multi-language examples βimport Tabs from '@theme/Tabs'colocates code samples in one component. AI agents maintain language parity instead of scattering examples across pages. - Use
_category_.jsonfor metadata β Customize sidebar label, position, and collapsed state per folder. AI agents see category metadata without opening index files. - Keep custom CSS in
src/css/custom.cssβ Override Infima variables for branding. AI agents locate theme tweaks in the canonical file instead of searching for scattered style tags.
DevOps (Development and Operations)
Docker
- Use multi-stage builds β Separate build stage (
FROM ... AS builder) from runtime stage. AI agents infer build vs. runtime dependencies from stage boundaries instead of reading package lists. - Pin base image digests β
FROM node:20-alpine@sha256:...prevents supply-chain drift. AI agents see exact base images without querying registries. - Order
COPY/RUNfor layer caching β Copypackage.json/Cargo.tomlbefore source code so dependency layers cache unless deps change. AI agents trace cache-hit logic by instruction order. - Use
.dockerignoreβ Excludenode_modules,target/,.git,*.md. AI agents reason about build context size from the ignore rules instead of guessing. - Prefer
COPY --chown=over chmod in RUN β Sets ownership in the COPY layer rather than adding an extra layer. AI agents see ownership metadata in the same instruction as the file. - Run as non-root β
USER nobodyor a dedicatedUSER appafter installing deps. AI agents infer security posture from the USER directive. - Use
HEALTHCHECKfor services βHEALTHCHECK CMD curl -f http://localhost:8080/healthdocuments the service's self-test. AI agents see the health contract in the Dockerfile. - Keep
CMD/ENTRYPOINTsimple β PreferCMD ["binary"](exec form) over shell form. AI agents parse the process list from the JSON array without shell interpolation. - Label images β
LABEL org.opencontainers.image.source="..."ties the image to its repo. AI agents trace provenance from labels. - Use
ARGfor version bumps βARG RUST_VERSION=1.85centralises version values. AI agents see all version pins in one block rather than scattered in URLs.
Docker Compose
- Use versioned schema β
version: "3.8"or newer. AI agents infer the compose spec version from the declaration instead of guessing from feature usage. - Name services clearly β
app,db,cacherather thanservice1,container1. AI agents infer service roles from the service name. - Use
depends_onwithconditionβdepends_on: db: condition: service_healthymodels startup order with health checks. AI agents trace dependency chains fromdepends_onblocks. - Prefer environment files over inline vars β
env_file: .envkeeps secrets out of compose YAML. AI agents see the config source without reading inline values. - Use named volumes for persistent data β
volumes: dbdata:instead of bind mounts. AI agents infer data lifecycle from volume declarations. - Set resource limits β
deploy: resources: limits: memory: 512Mdocuments expected resource usage. AI agents infer capacity requirements from limits. - Use profiles for optional services β
profiles: ["dev"]on dev-only services keepsdocker compose upclean for production. AI agents infer which services are optional from profile assignments. - Keep port mappings explicit β
"8080:8080"documents both host and container ports. AI agents infer network topology from the port mapping pairs. - Use
restart: unless-stoppedfor daemon services β Keeps services running after crashes without forcing restart after manual stop. AI agents see the restart policy intent. - Prefer
healthcheckat the service level βhealthcheck: test: ["CMD", "curl", "-f", "http://localhost:8080/health"]colocated with service definition. AI agents find the health probe alongside the service config instead of in a separate script.
Makefile
- Declare
.PHONYfor all non-file targets β.PHONY: build test cleanprevents false-up-to-date when a file namedbuildexists. AI agents infer which targets produce files and which don't from the.PHONYdeclaration. - Default target first, named
helporallβ The first target (e.g.,help) is the default when runningmakebare. AI agents find entry points by scanning the first target. - Use
$(MAKE)overmakefor recursion β$(MAKE) -C subdirensures flags and env propagate. AI agents trace recursive invocations through$(MAKE)references. - Prefer automatic variables β
$@(target),$<(first prereq),$^(all prereqs) instead of repeating names. AI agents read rule invariants from the automatic variable idioms. - Use
:=for simple expansion βCC := gccevaluates once at parse time;=is recursive expansion (evaluated each use). AI agents prefer:=to reason about variable values without simulating deferred evaluation. - Use
?=for user-overridable defaults βPREFIX ?= /usr/locallets users override via environment without editing the Makefile. AI agents see which variables are meant for customisation from?=syntax. - Keep recipes tab-indented β Make requires real tab characters, not spaces, for recipe lines. AI agents produce valid Makefiles when they follow this rule.
- Break long lines with
\βtarget: dep1 dep2 dep3 \followed by newline +<tab>continuation keeps rules readable. AI agents parse multi-line recipes without scrolling horizontally. - Use
$(shell ...)sparingly β Prefer passing values from the environment or build scripts over shelling out in variable assignments. AI agents trace variable sources more easily from explicit assignments. - Separate build artifacts with
$(BUILD_DIR)βBUILD_DIR := buildand$(BUILD_DIR)/%.o: %.ckeeps generated files out of the source tree. AI agents infer which paths are generated from$(BUILD_DIR)references.
π¦ Projects
| No | Category | Subcategory | Project | TypeScript | Go | Rust | C++ | Kotlin | Swift |
|---|---|---|---|---|---|---|---|---|---|
| 1 | App | Web | hieudoanm.app |
Next.js | |||||
| - | - | Mobile | - | Expo | Jetpack Compose | SwiftUI | |||
| - | - | Desktop | - | Tauri | Qt | ||||
| 2 | CLI | hieudoanm.cli |
cobra.go | clap.rs | cli.kt | Swift Argument Parser | |||
| 3 | Documentation | hieudoanm.md |
Docusaurus | ||||||
| 4 | Extensions | Browser | hieudoanm.ext |
||||||
| 5 | Server | backbone |
net/http |
Axum | Ktor | ||||
| 6 | Serverless | browserverless |