Skip to main content

ADR-010: Feature Gating Matrix by Tier

Status: Accepted Date: 2025-11-30 Deciders: Architecture Team, Product Team, Finance Team Tags: pricing, feature-gating, freemium, tier-management, product-strategy


Context

CODITECT-CORE provides a comprehensive AI development framework with 52 specialized agents, 81 slash commands, and 26 production skills. To implement a sustainable freemium business model, we need to control feature access based on license tier while maintaining an exceptional free tier that drives viral adoption and conversions to paid plans.

Business Requirements

Freemium Model Goals:

  1. Viral Adoption - Free tier compelling enough to attract 10,000+ users
  2. Clear Value Proposition - Paid tiers unlock meaningful capabilities
  3. Smooth Upgrade Path - Seamless transition from Free → Pro → Team → Enterprise
  4. Revenue Protection - Prevent feature abuse while maintaining developer trust
  5. Conversion Optimization - 5% Free → Pro conversion target ($174K ARR per 10K users)

Tier Structure (from ADR-001, ADR-005):

TierPrice/MonthTarget UsersKey Differentiators
Free$0Individual developers, studentsEssential features, 1 project limit
Pro$29Professional developersAll features, unlimited projects
Team$58/seat5-100 person teamsFloating seats, team dashboard
EnterpriseCustomLarge orgs, runtime embeddingSSO, SLA, custom agents, runtime licensing

Technical Requirements

Multi-Layer Enforcement:

  • Component-level gating (agents, commands, skills)
  • Resource-level gating (projects, seats, API calls)
  • Runtime enforcement (prevent unauthorized access)
  • Graceful degradation (helpful upgrade prompts)

Local-First Architecture Constraints:

  • License validation happens at session start
  • Feature gates cached locally (signed with Cloud KMS)
  • Offline grace periods by tier (24h-168h)
  • No continuous server connection required

User Experience Requirements:

  • Instant feedback when hitting limits
  • Clear upgrade paths with pricing
  • No surprise restrictions (transparent limits)
  • Alternative suggestions when feature unavailable

Competitive Landscape

Freemium Developer Tools:

ProductFree TierPro TierConversion Strategy
GitHubUnlimited public repos$4/mo private repos + advancedUpsell privacy + CI/CD
Vercel100GB bandwidth/mo$20/mo unlimitedUpsell bandwidth + team
Cursor2K requests/mo$20/mo unlimitedUpsell request limits
Claude ProRate limited$20/mo unlimitedUpsell capacity + priority

CODITECT Positioning:

  • Free tier more generous than competitors (5 essential agents vs. heavily limited)
  • Pro tier unlocks ALL features (not gradual tiers)
  • Team tier adds collaboration (seat sharing)
  • Enterprise tier adds runtime embedding (unique value)

Market Research Insights

Developer Tool Pricing Psychology:

  • Free tier must be genuinely useful (not trial/demo)
  • $20-30/mo sweet spot for individual tools
  • Team pricing $50-100/seat acceptable for productivity multipliers
  • Enterprise pricing custom (based on ROI, not seat count)

Conversion Drivers:

  • Project limits (#1 driver: "I need this for work projects")
  • Agent/command restrictions (#2: "I need advanced features")
  • Team collaboration (#3: "My team needs shared licenses")
  • Support SLA (#4: "I need guaranteed uptime")

Decision

We will implement a comprehensive Feature Gating Matrix with runtime enforcement, graceful degradation, and intelligent upgrade prompts that balance free tier value with paid tier monetization.

Feature Matrix by Tier

Complete Feature Comparison

Feature CategoryFreeProTeamEnterprise
Agents5 essentialAll 52All 52All 52 + custom
Commands10 basicAll 81All 81All 81 + custom
Skills5 basicAll 26All 26All 26 + custom
Projects1 activeUnlimitedUnlimitedUnlimited
Concurrent Sessions1 seat1 seat5-100 floatingUnlimited floating
Offline Grace Period24 hours72 hours48 hours168 hours (7 days)
Runtime Embedding✅ (with royalty)
Team Dashboard
SSO/SAML
Custom Agents
Support LevelCommunityEmail (48h)Priority (24h)Dedicated (4h SLA)
API Rate Limit100 req/hour1000 req/hour5000 req/hourCustom
Session History7 days30 days90 days365 days
Export DataJSON onlyJSON + CSVJSON + CSV + ExcelFull database export
Multi-Tenant IsolationShared infraShared infraShared infraDedicated cluster
SLA UptimeBest-effort99%99.5%99.9% (custom SLA)

Free Tier - Essential Features Only

Philosophy: Free tier provides genuinely useful development capabilities while creating clear upgrade motivation for professional use.

Allowed Agents (5 total - carefully selected to showcase value):

  1. codebase-locator (agents/codebase-locator.md)

    • Purpose: File discovery and navigation
    • Why Free: Essential for any development workflow
    • Upgrade Driver: Limited to 100 files per search (Pro: unlimited)
  2. codebase-analyzer (agents/codebase-analyzer.md)

    • Purpose: Code analysis and architecture understanding
    • Why Free: Demonstrates CODITECT's AI capabilities
    • Upgrade Driver: Analysis limited to single file (Pro: cross-file analysis)
  3. frontend-react-typescript-expert (agents/frontend-react-typescript-expert.md)

    • Purpose: React development specialist
    • Why Free: Most popular framework, drives adoption
    • Upgrade Driver: Basic components only (Pro: advanced patterns + optimization)
  4. rust-expert-developer (agents/rust-expert-developer.md)

    • Purpose: Rust development specialist
    • Why Free: Unique value proposition (Rust expertise scarce)
    • Upgrade Driver: Basic syntax help only (Pro: performance optimization, async patterns)
  5. codi-documentation-writer (agents/codi-documentation-writer.md)

    • Purpose: Documentation generation
    • Why Free: Essential for code quality
    • Upgrade Driver: Markdown only (Pro: API docs, diagrams, multi-format)

Excluded Agents (Drive Pro Upgrades):

  • orchestrator - Multi-agent workflows (Team tier upsell: collaboration)
  • cloud-architect - Production deployment (Enterprise tier: runtime embedding)
  • security-specialist - Security auditing (Enterprise tier: compliance requirements)
  • devops-engineer - CI/CD automation (Pro tier: professional workflows)
  • backend-architect - System design (Pro tier: production applications)
  • qa-test-engineer - Testing automation (Pro tier: quality assurance)

Allowed Commands (10 total - core development workflow):

  1. /analyze - Code review and analysis
  2. /implement - Implementation mode (basic)
  3. /document - Generate documentation
  4. /prototype - Rapid prototyping (limited complexity)
  5. /research - Verification mode (limited depth)
  6. /hello - Test command (always free)
  7. /action - Direct implementation (basic actions only)
  8. /ui - UI component generation (React only)
  9. /deliberation - Planning mode (single-agent only)
  10. /optimize - Performance optimization (basic suggestions)

Excluded Commands (Drive Pro Upgrades):

  • /git-sync - Advanced git workflows (Pro: complete repository management)
  • /new-project - Project creation (Pro: unlimited projects)
  • /orchestrate - Multi-agent coordination (Team tier: collaborative workflows)
  • /deploy - Deployment automation (Enterprise tier: production operations)
  • /security-audit - Security scanning (Enterprise tier: compliance)
  • /generate-tests - Test generation (Pro: comprehensive testing)
  • /cxs - Context save (Pro: advanced workflow management)

Allowed Skills (5 total - foundational patterns):

  1. search-strategies - Codebase search patterns
  2. production-patterns - Production code patterns (basic)
  3. framework-patterns - Architecture patterns (common frameworks)
  4. rust-backend-patterns - Rust development patterns (basic)
  5. documentation-librarian - Documentation management

Excluded Skills (Drive Pro Upgrades):

  • git-workflow-automation - Advanced git management (Pro)
  • docker-deployment - Deployment automation (Enterprise)
  • security-hardening - Security best practices (Enterprise)
  • performance-optimization - Advanced optimization (Pro)
  • multi-agent-coordination - Orchestration patterns (Team)

Free Tier Limitations:

FREE_TIER_LIMITS = {
'agents': {
'allowed': [
'codebase-locator',
'codebase-analyzer',
'frontend-react-typescript-expert',
'rust-expert-developer',
'codi-documentation-writer'
],
'max_count': 5,
'usage_limits': {
'codebase-locator': {'max_files_per_search': 100},
'codebase-analyzer': {'max_files_per_analysis': 1},
'frontend-react-typescript-expert': {'complexity_level': 'basic'},
'rust-expert-developer': {'complexity_level': 'basic'},
'codi-documentation-writer': {'formats': ['markdown']}
}
},
'commands': {
'allowed': [
'analyze',
'implement',
'document',
'prototype',
'research',
'hello',
'action',
'ui',
'deliberation',
'optimize'
],
'max_count': 10,
'usage_limits': {
'analyze': {'max_files': 5, 'depth': 'basic'},
'implement': {'complexity': 'basic'},
'prototype': {'max_components': 3},
'research': {'max_sources': 5},
'ui': {'frameworks': ['react']},
'deliberation': {'agents': 1} # Single-agent only
}
},
'skills': {
'allowed': [
'search-strategies',
'production-patterns',
'framework-patterns',
'rust-backend-patterns',
'documentation-librarian'
],
'max_count': 5
},
'projects': {
'max_active': 1,
'max_total': 3 # Can archive old projects
},
'seats': {
'max_concurrent': 1,
'floating': False
},
'offline_grace_hours': 24,
'api_rate_limit': {
'requests_per_hour': 100,
'requests_per_day': 500
},
'session_history_days': 7,
'export_formats': ['json'],
'support_level': 'community',
'sla_uptime': None
}

Pro Tier - All Features Unlocked (Individual Developer)

Philosophy: Pro tier removes all feature restrictions, providing complete CODITECT capabilities for professional individual developers.

Features:

  • All 52 Agents - Complete agent library (no restrictions)
  • All 81 Commands - Full command suite (no complexity limits)
  • All 26 Skills - Complete skill library (no usage limits)
  • Unlimited Projects - Create and manage unlimited projects
  • 72-Hour Offline Grace - 3x longer than Free tier
  • Priority Email Support - 48-hour response SLA
  • Higher API Limits - 10x rate limits vs Free tier
  • 30-Day Session History - 4x longer retention
  • Advanced Exports - JSON + CSV formats

Still Restricted (Upsell to Team/Enterprise):

  • No Floating Seats - Single developer only (Team tier: floating seats)
  • No Team Dashboard - Individual use only (Team tier: collaboration)
  • No Runtime Embedding - Development only (Enterprise tier: production embedding)
  • No SSO/SAML - Email authentication only (Enterprise tier: enterprise auth)
  • No Custom Agents - Standard library only (Enterprise tier: custom development)
PRO_TIER_LIMITS = {
'agents': {
'allowed': ['*'], # All agents
'max_count': -1, # Unlimited (-1 = no limit)
'usage_limits': {} # No usage restrictions
},
'commands': {
'allowed': ['*'],
'max_count': -1,
'usage_limits': {}
},
'skills': {
'allowed': ['*'],
'max_count': -1
},
'projects': {
'max_active': -1, # Unlimited
'max_total': -1
},
'seats': {
'max_concurrent': 1, # Still single user
'floating': False # No floating seats
},
'offline_grace_hours': 72, # 3 days
'api_rate_limit': {
'requests_per_hour': 1000, # 10x Free tier
'requests_per_day': 10000
},
'session_history_days': 30,
'export_formats': ['json', 'csv'],
'support_level': 'email_48h',
'sla_uptime': 0.99 # 99% uptime guarantee
}

Team Tier - Collaborative Development

Philosophy: Team tier adds floating seat sharing and collaboration features for small to medium teams (5-100 developers).

Additional Features Beyond Pro:

  • Floating Seats - 5-100 concurrent seats shared across team
  • Team Dashboard - Real-time seat usage, active sessions, usage analytics
  • Shared License Pool - Team members share single license key
  • Admin Controls - License admin can manage team members, view usage
  • 48-Hour Offline Grace - Balance between flexibility and license protection
  • Higher API Limits - 5x Pro tier limits
  • 90-Day Session History - Team collaboration requires longer history
  • Priority Support - 24-hour response SLA

Pricing Model:

  • 5 seats minimum - $290/month ($58/seat)
  • Scale linearly - Add seats as needed
  • 100 seats maximum - Enterprise tier for larger organizations
TEAM_TIER_LIMITS = {
'agents': {
'allowed': ['*'],
'max_count': -1,
'usage_limits': {}
},
'commands': {
'allowed': ['*'],
'max_count': -1,
'usage_limits': {}
},
'skills': {
'allowed': ['*'],
'max_count': -1
},
'projects': {
'max_active': -1,
'max_total': -1
},
'seats': {
'max_concurrent': 5, # Or 10, 20, 50, 100 (configurable)
'floating': True, # Seats shared across team
'seat_reservation': True # Can reserve seats for specific users
},
'offline_grace_hours': 48, # 2 days
'api_rate_limit': {
'requests_per_hour': 5000, # 5x Pro tier
'requests_per_day': 50000
},
'session_history_days': 90, # 3 months
'export_formats': ['json', 'csv', 'excel'],
'support_level': 'priority_24h',
'sla_uptime': 0.995, # 99.5% uptime
'team_features': {
'dashboard': True,
'usage_analytics': True,
'seat_management': True,
'admin_controls': True,
'audit_logs': True
}
}

Enterprise Tier - Production Embedding & Custom Development

Philosophy: Enterprise tier provides unlimited scale, runtime embedding licenses, custom development, and white-glove support for large organizations.

Additional Features Beyond Team:

  • Unlimited Floating Seats - No seat limits (fair use policy applies)
  • Runtime Embedding License - Deploy CODITECT in production applications
  • SSO/SAML Integration - Enterprise authentication (Okta, Azure AD, Google Workspace)
  • Custom Agents - Develop proprietary agents for organization
  • Custom Commands - Organization-specific slash commands
  • Custom Skills - Proprietary skill libraries
  • Dedicated Support - 4-hour response SLA with dedicated account manager
  • 168-Hour Offline Grace - 7 days for air-gapped environments
  • Custom API Limits - Negotiated based on usage projections
  • 365-Day Session History - Full year retention for compliance
  • Full Database Export - Complete data portability
  • Dedicated Infrastructure - Optional dedicated cluster for data isolation
  • Custom SLA - Negotiable uptime guarantees (up to 99.99%)

Pricing Model:

  • Custom Pricing - Based on seats, runtime usage, and custom development
  • Base: $299/month minimum + seat costs
  • Runtime: $0.10/1K API calls OR 3-5% revenue share
  • Custom Development: $10K-50K one-time fee
  • Implementation Services: Optional professional services
ENTERPRISE_TIER_LIMITS = {
'agents': {
'allowed': ['*'],
'max_count': -1,
'usage_limits': {},
'custom_agents': True, # Can create proprietary agents
'custom_agent_limit': -1
},
'commands': {
'allowed': ['*'],
'max_count': -1,
'usage_limits': {},
'custom_commands': True
},
'skills': {
'allowed': ['*'],
'max_count': -1,
'custom_skills': True
},
'projects': {
'max_active': -1,
'max_total': -1
},
'seats': {
'max_concurrent': -1, # Unlimited (fair use policy)
'floating': True,
'seat_reservation': True,
'seat_pools': True # Separate pools for departments
},
'offline_grace_hours': 168, # 7 days for air-gapped environments
'api_rate_limit': {
'requests_per_hour': -1, # Custom (negotiated)
'requests_per_day': -1
},
'session_history_days': 365, # 1 year
'export_formats': ['json', 'csv', 'excel', 'database_dump'],
'support_level': 'dedicated_4h', # 4-hour SLA
'sla_uptime': 0.999, # 99.9% default (customizable to 99.99%)
'team_features': {
'dashboard': True,
'usage_analytics': True,
'seat_management': True,
'admin_controls': True,
'audit_logs': True,
'sso_saml': True,
'custom_branding': True,
'dedicated_cluster': True # Optional
},
'runtime_embedding': {
'enabled': True,
'licensing_model': 'hybrid', # Per-activation OR revenue share
'activation_limit': -1, # Negotiated
'runtime_api_calls_included': 100000 # 100K included
}
}

Feature Gate Enforcement Architecture

1. License Payload with Feature Flags

Complete License Structure:

# Complete license JWT payload structure
LICENSE_PAYLOAD_STRUCTURE = {
# Standard JWT claims
'iss': 'coditect-cloud-backend', # Issuer
'sub': 'user_id_123', # Subject (user ID)
'aud': 'coditect-core', # Audience
'iat': 1701360000, # Issued at (Unix timestamp)
'exp': 1733000000, # Expiration (Unix timestamp)
'nbf': 1701360000, # Not before

# CODITECT-specific claims
'license_key': 'CODITECT-PRO-XXXX-YYYY-ZZZZ',
'tier': 'pro', # 'free', 'pro', 'team', 'enterprise'
'organization_id': 'org_789',
'user_email': 'developer@example.com',

# Feature flags (comprehensive)
'features': {
'agents': {
'allowed': ['*'], # ['*'] = all, or specific list
'max_count': 52,
'usage_limits': {
# Agent-specific limits (if any)
'codebase-analyzer': {
'max_files_per_analysis': -1 # -1 = unlimited
}
}
},
'commands': {
'allowed': ['*'],
'max_count': 81,
'usage_limits': {
'analyze': {
'max_files': -1,
'depth': 'unlimited'
}
}
},
'skills': {
'allowed': ['*'],
'max_count': 26
},
'projects': {
'max_active': -1, # -1 = unlimited
'max_total': -1
},
'seats': {
'max_concurrent': 1,
'floating': False,
'reservation': False
},
'api_limits': {
'requests_per_hour': 1000,
'requests_per_day': 10000,
'burst_limit': 100 # Max requests in 60 seconds
},
'offline': {
'grace_hours': 72,
'require_periodic_validation': True, # Heartbeat required
'validation_interval_hours': 24
},
'runtime': {
'embedding_allowed': False,
'runtime_license_key': None
},
'team': {
'dashboard_access': False,
'usage_analytics': False,
'admin_controls': False,
'sso_enabled': False
},
'support': {
'level': 'email_48h', # 'community', 'email_48h', 'priority_24h', 'dedicated_4h'
'sla_uptime': 0.99
},
'data': {
'session_history_days': 30,
'export_formats': ['json', 'csv']
},
'custom': {
'agents_allowed': False,
'commands_allowed': False,
'skills_allowed': False
}
},

# Usage tracking metadata
'metadata': {
'created_at': '2025-11-30T00:00:00Z',
'updated_at': '2025-11-30T12:00:00Z',
'last_validated': '2025-11-30T12:00:00Z',
'validation_count': 42,
'environment': 'production' # 'dev', 'staging', 'production'
}
}

Signature and Validation:

# License signing with Cloud KMS (RSA-4096)
# Prevents tampering with feature flags

import jwt
import requests
from google.cloud import kms

def sign_license_token(payload: dict, kms_key_name: str) -> str:
"""
Sign license payload with Cloud KMS asymmetric key.

Args:
payload: License feature flags and metadata
kms_key_name: Full KMS key resource name

Returns:
Signed JWT token
"""

# Encode payload
payload_json = json.dumps(payload, sort_keys=True)

# Create digest
digest = hashlib.sha256(payload_json.encode()).digest()

# Sign with Cloud KMS
kms_client = kms.KeyManagementServiceClient()

sign_request = kms.AsymmetricSignRequest(
name=kms_key_name,
digest={'sha256': digest}
)

sign_response = kms_client.asymmetric_sign(sign_request)
signature = sign_response.signature

# Create JWT with signature
token = jwt.encode(
payload,
signature,
algorithm='RS256',
headers={'kid': kms_key_name}
)

return token


def verify_license_token(token: str, kms_public_key_pem: str) -> dict:
"""
Verify license token signature.

Args:
token: Signed JWT token
kms_public_key_pem: Public key for signature verification

Returns:
Decoded payload if valid

Raises:
jwt.InvalidSignatureError: If signature invalid
jwt.ExpiredSignatureError: If token expired
"""

try:
payload = jwt.decode(
token,
kms_public_key_pem,
algorithms=['RS256'],
audience='coditect-core',
issuer='coditect-cloud-backend'
)

return payload

except jwt.ExpiredSignatureError:
raise ValueError("License expired - please renew subscription")
except jwt.InvalidSignatureError:
raise ValueError("License tampered - signature verification failed")
except Exception as e:
raise ValueError(f"License validation failed: {str(e)}")

2. Feature Gate Runtime Implementation

Complete Feature Gate Module:

# .coditect/sdk/feature_gate.py
# Complete production-ready feature gating implementation

import json
import logging
from typing import Tuple, Optional, Dict, List, Any
from dataclasses import dataclass
from datetime import datetime, timezone
import hashlib

logger = logging.getLogger(__name__)


@dataclass
class FeatureGateError:
"""Feature gate denial details."""
error_code: str
message: str
current_tier: str
required_tier: str
upgrade_url: str
alternative: Optional[str] = None
usage_info: Optional[Dict[str, Any]] = None


class FeatureGate:
"""
Feature gating enforcement for tier-based access control.

Validates agent, command, skill, and resource access based on
license tier and feature flags. Provides graceful degradation
with helpful upgrade prompts.

Thread-safe: Can be used across multiple threads.
"""

def __init__(self, license_data: dict):
"""
Initialize feature gate from license payload.

Args:
license_data: Decoded JWT license payload with feature flags
"""
self.license_data = license_data
self.tier = license_data.get('tier', 'free')
self.features = license_data.get('features', {})
self.license_key = license_data.get('license_key', 'UNKNOWN')

# Cache for performance
self._cache = {}

logger.info(f"FeatureGate initialized for tier: {self.tier}")

# ===================================================================
# Agent Gating
# ===================================================================

def check_agent_allowed(
self,
agent_name: str,
usage_context: Optional[Dict[str, Any]] = None
) -> Tuple[bool, Optional[FeatureGateError]]:
"""
Check if agent is allowed for this tier.

Args:
agent_name: Name of agent (e.g., 'orchestrator')
usage_context: Optional usage parameters (e.g., {'complexity': 'advanced'})

Returns:
(allowed: bool, error: Optional[FeatureGateError])
"""

# Check cache
cache_key = f"agent:{agent_name}"
if cache_key in self._cache:
return self._cache[cache_key]

agent_config = self.features.get('agents', {})
allowed_agents = agent_config.get('allowed', [])

# Wildcard: all agents allowed
if allowed_agents == ['*'] or '*' in allowed_agents:
# Check usage limits if context provided
if usage_context:
usage_allowed = self._check_agent_usage_limits(
agent_name,
usage_context
)
if not usage_allowed:
error = self._create_usage_limit_error(
'agent',
agent_name,
usage_context
)
result = (False, error)
self._cache[cache_key] = result
return result

result = (True, None)
self._cache[cache_key] = result
return result

# Check if agent in allowed list
if agent_name in allowed_agents:
result = (True, None)
self._cache[cache_key] = result
return result

# Agent not allowed - create error
error = FeatureGateError(
error_code='AGENT_NOT_ALLOWED',
message=f'Agent "{agent_name}" requires {self._get_required_tier("agent", agent_name)} or higher',
current_tier=self.tier,
required_tier=self._get_required_tier('agent', agent_name),
upgrade_url=self._get_upgrade_url(),
alternative=self._suggest_alternative_agent(agent_name),
usage_info={
'agent_name': agent_name,
'allowed_agents': allowed_agents,
'tier': self.tier
}
)

result = (False, error)
self._cache[cache_key] = result
return result

def _check_agent_usage_limits(
self,
agent_name: str,
usage_context: Dict[str, Any]
) -> bool:
"""Check if agent usage within tier limits."""

agent_config = self.features.get('agents', {})
usage_limits = agent_config.get('usage_limits', {})

if agent_name not in usage_limits:
return True # No limits for this agent

agent_limits = usage_limits[agent_name]

# Check each limit
for limit_key, limit_value in agent_limits.items():
context_value = usage_context.get(limit_key)

if context_value is None:
continue # Context doesn't specify this parameter

# Numeric limits (e.g., max_files_per_analysis: 1)
if isinstance(limit_value, int) and limit_value != -1:
if isinstance(context_value, int):
if context_value > limit_value:
return False

# String limits (e.g., complexity_level: 'basic')
elif isinstance(limit_value, str):
if context_value != limit_value:
return False

# List limits (e.g., formats: ['markdown'])
elif isinstance(limit_value, list):
if context_value not in limit_value:
return False

return True

# ===================================================================
# Command Gating
# ===================================================================

def check_command_allowed(
self,
command_name: str,
usage_context: Optional[Dict[str, Any]] = None
) -> Tuple[bool, Optional[FeatureGateError]]:
"""
Check if command is allowed for this tier.

Args:
command_name: Name of command (e.g., 'git-sync')
usage_context: Optional usage parameters

Returns:
(allowed: bool, error: Optional[FeatureGateError])
"""

cache_key = f"command:{command_name}"
if cache_key in self._cache:
return self._cache[cache_key]

command_config = self.features.get('commands', {})
allowed_commands = command_config.get('allowed', [])

# Wildcard: all commands allowed
if allowed_commands == ['*'] or '*' in allowed_commands:
# Check usage limits
if usage_context:
usage_allowed = self._check_command_usage_limits(
command_name,
usage_context
)
if not usage_allowed:
error = self._create_usage_limit_error(
'command',
command_name,
usage_context
)
result = (False, error)
self._cache[cache_key] = result
return result

result = (True, None)
self._cache[cache_key] = result
return result

# Check if command in allowed list
if command_name in allowed_commands:
result = (True, None)
self._cache[cache_key] = result
return result

# Command not allowed
error = FeatureGateError(
error_code='COMMAND_NOT_ALLOWED',
message=f'Command "/{command_name}" requires {self._get_required_tier("command", command_name)} or higher',
current_tier=self.tier,
required_tier=self._get_required_tier('command', command_name),
upgrade_url=self._get_upgrade_url(),
alternative=self._suggest_alternative_command(command_name),
usage_info={
'command_name': command_name,
'allowed_commands': allowed_commands,
'tier': self.tier
}
)

result = (False, error)
self._cache[cache_key] = result
return result

def _check_command_usage_limits(
self,
command_name: str,
usage_context: Dict[str, Any]
) -> bool:
"""Check if command usage within tier limits."""

command_config = self.features.get('commands', {})
usage_limits = command_config.get('usage_limits', {})

if command_name not in usage_limits:
return True

command_limits = usage_limits[command_name]

for limit_key, limit_value in command_limits.items():
context_value = usage_context.get(limit_key)

if context_value is None:
continue

if isinstance(limit_value, int) and limit_value != -1:
if isinstance(context_value, int):
if context_value > limit_value:
return False
elif isinstance(limit_value, str):
if context_value != limit_value:
return False
elif isinstance(limit_value, list):
if context_value not in limit_value:
return False

return True

# ===================================================================
# Skill Gating
# ===================================================================

def check_skill_allowed(self, skill_name: str) -> Tuple[bool, Optional[FeatureGateError]]:
"""Check if skill is allowed for this tier."""

cache_key = f"skill:{skill_name}"
if cache_key in self._cache:
return self._cache[cache_key]

skill_config = self.features.get('skills', {})
allowed_skills = skill_config.get('allowed', [])

if allowed_skills == ['*'] or '*' in allowed_skills:
result = (True, None)
self._cache[cache_key] = result
return result

if skill_name in allowed_skills:
result = (True, None)
self._cache[cache_key] = result
return result

error = FeatureGateError(
error_code='SKILL_NOT_ALLOWED',
message=f'Skill "{skill_name}" requires {self._get_required_tier("skill", skill_name)} or higher',
current_tier=self.tier,
required_tier=self._get_required_tier('skill', skill_name),
upgrade_url=self._get_upgrade_url(),
alternative=self._suggest_alternative_skill(skill_name)
)

result = (False, error)
self._cache[cache_key] = result
return result

# ===================================================================
# Resource Gating (Projects, Seats, API Limits)
# ===================================================================

def check_project_limit(
self,
current_active: int,
current_total: int
) -> Tuple[bool, Optional[FeatureGateError]]:
"""
Check if user has exceeded project limits.

Args:
current_active: Number of currently active projects
current_total: Total number of projects (including archived)

Returns:
(allowed: bool, error: Optional[FeatureGateError])
"""

project_config = self.features.get('projects', {})
max_active = project_config.get('max_active', 1)
max_total = project_config.get('max_total', 3)

# -1 = unlimited
if max_active == -1:
return (True, None)

# Check active project limit
if current_active >= max_active:
error = FeatureGateError(
error_code='PROJECT_LIMIT_EXCEEDED',
message=f'{self.tier.title()} tier limited to {max_active} active project(s)',
current_tier=self.tier,
required_tier='pro',
upgrade_url=self._get_upgrade_url(),
alternative='Archive an existing project to activate a new one',
usage_info={
'current_active': current_active,
'max_active': max_active,
'current_total': current_total,
'max_total': max_total
}
)
return (False, error)

# Check total project limit (if applicable)
if max_total != -1 and current_total >= max_total:
error = FeatureGateError(
error_code='PROJECT_TOTAL_LIMIT_EXCEEDED',
message=f'{self.tier.title()} tier limited to {max_total} total projects',
current_tier=self.tier,
required_tier='pro',
upgrade_url=self._get_upgrade_url(),
alternative='Delete an archived project to create a new one'
)
return (False, error)

return (True, None)

def check_api_rate_limit(
self,
requests_last_hour: int,
requests_last_day: int
) -> Tuple[bool, Optional[FeatureGateError]]:
"""Check if API rate limit exceeded."""

api_config = self.features.get('api_limits', {})
hourly_limit = api_config.get('requests_per_hour', 100)
daily_limit = api_config.get('requests_per_day', 500)

# -1 = unlimited
if hourly_limit == -1:
return (True, None)

if requests_last_hour >= hourly_limit:
error = FeatureGateError(
error_code='API_RATE_LIMIT_HOURLY',
message=f'Hourly API limit exceeded ({requests_last_hour}/{hourly_limit})',
current_tier=self.tier,
required_tier='pro',
upgrade_url=self._get_upgrade_url(),
alternative='Wait until next hour or upgrade for higher limits',
usage_info={
'requests_last_hour': requests_last_hour,
'hourly_limit': hourly_limit,
'requests_last_day': requests_last_day,
'daily_limit': daily_limit
}
)
return (False, error)

if daily_limit != -1 and requests_last_day >= daily_limit:
error = FeatureGateError(
error_code='API_RATE_LIMIT_DAILY',
message=f'Daily API limit exceeded ({requests_last_day}/{daily_limit})',
current_tier=self.tier,
required_tier='pro',
upgrade_url=self._get_upgrade_url(),
alternative='Wait until tomorrow or upgrade for higher limits'
)
return (False, error)

return (True, None)

def check_offline_grace(
self,
last_online: datetime
) -> Tuple[bool, Optional[FeatureGateError]]:
"""Check if offline grace period still valid."""

offline_config = self.features.get('offline', {})
grace_hours = offline_config.get('grace_hours', 24)

now = datetime.now(timezone.utc)
offline_duration = now - last_online
offline_hours = offline_duration.total_seconds() / 3600

if offline_hours < grace_hours:
hours_remaining = int(grace_hours - offline_hours)

# Warning if <24 hours remaining
if hours_remaining < 24:
logger.warning(
f"Offline grace period expires in {hours_remaining} hours"
)

return (True, None)

error = FeatureGateError(
error_code='OFFLINE_GRACE_EXPIRED',
message=f'Offline grace period expired ({int(offline_hours)} hours offline)',
current_tier=self.tier,
required_tier=None, # Not a tier issue
upgrade_url=None,
alternative='Connect to internet to validate license',
usage_info={
'grace_hours': grace_hours,
'offline_hours': int(offline_hours),
'last_online': last_online.isoformat()
}
)

return (False, error)

# ===================================================================
# Helper Methods
# ===================================================================

def _get_required_tier(self, feature_type: str, feature_name: str) -> str:
"""Determine minimum tier required for feature."""

# Free tier component lists (from earlier definitions)
FREE_AGENTS = [
'codebase-locator',
'codebase-analyzer',
'frontend-react-typescript-expert',
'rust-expert-developer',
'codi-documentation-writer'
]

FREE_COMMANDS = [
'analyze', 'implement', 'document', 'prototype',
'research', 'hello', 'action', 'ui', 'deliberation', 'optimize'
]

FREE_SKILLS = [
'search-strategies',
'production-patterns',
'framework-patterns',
'rust-backend-patterns',
'documentation-librarian'
]

# Team/Enterprise exclusive features
TEAM_EXCLUSIVE = {
'agent': ['orchestrator'],
'command': ['orchestrate', 'team-dashboard']
}

ENTERPRISE_EXCLUSIVE = {
'agent': ['cloud-architect', 'security-specialist'],
'command': ['deploy', 'security-audit', 'custom-agent']
}

# Check tier requirements
if feature_type == 'agent':
if feature_name in FREE_AGENTS:
return 'free'
elif feature_name in ENTERPRISE_EXCLUSIVE.get('agent', []):
return 'enterprise'
elif feature_name in TEAM_EXCLUSIVE.get('agent', []):
return 'team'
else:
return 'pro'

elif feature_type == 'command':
if feature_name in FREE_COMMANDS:
return 'free'
elif feature_name in ENTERPRISE_EXCLUSIVE.get('command', []):
return 'enterprise'
elif feature_name in TEAM_EXCLUSIVE.get('command', []):
return 'team'
else:
return 'pro'

elif feature_type == 'skill':
if feature_name in FREE_SKILLS:
return 'free'
else:
return 'pro'

return 'pro' # Default

def _get_upgrade_url(self) -> str:
"""Get upgrade URL for current tier."""
return 'https://coditect.ai/pricing'

def _suggest_alternative_agent(self, agent_name: str) -> Optional[str]:
"""Suggest free-tier alternative agent if available."""

alternatives = {
'orchestrator': 'Use codebase-analyzer for single-file analysis',
'cloud-architect': 'Use codi-documentation-writer for deployment docs',
'devops-engineer': 'Use rust-expert-developer for basic CI/CD scripting',
'backend-architect': 'Use codebase-analyzer for architecture review',
'qa-test-engineer': 'Use codi-documentation-writer for test documentation'
}

return alternatives.get(agent_name)

def _suggest_alternative_command(self, command_name: str) -> Optional[str]:
"""Suggest free-tier alternative command if available."""

alternatives = {
'git-sync': 'Use /action for manual git operations',
'new-project': 'Manually create project structure',
'orchestrate': 'Use /deliberation for single-agent planning',
'deploy': 'Use /document to generate deployment guides',
'generate-tests': 'Use /document to generate test templates'
}

return alternatives.get(command_name)

def _suggest_alternative_skill(self, skill_name: str) -> Optional[str]:
"""Suggest free-tier alternative skill if available."""

alternatives = {
'git-workflow-automation': 'Use search-strategies for git documentation',
'docker-deployment': 'Use documentation-librarian for deployment guides',
'security-hardening': 'Use production-patterns for basic security'
}

return alternatives.get(skill_name)

def _create_usage_limit_error(
self,
feature_type: str,
feature_name: str,
usage_context: Dict[str, Any]
) -> FeatureGateError:
"""Create error for usage limit exceeded."""

return FeatureGateError(
error_code='USAGE_LIMIT_EXCEEDED',
message=f'{feature_type.title()} "{feature_name}" usage exceeds {self.tier} tier limits',
current_tier=self.tier,
required_tier=self._get_required_tier(feature_type, feature_name),
upgrade_url=self._get_upgrade_url(),
alternative=f'Reduce usage parameters or upgrade to {self._get_required_tier(feature_type, feature_name)} tier',
usage_info=usage_context
)

def get_tier_info(self) -> Dict[str, Any]:
"""Get comprehensive tier information."""

return {
'tier': self.tier,
'license_key': self.license_key,
'features': self.features,
'limits': {
'agents': {
'allowed_count': len(self.features.get('agents', {}).get('allowed', [])),
'max_count': self.features.get('agents', {}).get('max_count', 0)
},
'commands': {
'allowed_count': len(self.features.get('commands', {}).get('allowed', [])),
'max_count': self.features.get('commands', {}).get('max_count', 0)
},
'projects': {
'max_active': self.features.get('projects', {}).get('max_active', 1),
'max_total': self.features.get('projects', {}).get('max_total', 3)
},
'api': {
'hourly_limit': self.features.get('api_limits', {}).get('requests_per_hour', 100),
'daily_limit': self.features.get('api_limits', {}).get('requests_per_day', 500)
},
'offline_grace_hours': self.features.get('offline', {}).get('grace_hours', 24)
},
'upgrade_url': self._get_upgrade_url()
}


# ===================================================================
# Upgrade Prompt Rendering
# ===================================================================

def show_upgrade_prompt(error: FeatureGateError, verbose: bool = True):
"""
Display beautiful upgrade prompt when feature gate denies access.

Args:
error: FeatureGateError with denial details
verbose: If True, show detailed comparison table
"""

import textwrap

# Color codes (ANSI)
RED = '\033[91m'
YELLOW = '\033[93m'
GREEN = '\033[92m'
BLUE = '\033[94m'
BOLD = '\033[1m'
RESET = '\033[0m'

# Build prompt
border = '═' * 59

print(f"""
{BOLD}{border}{RESET}
{BOLD}{' ' * 19}CODITECT License Upgrade Required{' ' * 19}{RESET}
{BOLD}{border}{RESET}
║ ║
{RED}Feature:{RESET} {error.usage_info.get('agent_name') or error.usage_info.get('command_name') or 'N/A':<47}
{YELLOW}Your Tier:{RESET} {error.current_tier.upper():<44}
{GREEN}Required:{RESET} {error.required_tier.upper():<45}
║ ║
{BOLD}{border}{RESET}
{BOLD}{' ' * 23}Upgrade Benefits{' ' * 23}{RESET}
{BOLD}{border}{RESET}
║ ║
║ ✓ All 52 specialized agents ║
║ ✓ All 81 slash commands ║
║ ✓ Unlimited projects ║
║ ✓ 72h offline grace period ║
║ ✓ Priority support ║
║ ║
{BOLD}Only $29/month - Cancel anytime{RESET}
║ ║
{BOLD}{border}{RESET}

{BLUE}Visit: {error.upgrade_url}{RESET}
""")

if error.alternative:
print(f"{YELLOW}Alternative:{RESET} {error.alternative}\n")

if verbose:
print_tier_comparison()


def print_tier_comparison():
"""Print detailed tier comparison table."""

print("""
┌──────────────────────────┬───────────┬─────────┬─────────┬────────────┐
│ Feature │ Free │ Pro │ Team │ Enterprise │
├──────────────────────────┼───────────┼─────────┼─────────┼────────────┤
│ Agents │ 5 │ All 52 │ All 52 │ All 52+ │
│ Commands │ 10 │ All 81 │ All 81 │ All 81+ │
│ Projects │ 1 │ Unlim. │ Unlim. │ Unlimited │
│ Concurrent Seats │ 1 │ 1 │ 5-100 │ Unlimited │
│ Offline Grace │ 24h │ 72h │ 48h │ 168h │
│ Team Dashboard │ ❌ │ ❌ │ ✅ │ ✅ │
│ Runtime Embedding │ ❌ │ ❌ │ ❌ │ ✅ │
│ SSO/SAML │ ❌ │ ❌ │ ❌ │ ✅ │
│ Support │ Community │ Email │ Priority│ Dedicated │
│ Price/Month │ $0 │ $29 │ $58/seat│ Custom │
└──────────────────────────┴───────────┴─────────┴─────────┴────────────┘
""")


# ===================================================================
# CLI for Testing Feature Gates
# ===================================================================

if __name__ == '__main__':
import argparse

parser = argparse.ArgumentParser(description='Test CODITECT feature gates')
parser.add_argument('--tier', choices=['free', 'pro', 'team', 'enterprise'], required=True)
parser.add_argument('--test', choices=['agent', 'command', 'skill', 'project', 'api'], required=True)
parser.add_argument('--name', help='Name of agent/command/skill to test')
parser.add_argument('--current-projects', type=int, default=0)
parser.add_argument('--api-requests-hour', type=int, default=0)

args = parser.parse_args()

# Mock license data
if args.tier == 'free':
license_data = {'tier': 'free', 'features': FREE_TIER_LIMITS, 'license_key': 'TEST-FREE'}
elif args.tier == 'pro':
license_data = {'tier': 'pro', 'features': PRO_TIER_LIMITS, 'license_key': 'TEST-PRO'}
elif args.tier == 'team':
license_data = {'tier': 'team', 'features': TEAM_TIER_LIMITS, 'license_key': 'TEST-TEAM'}
else:
license_data = {'tier': 'enterprise', 'features': ENTERPRISE_TIER_LIMITS, 'license_key': 'TEST-ENT'}

gate = FeatureGate(license_data)

if args.test == 'agent':
allowed, error = gate.check_agent_allowed(args.name)
if allowed:
print(f"✅ Agent '{args.name}' ALLOWED for {args.tier} tier")
else:
print(f"❌ Agent '{args.name}' DENIED for {args.tier} tier")
show_upgrade_prompt(error)

elif args.test == 'command':
allowed, error = gate.check_command_allowed(args.name)
if allowed:
print(f"✅ Command '/{args.name}' ALLOWED for {args.tier} tier")
else:
print(f"❌ Command '/{args.name}' DENIED for {args.tier} tier")
show_upgrade_prompt(error)

elif args.test == 'skill':
allowed, error = gate.check_skill_allowed(args.name)
if allowed:
print(f"✅ Skill '{args.name}' ALLOWED for {args.tier} tier")
else:
print(f"❌ Skill '{args.name}' DENIED for {args.tier} tier")
show_upgrade_prompt(error)

elif args.test == 'project':
allowed, error = gate.check_project_limit(args.current_projects, args.current_projects)
if allowed:
print(f"✅ Project creation ALLOWED for {args.tier} tier ({args.current_projects} active)")
else:
print(f"❌ Project creation DENIED for {args.tier} tier ({args.current_projects} active)")
show_upgrade_prompt(error)

elif args.test == 'api':
allowed, error = gate.check_api_rate_limit(args.api_requests_hour, args.api_requests_hour * 24)
if allowed:
print(f"✅ API request ALLOWED for {args.tier} tier ({args.api_requests_hour} requests/hour)")
else:
print(f"❌ API request DENIED for {args.tier} tier ({args.api_requests_hour} requests/hour)")
show_upgrade_prompt(error)

3. Integration Points

Session Initialization Hook:

# .coditect/scripts/init.sh
# Feature gate validation at session start

#!/bin/bash

set -e

echo "🔧 Initializing CODITECT session..."

# Load license
LICENSE_CACHE="$HOME/.coditect/license_cache.json"

if [ ! -f "$LICENSE_CACHE" ]; then
echo "❌ No license found - please run: coditect login"
exit 1
fi

# Validate license and feature gates
python3 .coditect/sdk/feature_gate.py validate --session-id "$SESSION_ID"

GATE_EXIT_CODE=$?

if [ $GATE_EXIT_CODE -eq 0 ]; then
echo "✅ License valid - all features available for your tier"
elif [ $GATE_EXIT_CODE -eq 1 ]; then
echo "⚠️ Some features restricted by license tier"
echo " Visit https://coditect.ai/pricing to upgrade"
# Continue with restricted access
elif [ $GATE_EXIT_CODE -eq 2 ]; then
echo "❌ License validation failed - critical error"
exit 1
fi

# Continue with session initialization
python3 .coditect/scripts/session-startup.py

echo "✅ CODITECT session ready"

Agent Invocation Hook:

# .coditect/sdk/agent_invocation.py
# Intercept Task() calls to enforce feature gates

from typing import Optional, Dict, Any
import json
import logging
from .feature_gate import FeatureGate, show_upgrade_prompt

logger = logging.getLogger(__name__)


def invoke_agent(
agent_name: str,
prompt: str,
context: Optional[Dict[str, Any]] = None
) -> Optional[Any]:
"""
Invoke agent with feature gate enforcement.

Args:
agent_name: Name of agent to invoke
prompt: Prompt for agent
context: Optional execution context

Returns:
Agent result if allowed, None if denied
"""

# Load license
license = load_license_cache()

if not license:
print("❌ No valid license - please run: coditect login")
return None

# Create feature gate
gate = FeatureGate(license)

# Check if agent allowed
allowed, error = gate.check_agent_allowed(agent_name, context)

if not allowed:
# Show upgrade prompt
show_upgrade_prompt(error, verbose=True)

# Log denial
logger.warning(
f"Agent '{agent_name}' denied for tier '{gate.tier}'",
extra={'error': error.__dict__}
)

return None

# Agent allowed - proceed with invocation
logger.info(f"Invoking agent: {agent_name}")

# Actual Task() invocation (imported from Claude Code SDK)
from claude_code import Task

return Task(
subagent_type=agent_name,
prompt=prompt,
description=f"Execute {agent_name}",
**context if context else {}
)


def load_license_cache() -> Optional[dict]:
"""Load cached license from local storage."""

import os
from pathlib import Path

cache_path = Path.home() / '.coditect' / 'license_cache.json'

if not cache_path.exists():
return None

try:
with open(cache_path, 'r') as f:
return json.load(f)
except Exception as e:
logger.error(f"Failed to load license cache: {e}")
return None

Command Execution Hook:

# .coditect/sdk/command_execution.py
# Intercept slash command execution

from typing import Optional
from .feature_gate import FeatureGate, show_upgrade_prompt
import logging

logger = logging.getLogger(__name__)


def execute_command(command_name: str, args: Optional[dict] = None) -> Optional[Any]:
"""
Execute slash command with feature gate enforcement.

Args:
command_name: Name of command (without leading /)
args: Optional command arguments

Returns:
Command result if allowed, None if denied
"""

# Load license
from .agent_invocation import load_license_cache
license = load_license_cache()

if not license:
print("❌ No valid license - please run: coditect login")
return None

# Create feature gate
gate = FeatureGate(license)

# Check if command allowed
allowed, error = gate.check_command_allowed(command_name, args)

if not allowed:
# Show upgrade prompt
show_upgrade_prompt(error, verbose=True)

# Log denial
logger.warning(
f"Command '/{command_name}' denied for tier '{gate.tier}'",
extra={'error': error.__dict__}
)

return None

# Command allowed - proceed
logger.info(f"Executing command: /{command_name}")

# Import and execute actual command
from claude_code import SlashCommand

return SlashCommand(
command=command_name,
args=args if args else {}
)

Project Creation Hook:

# .coditect/sdk/project_management.py
# Enforce project limits

from typing import Tuple, Optional
from .feature_gate import FeatureGate, show_upgrade_prompt, FeatureGateError
import logging

logger = logging.getLogger(__name__)


def can_create_project(project_name: str) -> Tuple[bool, Optional[FeatureGateError]]:
"""
Check if user can create new project.

Args:
project_name: Name of project to create

Returns:
(allowed: bool, error: Optional[FeatureGateError])
"""

# Load license
from .agent_invocation import load_license_cache
license = load_license_cache()

if not license:
error = FeatureGateError(
error_code='NO_LICENSE',
message='No valid license found',
current_tier='none',
required_tier='free',
upgrade_url='https://coditect.ai/pricing',
alternative='Run: coditect login'
)
return (False, error)

# Get current project count
current_active, current_total = get_project_counts()

# Create feature gate
gate = FeatureGate(license)

# Check project limit
allowed, error = gate.check_project_limit(current_active, current_total)

if not allowed:
logger.warning(
f"Project creation denied: {current_active} active, {current_total} total",
extra={'tier': gate.tier}
)

return (allowed, error)


def get_project_counts() -> Tuple[int, int]:
"""
Get current active and total project counts.

Returns:
(active_count: int, total_count: int)
"""

import os
from pathlib import Path

projects_dir = Path.home() / '.coditect' / 'projects'

if not projects_dir.exists():
return (0, 0)

projects = []

for project_file in projects_dir.glob('*.json'):
try:
with open(project_file, 'r') as f:
project = json.load(f)
projects.append(project)
except Exception:
continue

active_count = sum(1 for p in projects if p.get('status') == 'active')
total_count = len(projects)

return (active_count, total_count)

4. Graceful Degradation UX

Beautiful Upgrade Prompt (Enhanced):

# .coditect/sdk/upgrade_prompt.py
# Beautiful upgrade prompts with tier comparisons

from typing import Optional
from .feature_gate import FeatureGateError


def show_upgrade_prompt_interactive(error: FeatureGateError):
"""
Interactive upgrade prompt with options.

Displays:
- Feature denial reason
- Current vs required tier
- Upgrade benefits
- Pricing comparison
- Alternative suggestions
- Quick action buttons
"""

import textwrap

# ANSI color codes
RED = '\033[91m'
YELLOW = '\033[93m'
GREEN = '\033[92m'
BLUE = '\033[94m'
CYAN = '\033[96m'
BOLD = '\033[1m'
DIM = '\033[2m'
RESET = '\033[0m'

# Clear screen and display prompt
print('\033[2J\033[H') # Clear screen

border = '═' * 79

print(f"""
{BOLD}{BLUE}{border}{RESET}
{BOLD}{BLUE}{' ' * 28}CODITECT License Upgrade{' ' * 28}{RESET}
{BOLD}{BLUE}{border}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {RED}❌ Feature Not Available{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BOLD}Feature:{RESET} {error.usage_info.get('agent_name') or error.usage_info.get('command_name') or 'N/A':<67} {BLUE}{RESET}
{BLUE}{RESET} {BOLD}Reason:{RESET} {error.message:<67} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {YELLOW}Your Tier:{RESET} {BOLD}{error.current_tier.upper():<60}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}Required Tier:{RESET} {BOLD}{error.required_tier.upper():<60}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BOLD}{BLUE}{border}{RESET}
{BOLD}{BLUE}{' ' * 30}Why Upgrade to Pro?{' ' * 30}{RESET}
{BOLD}{BLUE}{border}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}All 52 Specialized Agents{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}AI experts for React, Rust, Python, Cloud Architecture, DevOps, and more{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}All 81 Slash Commands{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}Complete workflow automation: /git-sync, /new-project, /deploy, etc.{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}Unlimited Projects{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}Work on as many projects as you need (Free: 1 project limit){RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}72-Hour Offline Grace Period{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}Work offline for 3 days (Free: 24 hours){RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}10x Higher API Rate Limits{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}1,000 requests/hour vs. 100/hour on Free tier{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}Priority Email Support{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}48-hour response SLA (Free: Community support only){RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {GREEN}{RESET} {BOLD}30-Day Session History{RESET} {BLUE}{RESET}
{BLUE}{RESET} {DIM}4x longer retention vs. Free tier (7 days){RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BOLD}{GREEN}Only $29/month - Cancel anytime{RESET} {BLUE}{RESET}
{BLUE}{RESET} {BLUE}{RESET}
{BOLD}{BLUE}{border}{RESET}

{CYAN}{BOLD}Pricing Options:{RESET}

{BOLD}Pro:{RESET} $29/month - Individual developer, all features
{BOLD}Team:{RESET} $58/seat - 5-100 floating seats, team dashboard
{BOLD}Enterprise:{RESET} Custom - Unlimited seats, SSO, runtime embedding

{BLUE}{BOLD}Quick Actions:{RESET}

{GREEN}[1]{RESET} Upgrade now → https://coditect.ai/pricing
{YELLOW}[2]{RESET} See comparison → Show detailed tier comparison
{CYAN}[3]{RESET} Try alternative → {error.alternative or 'No alternative available'}
{RED}[4]{RESET} Cancel → Continue with current tier

""")

# Interactive choice
try:
choice = input(f"{BOLD}Enter your choice [1-4]:{RESET} ").strip()

if choice == '1':
import webbrowser
webbrowser.open(error.upgrade_url)
print(f"\n{GREEN}✓ Opening upgrade page in browser...{RESET}\n")

elif choice == '2':
print_detailed_tier_comparison()

elif choice == '3':
if error.alternative:
print(f"\n{CYAN}Alternative approach:{RESET} {error.alternative}\n")
else:
print(f"\n{YELLOW}No alternative available for this feature.{RESET}\n")

elif choice == '4':
print(f"\n{DIM}Continuing with {error.current_tier} tier...{RESET}\n")

else:
print(f"\n{RED}Invalid choice. Continuing with {error.current_tier} tier.{RESET}\n")

except KeyboardInterrupt:
print(f"\n\n{DIM}Cancelled. Continuing with {error.current_tier} tier.{RESET}\n")


def print_detailed_tier_comparison():
"""Print comprehensive tier comparison table."""

GREEN = '\033[92m'
YELLOW = '\033[93m'
RED = '\033[91m'
BOLD = '\033[1m'
RESET = '\033[0m'

print(f"""
{BOLD}Complete Tier Comparison:{RESET}

┌──────────────────────────────┬────────────┬─────────────┬─────────────┬──────────────┐
│ Feature │ Free │ Pro │ Team │ Enterprise │
├──────────────────────────────┼────────────┼─────────────┼─────────────┼──────────────┤
{BOLD}Agents{RESET} │ 5 essential│ {GREEN}All 52{RESET}{GREEN}All 52{RESET}{GREEN}All 52+{RESET}
{BOLD}Commands{RESET} │ 10 basic │ {GREEN}All 81{RESET}{GREEN}All 81{RESET}{GREEN}All 81+{RESET}
{BOLD}Skills{RESET} │ 5 basic │ {GREEN}All 26{RESET}{GREEN}All 26{RESET}{GREEN}All 26+{RESET}
{BOLD}Projects{RESET}{RED}1{RESET}{GREEN}Unlimited{RESET}{GREEN}Unlimited{RESET}{GREEN}Unlimited{RESET}
{BOLD}Concurrent Seats{RESET} │ 1 │ 1 │ {GREEN}5-100{RESET}{GREEN}Unlimited{RESET}
{BOLD}Offline Grace{RESET} │ 24h │ {GREEN}72h{RESET} │ 48h │ {GREEN}168h (7d){RESET}
{BOLD}API Rate Limit{RESET} │ 100/hour │ {GREEN}1000/hour{RESET}{GREEN}5000/hour{RESET}{GREEN}Custom{RESET}
{BOLD}Session History{RESET} │ 7 days │ {GREEN}30 days{RESET}{GREEN}90 days{RESET}{GREEN}365 days{RESET}
{BOLD}Team Dashboard{RESET}{RED}{RESET}{RED}{RESET}{GREEN}{RESET}{GREEN}{RESET}
{BOLD}Runtime Embedding{RESET}{RED}{RESET}{RED}{RESET}{RED}{RESET}{GREEN}{RESET}
{BOLD}SSO/SAML{RESET}{RED}{RESET}{RED}{RESET}{RED}{RESET}{GREEN}{RESET}
{BOLD}Custom Agents{RESET}{RED}{RESET}{RED}{RESET}{RED}{RESET}{GREEN}{RESET}
{BOLD}Support{RESET} │ Community │ Email 48h │ Priority 24h│ Dedicated 4h │
{BOLD}SLA Uptime{RESET} │ Best-effort│ 99% │ 99.5% │ 99.9% │
├──────────────────────────────┼────────────┼─────────────┼─────────────┼──────────────┤
{BOLD}Price/Month{RESET}{GREEN}$0{RESET}{YELLOW}$29{RESET}{YELLOW}$58/seat{RESET} │ Custom │
└──────────────────────────────┴────────────┴─────────────┴─────────────┴──────────────┘

{BOLD}Use Cases:{RESET}

{GREEN}Free:{RESET} Students, hobbyists, trying CODITECT
{YELLOW}Pro:{RESET} Individual professional developers
{YELLOW}Team:{RESET} 5-100 person development teams
{YELLOW}Enterprise:{RESET} Large organizations, production embedding

""")

Consequences

Positive

Clear Value Proposition

  • Free tier genuinely useful (not just trial/demo)
  • Pro tier unlocks ALL features (no confusing gradual tiers)
  • Team tier adds collaboration without feature restrictions
  • Enterprise tier provides unique value (runtime embedding, custom development)

Sustainable Freemium Model

  • 5% Free → Pro conversion = $174K ARR per 10K users
  • Project limit (#1 conversion driver) creates natural upgrade motivation
  • Agent/command restrictions showcase advanced capabilities
  • Team tier provides group pricing for organizations

Graceful Degradation

  • Helpful upgrade prompts instead of hard errors
  • Alternative suggestions when features unavailable
  • Transparent limits (no surprise restrictions)
  • Beautiful UI/UX for upgrade flow

Runtime Enforcement

  • Feature gates validated at multiple levels (init, invocation, execution)
  • Cloud KMS signing prevents tampering
  • Offline grace periods enable offline development
  • Local caching reduces network dependency

Competitive Positioning

  • More generous free tier than competitors (5 agents vs. heavily rate-limited)
  • Pro tier pricing competitive ($29 vs. $20-50 market range)
  • Team tier pricing reasonable ($58/seat vs. $75-150 competitors)
  • Enterprise tier provides unique runtime embedding value

Viral Growth Potential

  • Free tier compelling for students/learners
  • Open-source-friendly (community support, transparent limits)
  • Developer-first UX (no aggressive upselling)
  • Word-of-mouth driver (free tier actually works)

Negative

⚠️ Free Tier Support Burden

  • Community support only may frustrate free users
  • Support tickets from free tier with upgrade resistance
  • Mitigation: Comprehensive documentation, community forums

⚠️ Feature Gate Performance Overhead

  • ~5ms latency per feature gate check
  • Cache reduces repeat checks to <1ms
  • Mitigation: Aggressive caching, batch validation

⚠️ Complexity in Maintaining Feature Matrix

  • Must update feature gates when adding new agents/commands
  • Risk of inconsistency between tiers
  • Mitigation: Automated testing, tier validation scripts

⚠️ Piracy Risk

  • Developers may share license keys
  • Free tier may be "good enough" for some pro use cases
  • Mitigation: Hardware fingerprinting, usage monitoring

⚠️ Conversion Optimization Required

  • 5% conversion target may be optimistic
  • Requires A/B testing upgrade prompts
  • Mitigation: Analytics, experimentation framework

⚠️ Upgrade Prompt Fatigue

  • Frequent upgrade prompts may annoy free users
  • Balance between conversion optimization and UX
  • Mitigation: Rate-limit prompts, contextual timing

Neutral

🔄 Tier-Based Pricing Complexity

  • Four tiers more complex than simple Pro/Enterprise
  • Familiar pattern (GitHub, Vercel, etc.)
  • Acceptable: Industry standard approach

🔄 Feature Flag Payload Size

  • JWT payload ~2-3KB (vs. <1KB without feature flags)
  • Negligible network overhead
  • Acceptable: Feature granularity worth payload cost

Alternatives Considered

Alternative 1: Time-Based Trials (No Free Tier)

Implementation:

# 14-day free trial, then paid tiers only
{
'tier': 'trial',
'trial_expires_at': '2025-12-14T00:00:00Z',
'full_features': True # All features during trial
}

Pros:

  • ✅ Higher conversion likelihood (users commit upfront)
  • ✅ Lower support burden (no long-term free users)
  • ✅ Simpler feature matrix (trial = pro tier)

Cons:

  • ❌ No viral growth (trial users don't evangelize)
  • ❌ High churn after trial expires
  • ❌ Barrier to entry (credit card required)
  • ❌ Not competitive (most dev tools have perpetual free tiers)

Rejected Because: Developer tools market expects perpetual free tiers. Trials alone don't drive viral adoption.

Alternative 2: Usage-Based Pricing (No Seat Limits)

Implementation:

# Pay per API call instead of seats
{
'tier': 'usage',
'api_calls_included': 10000,
'overage_price_per_1k': 0.10
}

Pros:

  • ✅ Fair "pay for what you use" model
  • ✅ Scales with actual usage
  • ✅ No seat contention issues

Cons:

  • ❌ Unpredictable billing (developers dislike surprises)
  • ❌ Complex metering infrastructure
  • ❌ Doesn't align with competitive market (seat-based standard)
  • ❌ Hard to price correctly (usage highly variable)

Rejected Because: Developers prefer predictable monthly pricing. Usage-based works for APIs, not development tools.

Alternative 3: Open-Source Core + Paid Extensions

Implementation:

# Core framework open-source (MIT)
# Premium agents/commands proprietary
{
'tier': 'oss',
'premium_features': ['cloud-architect', 'security-specialist']
}

Pros:

  • ✅ Maximum viral adoption (fully open-source)
  • ✅ Community contributions
  • ✅ Trust and transparency

Cons:

  • ❌ Revenue leakage (users fork and remove licensing)
  • ❌ Support burden without revenue
  • ❌ Difficult to enforce premium features
  • ❌ Competitive disadvantage (competitors can copy)

Rejected Because: Not viable for cloud-hosted licensing model. Would work for self-hosted, but conflicts with SaaS business model.

Alternative 4: Single Tier ($29/mo, No Free Tier)

Implementation:

# Only one paid tier, no free option
{
'tier': 'pro',
'price_monthly': 29,
'all_features': True
}

Pros:

  • ✅ Simplest pricing model
  • ✅ Highest ARPU (average revenue per user)
  • ✅ Clear value proposition

Cons:

  • ❌ No viral adoption (no free trial)
  • ❌ High barrier to entry
  • ❌ Can't compete with free alternatives
  • ❌ Slower growth

Rejected Because: Freemium proven model for developer tools. Free tier critical for adoption.

Alternative 5: GitHub Model (All Features Free for Public Repos)

Implementation:

# All features free if project is public
{
'tier': 'free_public',
'project_visibility': 'public',
'all_features': True
}

# Paid tier for private projects
{
'tier': 'pro_private',
'project_visibility': 'private',
'all_features': True
}

Pros:

  • ✅ Aligns with open-source ethos
  • ✅ Viral growth via public projects
  • ✅ Clear upsell (privacy)

Cons:

  • ❌ Most professional work is private
  • ❌ Doesn't align with CODITECT use case (local development)
  • ❌ Hard to enforce (no centralized project hosting)

Rejected Because: CODITECT is local-first tool, not hosted platform. Can't verify project visibility.


Implementation Notes

Free Tier Agent Selection Rationale

Why These 5 Agents?

  1. codebase-locator - Essential for ANY development

    • Use case: File discovery, navigation, search
    • Upgrade driver: Limited to 100 files per search (Pro: unlimited)
  2. codebase-analyzer - Core value proposition

    • Use case: Understand existing codebases
    • Upgrade driver: Single-file analysis only (Pro: cross-file, architecture analysis)
  3. frontend-react-typescript-expert - Most popular framework

    • Use case: React component generation, TypeScript help
    • Upgrade driver: Basic components only (Pro: advanced patterns, optimization, hooks)
  4. rust-expert-developer - Unique value proposition

    • Use case: Rust syntax, ownership, async
    • Upgrade driver: Basic help only (Pro: performance optimization, production patterns)
  5. codi-documentation-writer - Essential for quality

    • Use case: Generate README, API docs
    • Upgrade driver: Markdown only (Pro: multi-format, diagrams, interactive)

Excluded Agents (Drive Upgrades):

  • orchestrator → Team tier (multi-agent workflows = collaboration)
  • cloud-architect → Enterprise tier (production deployment = runtime)
  • security-specialist → Enterprise tier (security audits = compliance)
  • devops-engineer → Pro tier (CI/CD = professional workflows)
  • backend-architect → Pro tier (system design = production apps)
  • qa-test-engineer → Pro tier (testing = quality assurance)

Feature Gate Performance Optimization

Caching Strategy:

from functools import lru_cache
import hashlib
import json

class FeatureGateCache:
"""LRU cache for feature gate checks."""

def __init__(self, maxsize=256):
self.cache = {}
self.maxsize = maxsize
self.hits = 0
self.misses = 0

def cache_key(self, license_key: str, feature_type: str, feature_name: str) -> str:
"""Generate cache key."""
return hashlib.sha256(
f"{license_key}:{feature_type}:{feature_name}".encode()
).hexdigest()[:16]

def get(self, license_key: str, feature_type: str, feature_name: str):
"""Get cached result."""
key = self.cache_key(license_key, feature_type, feature_name)

if key in self.cache:
self.hits += 1
return self.cache[key]

self.misses += 1
return None

def put(self, license_key: str, feature_type: str, feature_name: str, result):
"""Store result in cache."""
key = self.cache_key(license_key, feature_type, feature_name)

# LRU eviction if full
if len(self.cache) >= self.maxsize:
oldest_key = next(iter(self.cache))
del self.cache[oldest_key]

self.cache[key] = result

def stats(self) -> dict:
"""Get cache statistics."""
total = self.hits + self.misses
hit_rate = (self.hits / total * 100) if total > 0 else 0

return {
'hits': self.hits,
'misses': self.misses,
'hit_rate_percent': round(hit_rate, 2),
'size': len(self.cache),
'maxsize': self.maxsize
}


# Global cache instance
_feature_gate_cache = FeatureGateCache(maxsize=256)


def check_agent_cached(gate: FeatureGate, agent_name: str):
"""Check agent with caching."""

# Try cache first
cached = _feature_gate_cache.get(gate.license_key, 'agent', agent_name)

if cached is not None:
return cached

# Cache miss - compute
result = gate.check_agent_allowed(agent_name)

# Store in cache
_feature_gate_cache.put(gate.license_key, 'agent', agent_name, result)

return result

Performance Benchmarks:

# Benchmark feature gate performance
import time

def benchmark_feature_gates():
"""Benchmark feature gate performance."""

# Setup
license_data = {'tier': 'pro', 'features': PRO_TIER_LIMITS, 'license_key': 'BENCH-PRO'}
gate = FeatureGate(license_data)

# Warm up cache
for i in range(100):
gate.check_agent_allowed('codebase-analyzer')

# Benchmark uncached
start = time.time()
for i in range(1000):
gate.check_agent_allowed(f'agent-{i % 52}') # Cycle through agents
uncached_time = (time.time() - start) / 1000 * 1000 # ms per check

# Benchmark cached
start = time.time()
for i in range(1000):
gate.check_agent_allowed('codebase-analyzer') # Same agent (cached)
cached_time = (time.time() - start) / 1000 * 1000 # ms per check

print(f"Uncached check: {uncached_time:.2f}ms")
print(f"Cached check: {cached_time:.2f}ms")
print(f"Speedup: {uncached_time / cached_time:.1f}x")

# Expected results:
# Uncached: ~5ms (hash computation, lookup, decision logic)
# Cached: ~0.5ms (hash lookup only)
# Speedup: 10x

A/B Testing Infrastructure

Upgrade Prompt Variants:

# .coditect/sdk/ab_testing.py
# A/B test different upgrade prompt strategies

import hashlib
from enum import Enum

class UpgradePromptVariant(Enum):
"""Upgrade prompt experiment variants."""

AGGRESSIVE = 'aggressive' # Immediate blocking modal
MODERATE = 'moderate' # Inline banner with call-to-action
PASSIVE = 'passive' # Console message only
EDUCATIONAL = 'educational' # Feature comparison table
SOCIAL_PROOF = 'social_proof' # Testimonials + pricing


def get_prompt_variant(user_id: str, feature_name: str) -> UpgradePromptVariant:
"""
Deterministic A/B test variant assignment.

Args:
user_id: User identifier (email hash)
feature_name: Feature being gated

Returns:
Assigned variant
"""

# Consistent hash for stable assignment
hash_input = f"{user_id}:{feature_name}:upgrade_prompt_v1"
hash_value = int(hashlib.sha256(hash_input.encode()).hexdigest(), 16)

# 5-way split (20% each variant)
variant_index = hash_value % 5

variants = list(UpgradePromptVariant)
return variants[variant_index]


def show_upgrade_prompt_ab(
error: FeatureGateError,
user_id: str
):
"""Show upgrade prompt with A/B testing."""

variant = get_prompt_variant(user_id, error.usage_info.get('agent_name', 'unknown'))

# Log variant assignment for analytics
log_ab_test_event(
experiment='upgrade_prompt',
variant=variant.value,
user_id=user_id,
feature=error.usage_info.get('agent_name'),
tier=error.current_tier
)

if variant == UpgradePromptVariant.AGGRESSIVE:
show_blocking_modal(error)

elif variant == UpgradePromptVariant.MODERATE:
show_inline_banner(error)

elif variant == UpgradePromptVariant.PASSIVE:
show_console_message(error)

elif variant == UpgradePromptVariant.EDUCATIONAL:
show_feature_comparison(error)

elif variant == UpgradePromptVariant.SOCIAL_PROOF:
show_testimonials_pricing(error)


def log_ab_test_event(
experiment: str,
variant: str,
user_id: str,
**metadata
):
"""Log A/B test event to analytics."""

import requests
import os

# Send to analytics backend
analytics_url = os.getenv('CODITECT_ANALYTICS_URL', 'https://analytics.coditect.ai/v1/events')

try:
requests.post(
analytics_url,
json={
'event_type': 'ab_test_impression',
'experiment': experiment,
'variant': variant,
'user_id': user_id,
'timestamp': datetime.now(timezone.utc).isoformat(),
'metadata': metadata
},
timeout=2 # Non-blocking
)
except Exception as e:
# Silent failure - analytics shouldn't break user experience
pass

Conversion Tracking:

# Track upgrade conversions by variant

def track_upgrade_conversion(
user_id: str,
from_tier: str,
to_tier: str,
variant: str
):
"""Track successful upgrade conversion."""

log_ab_test_event(
experiment='upgrade_prompt',
variant=variant,
user_id=user_id,
event_type='conversion',
from_tier=from_tier,
to_tier=to_tier
)


# Analytics query to measure conversion rates by variant:
#
# SELECT
# variant,
# COUNT(DISTINCT CASE WHEN event_type = 'ab_test_impression' THEN user_id END) AS impressions,
# COUNT(DISTINCT CASE WHEN event_type = 'conversion' THEN user_id END) AS conversions,
# ROUND(COUNT(DISTINCT CASE WHEN event_type = 'conversion' THEN user_id END) /
# COUNT(DISTINCT CASE WHEN event_type = 'ab_test_impression' THEN user_id END) * 100, 2) AS conversion_rate_percent
# FROM ab_test_events
# WHERE experiment = 'upgrade_prompt'
# AND timestamp > DATE_SUB(CURRENT_DATE(), INTERVAL 30 DAY)
# GROUP BY variant
# ORDER BY conversion_rate_percent DESC;

Mermaid Diagrams

Feature Gate Flow:

Tier Upgrade Journey:

License Validation Flow:


  • ADR-001: Floating Licenses vs. Node-Locked Licenses (defines tier structure and offline grace periods)
  • ADR-005: Builder vs. Runtime Licensing Model (Enterprise tier runtime embedding)
  • ADR-013: Stripe Integration (upgrade funnel and payment processing) - To be created
  • ADR-014: Usage Analytics and Telemetry (A/B testing infrastructure) - To be created
  • ADR-015: Pricing Strategy and Tier Optimization (market research and pricing psychology) - To be created

Pricing Strategy

Free Tier Economics

Goal: Viral adoption with 5% conversion to paid tiers

Projections (10,000 Free Tier Users):

MetricValueCalculation
Free Users10,000Target user base
Conversion Rate5%Industry benchmark for dev tools
Pro Conversions50010,000 × 5%
Pro MRR$14,500500 × $29
Pro ARR$174,000$14,500 × 12

Additional Revenue Streams:

  • Team tier conversions: 10% of Pro users upgrade to Team (50 teams × $290 = $14,500/mo)
  • Enterprise tier: 2 customers × $5K/mo = $10K/mo
  • Total ARR: $174K + $174K + $120K = $468K ARR from 10K free users

CAC (Customer Acquisition Cost):

  • Organic/viral: $0 (free tier drives word-of-mouth)
  • Paid ads (optional): $50/signup → $1,000 CAC for Pro conversion
  • Target: <$500 CAC for profitable unit economics

LTV (Lifetime Value):

  • Pro user: $29/mo × 24 months average = $696 LTV
  • Team user: $290/mo × 36 months average = $10,440 LTV per team
  • Enterprise user: $5K/mo × 48 months = $240K LTV

LTV:CAC Ratios:

  • Pro: $696 / $500 = 1.4x (acceptable, improves with retention)
  • Team: $10,440 / $500 = 20x (excellent)
  • Enterprise: $240K / $10K = 24x (exceptional)

Pro Tier Pricing Rationale

$29/month Pricing:

Competitive Analysis:

ProductPrice/MonthFeatures
GitHub Copilot$10Code completion only
Cursor Pro$20AI code editor
Claude Pro$20LLM access
JetBrains AI$10IDE integration
CODITECT Pro$2952 agents + 81 commands + complete framework

Value Justification:

  • Time Savings: 10 hours/month × $50/hour = $500 value
  • ROI: $500 / $29 = 17x return on investment
  • Positioning: Premium tier (more comprehensive than competitors)
  • Willingness to Pay: Developers spend $20-50/mo on productivity tools

Pricing Psychology:

  • $29 < $30 (perceived as "20s" not "30s")
  • Annual discount: $29 × 12 = $348 → offer $299/year (14% discount)
  • Monthly flexibility (cancel anytime) reduces commitment friction

Team Tier Pricing Rationale

$58/seat/month Pricing:

Competitive Analysis:

ProductPrice/Seat/MonthFeatures
GitHub Team$4Repository collaboration
Vercel Team$20Deployment platform
GitLab Premium$29DevOps platform
JetBrains Team$65IDE suite
CODITECT Team$58Floating seats + team dashboard

Value Justification:

  • Individual Pro: $29/mo (fixed seat)
  • Team Sharing: $58/mo (floating seat) = 2x Pro price for flexibility
  • Team Productivity: 5-seat team saves 50 hours/month collectively = $2,500 value
  • ROI: $2,500 / $290 (5 seats) = 8.6x return

Pricing Structure:

  • Minimum: 5 seats × $58 = $290/month
  • Scale: Linear ($58/seat regardless of team size)
  • Maximum: 100 seats (Enterprise tier beyond this)
  • Annual Discount: $290 × 12 = $3,480 → $2,999/year (14% discount)

Team Tier Adoption Drivers:

  1. Seat contention (Free tier: 1 seat only)
  2. Team collaboration (dashboard, usage analytics)
  3. Cost savings vs. individual Pro licenses (10 users: $290 Team vs. $290 Pro = break-even, but floating seats reduce waste)

Enterprise Tier Pricing Rationale

Custom Pricing Model:

Base Pricing:

  • Minimum: $299/month base fee
  • Seats: Unlimited floating (fair use policy)
  • Runtime: $0.10/1K API calls OR 3-5% revenue share
  • Custom Development: $10K-50K one-time

Revenue Scenarios:

Scenario 1: SaaS Application Embedding (100K users)

  • Base: $299/mo
  • Runtime API calls: 100K users × 10 calls/month = 1M calls
  • Runtime fee: 1M / 1K × $0.10 = $100/mo
  • Total: $399/month

Scenario 2: Large Enterprise (500 developers)

  • Base: $299/mo
  • Unlimited seats (500 developers) = no additional seat fees
  • Runtime: 10M API calls/month = 10K × $0.10 = $1,000/mo
  • Total: $1,299/month

Scenario 3: High-Volume SaaS (1M MAU)

  • Base: $299/mo
  • Revenue share: $500K/month revenue × 3% = $15,000/mo
  • Total: $15,299/month (likely negotiate to 2% = $10,299/mo)

Value Justification:

  • Runtime Embedding: Enables product differentiation (AI-powered features)
  • Custom Agents: Proprietary competitive advantage
  • SLA: 99.9% uptime = $1M+ opportunity cost if down
  • Dedicated Support: 4-hour SLA prevents lost productivity

Negotiation Strategy:

  • Start high ($299 base + usage)
  • Volume discounts for high API usage
  • Revenue share cap for predictability
  • Multi-year contracts (discount 20% for 3-year)

Pricing Optimization Strategy

A/B Testing Plan:

  1. Test Pro Tier Pricing - $29 vs. $34 vs. $24

    • Hypothesis: $29 optimal (psychological threshold)
    • Duration: 3 months
    • Sample size: 1,000 signups
  2. Test Team Tier Seat Pricing - $58 vs. $50 vs. $65

    • Hypothesis: $58 balances value and profit margin
    • Duration: 3 months
    • Sample size: 100 teams
  3. Test Annual Discount - 10% vs. 14% vs. 20%

    • Hypothesis: 14% optimal for cash upfront vs. commitment
    • Duration: 6 months
    • Sample size: 500 annual purchases
  4. Test Upgrade Prompt Variants (from A/B testing section)

    • Hypothesis: Educational variant drives highest conversion
    • Duration: 6 months
    • Sample size: 10,000 free tier users

Pricing Experiments:

# Pricing experiment tracking

class PricingExperiment:
"""Track pricing A/B test experiments."""

def __init__(self, name: str, variants: List[Dict[str, Any]]):
self.name = name
self.variants = variants
self.results = {}

def assign_variant(self, user_id: str) -> Dict[str, Any]:
"""Assign user to pricing variant."""
hash_value = int(hashlib.sha256(f"{user_id}:{self.name}".encode()).hexdigest(), 16)
variant_index = hash_value % len(self.variants)
return self.variants[variant_index]

def record_conversion(self, user_id: str, tier: str, price: float):
"""Record successful upgrade."""
variant = self.assign_variant(user_id)
variant_name = variant['name']

if variant_name not in self.results:
self.results[variant_name] = {
'impressions': 0,
'conversions': 0,
'revenue': 0.0
}

self.results[variant_name]['conversions'] += 1
self.results[variant_name]['revenue'] += price

def record_impression(self, user_id: str):
"""Record pricing page view."""
variant = self.assign_variant(user_id)
variant_name = variant['name']

if variant_name not in self.results:
self.results[variant_name] = {
'impressions': 0,
'conversions': 0,
'revenue': 0.0
}

self.results[variant_name]['impressions'] += 1

def analyze_results(self) -> Dict[str, Any]:
"""Analyze experiment results."""
analysis = {}

for variant_name, data in self.results.items():
conversion_rate = (data['conversions'] / data['impressions'] * 100
if data['impressions'] > 0 else 0)

avg_revenue = (data['revenue'] / data['conversions']
if data['conversions'] > 0 else 0)

analysis[variant_name] = {
'impressions': data['impressions'],
'conversions': data['conversions'],
'conversion_rate_percent': round(conversion_rate, 2),
'total_revenue': round(data['revenue'], 2),
'avg_revenue_per_conversion': round(avg_revenue, 2)
}

return analysis


# Example: Pro tier pricing experiment
pro_pricing_experiment = PricingExperiment(
name='pro_tier_pricing_v1',
variants=[
{'name': 'control_$29', 'price': 29},
{'name': 'variant_$24', 'price': 24},
{'name': 'variant_$34', 'price': 34}
]
)

# Usage in checkout flow:
variant = pro_pricing_experiment.assign_variant(user_id)
display_price = variant['price']

# On conversion:
pro_pricing_experiment.record_conversion(user_id, 'pro', display_price)

Pricing Page Optimization

Conversion-Optimized Pricing Table:

<!-- Pricing page with conversion optimization -->

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>CODITECT Pricing - Transparent & Fair</title>
<style>
.pricing-container {
display: flex;
justify-content: center;
gap: 30px;
padding: 50px;
}

.pricing-card {
border: 2px solid #e0e0e0;
border-radius: 12px;
padding: 40px;
width: 300px;
position: relative;
transition: transform 0.3s, box-shadow 0.3s;
}

.pricing-card:hover {
transform: translateY(-10px);
box-shadow: 0 12px 24px rgba(0,0,0,0.15);
}

.pricing-card.recommended {
border-color: #0066cc;
border-width: 3px;
}

.pricing-card.recommended::before {
content: "MOST POPULAR";
position: absolute;
top: -15px;
left: 50%;
transform: translateX(-50%);
background: #0066cc;
color: white;
padding: 5px 20px;
border-radius: 20px;
font-size: 12px;
font-weight: bold;
}

.tier-name {
font-size: 24px;
font-weight: bold;
margin-bottom: 10px;
}

.tier-price {
font-size: 48px;
font-weight: bold;
color: #0066cc;
}

.tier-price-period {
font-size: 16px;
color: #666;
}

.tier-features {
list-style: none;
padding: 0;
margin: 30px 0;
}

.tier-features li {
padding: 10px 0;
border-bottom: 1px solid #e0e0e0;
}

.tier-features li:last-child {
border-bottom: none;
}

.feature-check {
color: #00cc66;
margin-right: 10px;
}

.feature-cross {
color: #cc0000;
margin-right: 10px;
}

.cta-button {
width: 100%;
padding: 15px;
background: #0066cc;
color: white;
border: none;
border-radius: 8px;
font-size: 18px;
font-weight: bold;
cursor: pointer;
transition: background 0.3s;
}

.cta-button:hover {
background: #0052a3;
}

.cta-button.secondary {
background: white;
color: #0066cc;
border: 2px solid #0066cc;
}

.cta-button.secondary:hover {
background: #f0f8ff;
}
</style>
</head>
<body>
<div class="pricing-container">
<!-- Free Tier -->
<div class="pricing-card">
<div class="tier-name">Free</div>
<div class="tier-price">$0<span class="tier-price-period">/month</span></div>

<ul class="tier-features">
<li><span class="feature-check"></span> 5 Essential Agents</li>
<li><span class="feature-check"></span> 10 Basic Commands</li>
<li><span class="feature-check"></span> 1 Project</li>
<li><span class="feature-check"></span> 24h Offline Grace</li>
<li><span class="feature-check"></span> Community Support</li>
<li><span class="feature-cross"></span> Advanced Agents</li>
<li><span class="feature-cross"></span> Unlimited Projects</li>
</ul>

<button class="cta-button secondary">Get Started Free</button>
</div>

<!-- Pro Tier (Recommended) -->
<div class="pricing-card recommended">
<div class="tier-name">Pro</div>
<div class="tier-price">$29<span class="tier-price-period">/month</span></div>

<ul class="tier-features">
<li><span class="feature-check"></span> All 52 Agents</li>
<li><span class="feature-check"></span> All 81 Commands</li>
<li><span class="feature-check"></span> Unlimited Projects</li>
<li><span class="feature-check"></span> 72h Offline Grace</li>
<li><span class="feature-check"></span> Priority Email Support</li>
<li><span class="feature-check"></span> 10x Higher API Limits</li>
<li><span class="feature-check"></span> 30-Day Session History</li>
</ul>

<button class="cta-button">Start Pro Trial</button>
<p style="text-align: center; color: #666; font-size: 14px; margin-top: 10px;">
14-day free trial • Cancel anytime
</p>
</div>

<!-- Team Tier -->
<div class="pricing-card">
<div class="tier-name">Team</div>
<div class="tier-price">$58<span class="tier-price-period">/seat/month</span></div>

<ul class="tier-features">
<li><span class="feature-check"></span> Everything in Pro</li>
<li><span class="feature-check"></span> 5-100 Floating Seats</li>
<li><span class="feature-check"></span> Team Dashboard</li>
<li><span class="feature-check"></span> Usage Analytics</li>
<li><span class="feature-check"></span> Admin Controls</li>
<li><span class="feature-check"></span> Priority 24h Support</li>
<li><span class="feature-check"></span> 90-Day Session History</li>
</ul>

<button class="cta-button">Contact Sales</button>
</div>

<!-- Enterprise Tier -->
<div class="pricing-card">
<div class="tier-name">Enterprise</div>
<div class="tier-price">Custom<span class="tier-price-period"></span></div>

<ul class="tier-features">
<li><span class="feature-check"></span> Everything in Team</li>
<li><span class="feature-check"></span> Unlimited Seats</li>
<li><span class="feature-check"></span> Runtime Embedding</li>
<li><span class="feature-check"></span> SSO/SAML</li>
<li><span class="feature-check"></span> Custom Agents</li>
<li><span class="feature-check"></span> Dedicated Support (4h SLA)</li>
<li><span class="feature-check"></span> 99.9% SLA Uptime</li>
</ul>

<button class="cta-button secondary">Schedule Demo</button>
</div>
</div>
</body>
</html>

References


Last Updated: 2025-11-30 Owner: Architecture Team, Product Team, Finance Team Review Cycle: Monthly (pricing optimization) + Quarterly (tier structure)