Make vs buy vs open source decision frameworks for technology and component acquisition
Provides structured frameworks for make vs buy vs open source decisions. Triggers when evaluating technology acquisition options for components or systems.
/plugin marketplace add melodic-software/claude-code-plugins/plugin install estimation-planning@melodic-softwareThis skill is limited to using the following tools:
Use this skill when:
Structured decision frameworks for evaluating whether to build custom solutions, buy commercial products, or leverage open source components.
Before providing build/buy guidance:
docs-management skill for methodology documentation┌─────────────────────────────────────────────────────────────────┐
│ │
│ Build │ Hybrid │ OSS │ Buy │
│ Custom │ │ Open Source │ Commercial │
│ │
│ ◄────────────────────────────────────────────────────────────► │
│ Full Control Minimal Maintenance │
│ High Effort Vendor Risk │
│ Differentiating Commodity/Solved │
│ │
└─────────────────────────────────────────────────────────────────┘
public enum AcquisitionOption
{
BuildCustom, // Develop from scratch in-house
BuildOnPlatform, // Custom development on commercial platform
OpenSource, // Adopt open source solution
OSSWithSupport, // Open source with commercial support
SaaS, // Software as a Service
COTS, // Commercial off-the-shelf (on-premise)
Outsource // Custom development by third party
}
public sealed record AcquisitionAnalysis(
string ComponentName,
string BusinessNeed,
IReadOnlyList<AcquisitionOption> OptionsAnalyzed,
IReadOnlyList<OptionEvaluation> Evaluations,
AcquisitionOption RecommendedOption,
string Rationale,
IReadOnlyList<string> Assumptions,
IReadOnlyList<string> Risks,
DecisionConfidence Confidence);
public enum DecisionConfidence
{
High, // Clear winner, well-understood domain
Medium, // Good option, some uncertainty
Low, // Close call, significant unknowns
NeedsMore // Insufficient information to decide
}
public enum BusinessClassification
{
Core, // Competitive differentiator, strategic advantage
CoreSupporting, // Enables core but not differentiating
Context, // Necessary but not differentiating
Commodity // Utility, widely available
}
public sealed class StrategicFitAnalyzer
{
public AcquisitionOption RecommendByStrategicFit(
BusinessClassification classification,
TimeToMarket timeToMarket,
SkillsAvailability skills)
{
return classification switch
{
// Core: Build to control, differentiate
BusinessClassification.Core when skills == SkillsAvailability.Available
=> AcquisitionOption.BuildCustom,
BusinessClassification.Core
=> AcquisitionOption.BuildOnPlatform,
// Core Supporting: Build if feasible, else buy with customization
BusinessClassification.CoreSupporting when timeToMarket == TimeToMarket.Urgent
=> AcquisitionOption.SaaS,
BusinessClassification.CoreSupporting
=> AcquisitionOption.OpenSource,
// Context: Buy or use OSS
BusinessClassification.Context
=> AcquisitionOption.SaaS,
// Commodity: Buy the cheapest reliable option
BusinessClassification.Commodity
=> AcquisitionOption.SaaS,
_ => AcquisitionOption.OpenSource
};
}
}
public enum TimeToMarket
{
Flexible, // Months to years acceptable
Normal, // Weeks to months
Urgent, // Days to weeks
Immediate // Need it now
}
public enum SkillsAvailability
{
Available, // Team has skills and capacity
Acquirable, // Can hire or train in reasonable time
Scarce, // Difficult to obtain
NotAvailable // Cannot obtain
}
| Classification | Build | Buy | OSS |
|---|---|---|---|
| Core + Skills Available | ✅ Recommended | ⚠️ Risk | ⚠️ If excellent fit |
| Core + No Skills | ⚠️ With outsource | ✅ Platform | ✅ With support |
| Core Supporting | ⚠️ If simple | ✅ Recommended | ✅ Recommended |
| Context | ❌ Rarely | ✅ SaaS preferred | ⚠️ If mature |
| Commodity | ❌ Never | ✅ Commodity | ⚠️ If mature |
public sealed record TotalCostOfOwnership(
string Option,
decimal InitialCost,
decimal AnnualOperatingCost,
decimal TCOYears3,
decimal TCOYears5,
IReadOnlyList<CostLineItem> CostBreakdown);
public sealed record CostLineItem(
string Category,
CostType Type,
decimal Amount,
string Period,
string Notes);
public enum CostType
{
OneTime,
Recurring,
Variable
}
public sealed class TCOCalculator
{
public TotalCostOfOwnership CalculateBuildTCO(BuildCostInputs inputs, int years)
{
var costs = new List<CostLineItem>();
// Initial Development
costs.Add(new CostLineItem(
"Development",
CostType.OneTime,
inputs.DevelopmentHours * inputs.HourlyRate,
"Initial",
$"{inputs.DevelopmentHours} hours @ ${inputs.HourlyRate}/hr"));
// Infrastructure Setup
costs.Add(new CostLineItem(
"Infrastructure Setup",
CostType.OneTime,
inputs.InfrastructureSetupCost,
"Initial",
"Servers, cloud setup, environments"));
// Annual Maintenance (15-20% of development cost)
var maintenanceCost = inputs.DevelopmentHours * inputs.HourlyRate * 0.18m;
costs.Add(new CostLineItem(
"Maintenance",
CostType.Recurring,
maintenanceCost,
"Annual",
"Bug fixes, updates, tech debt"));
// Annual Infrastructure
costs.Add(new CostLineItem(
"Infrastructure",
CostType.Recurring,
inputs.AnnualInfrastructureCost,
"Annual",
"Cloud/hosting, monitoring"));
// Annual Support/Operations
costs.Add(new CostLineItem(
"Operations",
CostType.Recurring,
inputs.AnnualOperationsCost,
"Annual",
"DevOps, SRE, on-call"));
var initial = costs.Where(c => c.Type == CostType.OneTime).Sum(c => c.Amount);
var annual = costs.Where(c => c.Type == CostType.Recurring).Sum(c => c.Amount);
return new TotalCostOfOwnership(
Option: "Build",
InitialCost: initial,
AnnualOperatingCost: annual,
TCOYears3: initial + annual * 3,
TCOYears5: initial + annual * 5,
CostBreakdown: costs);
}
public TotalCostOfOwnership CalculateBuyTCO(BuyCostInputs inputs, int years)
{
var costs = new List<CostLineItem>();
// License/Subscription
if (inputs.IsSubscription)
{
costs.Add(new CostLineItem(
"Subscription",
CostType.Recurring,
inputs.AnnualLicenseCost,
"Annual",
$"{inputs.Users} users @ ${inputs.PerUserCost}/user/year"));
}
else
{
costs.Add(new CostLineItem(
"License",
CostType.OneTime,
inputs.PerpetualLicenseCost,
"Initial",
"Perpetual license"));
costs.Add(new CostLineItem(
"Maintenance",
CostType.Recurring,
inputs.PerpetualLicenseCost * 0.20m,
"Annual",
"20% annual maintenance"));
}
// Implementation
costs.Add(new CostLineItem(
"Implementation",
CostType.OneTime,
inputs.ImplementationCost,
"Initial",
"Configuration, customization, integration"));
// Training
costs.Add(new CostLineItem(
"Training",
CostType.OneTime,
inputs.TrainingCost,
"Initial",
$"Training for {inputs.Users} users"));
// Integration/Customization
costs.Add(new CostLineItem(
"Integration",
CostType.Recurring,
inputs.AnnualIntegrationCost,
"Annual",
"Ongoing integration maintenance"));
var initial = costs.Where(c => c.Type == CostType.OneTime).Sum(c => c.Amount);
var annual = costs.Where(c => c.Type == CostType.Recurring).Sum(c => c.Amount);
return new TotalCostOfOwnership(
Option: "Buy",
InitialCost: initial,
AnnualOperatingCost: annual,
TCOYears3: initial + annual * 3,
TCOYears5: initial + annual * 5,
CostBreakdown: costs);
}
public TotalCostOfOwnership CalculateOSSTCO(OSSCostInputs inputs, int years)
{
var costs = new List<CostLineItem>();
// No license cost (but maybe support contract)
if (inputs.SupportContractCost > 0)
{
costs.Add(new CostLineItem(
"Support Contract",
CostType.Recurring,
inputs.SupportContractCost,
"Annual",
"Commercial support subscription"));
}
// Implementation/Integration
costs.Add(new CostLineItem(
"Implementation",
CostType.OneTime,
inputs.ImplementationHours * inputs.HourlyRate,
"Initial",
"Integration, configuration, customization"));
// Expertise Development
costs.Add(new CostLineItem(
"Training/Expertise",
CostType.OneTime,
inputs.ExpertiseDevelopmentCost,
"Initial",
"Learning curve, training"));
// Annual Maintenance (often higher than commercial - you own it)
costs.Add(new CostLineItem(
"Maintenance",
CostType.Recurring,
inputs.AnnualMaintenanceHours * inputs.HourlyRate,
"Annual",
"Upgrades, security patches, customizations"));
// Community Contribution (optional)
if (inputs.ContributionHoursAnnual > 0)
{
costs.Add(new CostLineItem(
"Community Contribution",
CostType.Recurring,
inputs.ContributionHoursAnnual * inputs.HourlyRate,
"Annual",
"Contributing back to project"));
}
var initial = costs.Where(c => c.Type == CostType.OneTime).Sum(c => c.Amount);
var annual = costs.Where(c => c.Type == CostType.Recurring).Sum(c => c.Amount);
return new TotalCostOfOwnership(
Option: "Open Source",
InitialCost: initial,
AnnualOperatingCost: annual,
TCOYears3: initial + annual * 3,
TCOYears5: initial + annual * 5,
CostBreakdown: costs);
}
}
public sealed record EvaluationCriterion(
string Name,
string Description,
double Weight, // 0-1, all weights sum to 1
CriterionCategory Category);
public enum CriterionCategory
{
Cost,
Functionality,
Technical,
Vendor,
Risk,
Strategic
}
public sealed class BuildBuyEvaluator
{
public static IReadOnlyList<EvaluationCriterion> StandardCriteria { get; } = new[]
{
// Cost (25% total)
new EvaluationCriterion("Initial Cost", "Upfront investment required", 0.10, CriterionCategory.Cost),
new EvaluationCriterion("Ongoing Cost", "Annual operating cost", 0.10, CriterionCategory.Cost),
new EvaluationCriterion("Hidden Costs", "Integration, training, opportunity cost", 0.05, CriterionCategory.Cost),
// Functionality (25% total)
new EvaluationCriterion("Feature Fit", "How well requirements are met", 0.15, CriterionCategory.Functionality),
new EvaluationCriterion("Customizability", "Ability to adapt to specific needs", 0.10, CriterionCategory.Functionality),
// Technical (20% total)
new EvaluationCriterion("Integration", "Ease of integration with existing systems", 0.10, CriterionCategory.Technical),
new EvaluationCriterion("Scalability", "Ability to grow with needs", 0.05, CriterionCategory.Technical),
new EvaluationCriterion("Security", "Security posture and compliance", 0.05, CriterionCategory.Technical),
// Vendor/Community (15% total)
new EvaluationCriterion("Viability", "Long-term stability of vendor/project", 0.08, CriterionCategory.Vendor),
new EvaluationCriterion("Support", "Quality of support available", 0.07, CriterionCategory.Vendor),
// Risk (10% total)
new EvaluationCriterion("Lock-in Risk", "Difficulty of switching later", 0.05, CriterionCategory.Risk),
new EvaluationCriterion("Execution Risk", "Risk of failed implementation", 0.05, CriterionCategory.Risk),
// Strategic (5% total)
new EvaluationCriterion("Strategic Value", "Alignment with strategy, differentiation", 0.05, CriterionCategory.Strategic)
};
public OptionEvaluation Evaluate(
AcquisitionOption option,
IReadOnlyDictionary<string, int> scores) // criterion name -> score (1-5)
{
var weightedScore = StandardCriteria
.Sum(c => c.Weight * scores.GetValueOrDefault(c.Name, 3));
var categoryScores = StandardCriteria
.GroupBy(c => c.Category)
.ToDictionary(
g => g.Key,
g => g.Sum(c => c.Weight * scores.GetValueOrDefault(c.Name, 3)) /
g.Sum(c => c.Weight));
return new OptionEvaluation(
Option: option,
WeightedScore: weightedScore,
CategoryScores: categoryScores,
Strengths: IdentifyStrengths(scores),
Weaknesses: IdentifyWeaknesses(scores));
}
}
public sealed record VendorEvaluation(
string VendorName,
string Product,
VendorViability Viability,
ProductMaturity Maturity,
SupportQuality Support,
ContractTerms Terms,
IReadOnlyList<string> RedFlags,
IReadOnlyList<string> Strengths,
VendorRisk OverallRisk);
public sealed record VendorViability(
decimal AnnualRevenue,
int YearsInBusiness,
int TotalCustomers,
int CustomersInYourIndustry,
FundingStatus Funding,
bool PubliclyTraded,
MarketPosition Position);
public enum FundingStatus
{
Bootstrapped,
SeedFunded,
VentureCapital,
PrivateEquity,
PubliclyTraded,
Acquired
}
public enum MarketPosition
{
Leader,
Challenger,
Niche,
Emerging,
Declining
}
public sealed class VendorRiskAssessor
{
public VendorRisk AssessRisk(VendorViability viability)
{
var riskFactors = new List<string>();
// Company size/stability
if (viability.YearsInBusiness < 3)
riskFactors.Add("Company less than 3 years old");
if (viability.TotalCustomers < 100)
riskFactors.Add("Limited customer base");
// Financial health
if (viability.Funding == FundingStatus.SeedFunded)
riskFactors.Add("Early-stage funding - viability uncertain");
// Market position
if (viability.Position == MarketPosition.Declining)
riskFactors.Add("Declining market position");
if (viability.Position == MarketPosition.Emerging && viability.TotalCustomers < 50)
riskFactors.Add("Emerging vendor with limited track record");
return new VendorRisk(
Level: riskFactors.Count switch
{
0 => RiskLevel.Low,
1 or 2 => RiskLevel.Medium,
_ => RiskLevel.High
},
Factors: riskFactors);
}
}
public sealed record OSSProjectHealth(
string ProjectName,
string Repository,
OSSMetrics Metrics,
CommunityHealth Community,
SecurityPosture Security,
LicenseAnalysis License,
IReadOnlyList<string> Risks,
OSSHealthRating Rating);
public sealed record OSSMetrics(
int Stars,
int Forks,
int Contributors,
int OpenIssues,
int ClosedIssues,
TimeSpan AverageIssueResolutionTime,
DateOnly LastCommit,
int CommitsLastYear,
int ReleasesLastYear);
public sealed record CommunityHealth(
bool HasCodeOfConduct,
bool HasContributorGuidelines,
bool ResponsiveToIssues,
bool ActiveMaintainers,
int MaintainerCount,
bool HasDiscussionForum,
bool HasDocumentation);
public sealed record LicenseAnalysis(
string License,
LicenseType Type,
bool CommercialUsageAllowed,
bool PatentGranted,
bool CopyleftRequired,
IReadOnlyList<string> Obligations);
public enum LicenseType
{
Permissive, // MIT, Apache, BSD
WeakCopyleft, // LGPL, MPL
StrongCopyleft, // GPL, AGPL
Proprietary,
Unknown
}
public sealed class OSSEvaluator
{
public OSSHealthRating Evaluate(OSSMetrics metrics, CommunityHealth community)
{
var score = 0;
// Activity (0-30)
score += metrics.CommitsLastYear > 100 ? 20 : metrics.CommitsLastYear / 5;
score += metrics.ReleasesLastYear >= 4 ? 10 : metrics.ReleasesLastYear * 2;
// Popularity/Adoption (0-20)
score += Math.Min(10, metrics.Stars / 1000);
score += Math.Min(10, metrics.Contributors / 10);
// Maintenance (0-25)
var daysSinceCommit = (DateOnly.FromDateTime(DateTime.UtcNow) - metrics.LastCommit).Days;
score += daysSinceCommit < 30 ? 15 : daysSinceCommit < 90 ? 10 : 0;
score += community.ActiveMaintainers ? 10 : 0;
// Community (0-25)
score += community.HasDocumentation ? 10 : 0;
score += community.ResponsiveToIssues ? 10 : 0;
score += community.MaintainerCount > 2 ? 5 : 0;
return score switch
{
>= 80 => OSSHealthRating.Excellent,
>= 60 => OSSHealthRating.Good,
>= 40 => OSSHealthRating.Fair,
>= 20 => OSSHealthRating.Poor,
_ => OSSHealthRating.Risky
};
}
}
public enum OSSHealthRating
{
Excellent, // Active, well-maintained, strong community
Good, // Healthy with minor concerns
Fair, // Some red flags but usable
Poor, // Significant concerns
Risky // High risk of abandonment
}
public sealed class BuildBuyDecisionTree
{
public AcquisitionOption Recommend(DecisionContext context)
{
// Step 1: Strategic classification
if (context.Classification == BusinessClassification.Core)
{
// Core capabilities: lean toward build
if (context.Skills == SkillsAvailability.Available &&
context.TimeToMarket != TimeToMarket.Urgent)
return AcquisitionOption.BuildCustom;
if (context.TimeToMarket == TimeToMarket.Urgent)
return AcquisitionOption.BuildOnPlatform;
}
// Step 2: Check if good commercial options exist
if (context.CommercialOptions.Any(o => o.FeatureFit >= 0.8))
{
// Good commercial fit exists
if (context.Classification >= BusinessClassification.Context)
return AcquisitionOption.SaaS;
}
// Step 3: Check if good OSS options exist
if (context.OSSOptions.Any(o => o.Rating >= OSSHealthRating.Good))
{
var bestOSS = context.OSSOptions.OrderByDescending(o => o.Rating).First();
return bestOSS.HasCommercialSupport
? AcquisitionOption.OSSWithSupport
: AcquisitionOption.OpenSource;
}
// Step 4: No good options - must build
if (context.Skills == SkillsAvailability.Available)
return AcquisitionOption.BuildCustom;
return AcquisitionOption.Outsource;
}
}
When conducting build-buy analysis:
For detailed templates:
Last Updated: 2025-12-26
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.
Applies Anthropic's official brand colors and typography to any sort of artifact that may benefit from having Anthropic's look-and-feel. Use it when brand colors or style guidelines, visual formatting, or company design standards apply.
Create beautiful visual art in .png and .pdf documents using design philosophy. You should use this skill when the user asks to create a poster, piece of art, design, or other static piece. Create original visual designs, never copying existing artists' work to avoid copyright violations.