Files
MeWeb/CLAUDE.md
T
thepraandClaude Opus 5.5 0d99c552eb
Build / Desktop, server and tools (push) Successful in 28s
Workload install without build flags; CI variables and the APK key documented
dotnet workload install refuses -nologo. CLAUDE.md lists every variable and
secret the scripts and workflows read; the README gives the APK
certificate's SHA-256.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012CzABvBkbcFqoHdmi8b9WB
2026-10-15 01:24:11 +02:00

5.2 KiB

CLAUDE.md — MeWeb quick reference

Read AGENT.md first and cite PATTERNS.md for code rules. This file holds commands, the map and the pitfalls.

Commands

dotnet build src/MeWeb.Desktop/MeWeb.Desktop.csproj
dotnet run --project src/MeWeb.Desktop
dotnet run --project src/MeWeb.Server                     # ASPNETCORE_URLS=http://127.0.0.1:5481
dotnet run tools/setup.cs -- --group jdk                   # pinned JDK 21 into tools/jdk
dotnet run tools/setup.cs -- --group packaging             # pinned nfpm into tools/packaging
dotnet build src/MeWeb.Android/MeWeb.Android.csproj \
  -p:JavaSdkDirectory=$PWD/tools/jdk/linux-x64/jdk-21.0.12+8 -p:AndroidSdkDirectory=$HOME/Android/Sdk
dotnet run --project tools/Screenshots -- dist/screenshots [en,it,...]
dotnet run tools/strings.cs -- check                       # every language against English
dotnet run tools/strings.cs -- set Key values.json         # one key, every language at once
dotnet run tools/languages.cs                              # regenerate data/languages.json from CLDR
dotnet publish src/MeWeb.Desktop -c Release -r win-x64 --self-contained -p:PublishSingleFile=true \
  -p:IncludeNativeLibrariesForSelfExtract=true -p:EnableCompressionInSingleFile=true
dotnet publish src/MeWeb.Desktop -c Release -r osx-arm64 --self-contained

The Android workload installs into the user SDK (dotnet workload install android); the system SDK in /opt/dotnet is root-owned, so CI uses the runner user's own ~/.dotnet (passolo's tools/release.sh pattern).

Repository, CI and the variables they read

Name Where What
GITEA_URL shell, optional Gitea base URL for tools/gitea/*.sh; default https://git.thepra.dev
GITEA_ORG shell, optional organisation; default Arasaka
GITEA_REPO shell, optional repository for set_secret.sh; default MeWeb
(git credential store) ~/.git-credentials the only Gitea authentication the scripts use: git credential fill for git.thepra.dev
MEWEB_KEYSTORE_B64 Actions secret the Android keystore, base64 (tools/gitea/set_secret.sh)
MEWEB_KEYSTORE_PASS Actions secret its password (store and key share it), alias meweb
GITEA_TOKEN Actions, automatic the job token; release.sh uses it as RELEASE_TOKEN to create the release and attach files
VERSION, COMMIT job env written by .gitea/scripts/prepare.sh from Directory.Build.props and the commit
MEWEB_KEYSTORE release step a temporary file in $RUNNER_TEMP decoded by .gitea/scripts/android.sh, removed on exit

build.yml runs on every push to master; release.yml on a v* tag (publishes the Gitea release) or by hand (publish: false builds every platform and deploys the server only). Both run on the Arasaka org runner nuvola, user gitea-runner, home /var/lib/gitea-runner: tools/sdk.sh installs the SDK from global.json into its ~/.dotnet (the system SDK in /opt/dotnet is older and root-owned), and the JDK, nfpm and the Android SDK are cached in ~/.cache/meweb. There is deliberately no pull_request trigger: the runner is the production box.

The server's one-time root setup is deploy/max/setup.sh (user meweb, /var/www/meweb.arasaka.software, /etc/meweb/meweb.env, the unit, the runner's sudoers line, the certificate, nginx), run on the box through arasaka.software's tools/max/run.sh.

The Android release key: alias meweb, certificate SHA-256 5f52cff4f52f4e0b6da6cd044bfceaf78d1d42db24f2470602db7f19cbfdf846. Never regenerate it.

Map

Path What
src/MeWeb.Shared Endpoints.cs (routes and hosts), wire contracts, MeWebJsonContext, generated BuildInfo
src/MeWeb.App Avalonia views and view models, Services/Localizer.cs (+ {s:Tr Key}), Strings/<code>.json, Resources/Colors.axaml
src/MeWeb.Desktop desktop head (meweb executable), Windows manifest
src/MeWeb.Android Android head (software.arasaka.meweb), resources, manifest
src/MeWeb.Server meweb.arasaka.software: /api/info, /api/ip
data/languages.json 113 languages: code, autonym, English name, rtl, reviewed or draft
tools/setup.cs + setup.json pinned build tools
tools/Screenshots headless renders of every view in every language
branding/ the icon (SVG source, PNG, ICO)

Pitfalls

  • Avalonia 12 Android head: [Application] MainApplication : AvaloniaAndroidApplication<App> plus a non-generic AvaloniaMainActivity; the main view comes through IActivityApplicationLifetime.MainViewFactory, checked before ISingleViewApplicationLifetime.
  • ApplicationVersion must be an integer: computed from Version through separate VersionMajor/Minor/Patch properties; one nested property function left it unevaluated (XA0003).
  • A headless Avalonia session does not end on its own while the pulse animation runs: the screenshot tool calls Environment.Exit(0) after dispatching.
  • The macOS apphost is ad-hoc signed by the .NET 10 SDK even on Linux (LC_CODE_SIGNATURE present); Apple Silicon refuses unsigned arm64 code, so never strip it.
  • The Windows single-file publish drops native .pdb files beside the exe; only meweb.exe ships.