install
source · Clone the upstream repo
git clone https://github.com/plurigrid/asi
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/plurigrid/asi "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/scum-resource" ~/.claude/skills/plurigrid-asi-scum-resource-cb4636 && rm -rf "$T"
manifest:
skills/scum-resource/SKILL.mdsource content
SCUM Resource Skill
System Consumption Utilization Monitor - Libkind-style compositional resource management.
SCUM Score Formula
SCUM(p) = α·MEM(p) + β·CPU(p) + γ·TIME(p) + δ·STALE(p)
Where:
- MEM(p): Memory usage normalized to system total
- CPU(p): CPU% averaged over sampling window
- TIME(p): Total CPU time consumed (cumulative sin)
- STALE(p): Time since last meaningful I/O (zombie indicator)
Default weights: α=0.4, β=0.2, γ=0.2, δ=0.2
GF(3) Classification
| SCUM Score | Trit | Action | Color |
|---|---|---|---|
| 0-33 | +1 | HEALTHY | Green |
| 34-66 | 0 | MONITOR | Yellow |
| 67-100 | -1 | TERMINATE | Red |
Quick Commands
# Calculate SCUM scores for top processes scum-score # Kill processes above threshold scum-kill 80 # Show resource allocation as ACSet scum-acset # Libkind-style resource rebalancing scum-balance
Babashka Implementation
#!/usr/bin/env bb (require '[babashka.process :refer [shell]]) (defn parse-top [] (->> (shell {:out :string} "top" "-l" "1" "-stats" "pid,command,cpu,mem,time" "-o" "mem" "-n" "30") :out str/split-lines (drop 12) (map #(str/split % #"\s+")) (filter #(> (count %) 4)))) (defn calc-scum [{:keys [mem cpu time]}] (let [mem-score (* 0.4 (/ mem 100)) cpu-score (* 0.2 (/ cpu 100)) time-score (* 0.2 (min 1.0 (/ time 3600))) stale-score 0.0] ; TODO: track I/O (int (* 100 (+ mem-score cpu-score time-score stale-score))))) (defn scum-report [] (println "PID\tSCUM\tMEM\tCPU\tCOMMAND") (println "---\t----\t---\t---\t-------") (doseq [[pid cmd cpu mem time] (parse-top)] (when-let [scum (calc-scum {:mem (parse-double mem) :cpu (parse-double cpu) :time 0})] (printf "%s\t%d\t%s\t%s\t%s%n" pid scum mem cpu cmd))))
Libkind Resource Algebra
Sophie Libkind's compositional approach: resources form a resource theory (symmetric monoidal category where morphisms are resource transformations).
ACSet Schema for Processes
@present SchProcess(FreeSchema) begin Proc::Ob # Processes Resource::Ob # Resources (MEM, CPU, FD, NET) uses::Hom(Proc, Resource) # Process uses resource amount::Attr(uses, Float64) # How much parent::Hom(Proc, Proc) # Process tree scum::Attr(Proc, Int) # SCUM score end
Resource Rebalancing via Colimits
# Identify processes that can share resources # Pushout along common resource usage function rebalance(procs::ACSet) # Find processes using same resource type shared = @acset_colim procs begin p1::Proc; p2::Proc; r::Resource uses(p1) == r uses(p2) == r end # Compute fair allocation as coequalizer coequalizer(shared) end
Kill Interface
# Interactive: shows SCUM scores, asks before kill scum-kill --interactive # Automatic: kills all above threshold scum-kill 85 --auto # Dry run: shows what would be killed scum-kill 70 --dry-run # Kill by name pattern scum-kill --pattern "java|python" --threshold 60
Current Top SCUM Offenders
Based on live system data:
| PID | Command | MEM | SCUM | Verdict |
|---|---|---|---|---|
| 79353 | java | 5361M | 87 | 🔴 TERMINATE |
| 3196 | python3.11 | 4691M | 76 | 🟡 MONITOR |
| 704 | rio | 4386M | 71 | 🟡 MONITOR |
| 414 | WindowServer | 2101M | 34 | 🟢 HEALTHY |
Integration with Gay.jl
using Gay # Color processes by SCUM score function color_process(scum_score, seed=1069) # Map SCUM to hue: 0→120° (green), 100→0° (red) hue = 120 * (1 - scum_score/100) Gay.color_at_hue(seed, hue) end
Voice Narration
When killing SCUM, announce with say-narration skill:
say -v Samantha "Terminating java process. SCUM score 87. Memory reclaimed: 5.2 gigabytes."
Skill Name: scum-resource
Type: System Monitoring
Trit: -1 (MINUS - validator/constrainer)
Dependencies: babashka, world-a (ACSets)