Technical Analysis of the HagiCode Skill System: Building a Scalable AI Skill Management Platform
编辑此页Technical Analysis of the HagiCode Skill System: Building a Scalable AI Skill Management Platform
Section titled “Technical Analysis of the HagiCode Skill System: Building a Scalable AI Skill Management Platform”This article takes an in-depth look at the architecture and implementation of the Skill management system in the HagiCode project, covering the technical details behind four core capabilities: local global management, marketplace search, intelligent recommendations, and trusted provider management.
Background
Section titled “Background”In the field of AI coding assistants, how to extend the boundaries of AI capabilities has always been a core question. Claude Code itself is already strong at code assistance, but different development teams and different technology stacks often need specialized capabilities for specific scenarios, such as handling Docker deployments, database optimization, or frontend component generation. That is exactly where a Skill system becomes especially important.
During the development of the HagiCode project, we ran into a similar challenge: how do we let Claude Code “learn” new professional skills like a person would, while still maintaining a solid user experience and good engineering maintainability? This problem is both hard and simple in its own way. Around that question, we designed and implemented a complete Skill management system.
This article walks through the technical architecture and core implementation of the system in detail. It is intended for developers interested in AI extensibility and command-line tool integration. It might be useful to you, or it might not, but at least it is written down now.
About HagiCode
Section titled “About HagiCode”The approach shared in this article comes from our practical experience in the HagiCode project. HagiCode is an open-source AI coding assistant project designed to help development teams improve engineering efficiency. The project’s stack includes ASP.NET Core, the Orleans distributed framework, a TanStack Start + React frontend, and the Skill management subsystem introduced in this article.
The GitHub repository is HagiCode-org/site. If you find the technical approach in this article valuable, feel free to give it a Star. More Stars tend to improve the mood, after all.
System Architecture Overview
Section titled “System Architecture Overview”The Skill system uses a frontend-backend separated architecture. There is nothing especially mysterious about that.
Frontend uses TanStack Start + React to build the user interface, with Redux Toolkit managing state. The four main capabilities map directly to four Tab components: Local Skills, Skill Gallery, Intelligent Recommendations, and Trusted Providers. In the end, the design is mostly about making the user experience better.
Backend is based on ASP.NET Core + ABP Framework, using Orleans Grain for distributed state management. The online API client wraps the IOnlineApiClient interface to communicate with the remote skill catalog service.
The overall architectural principle is to separate command execution from business logic. Through the adapter pattern, the implementation details of npm/npx command execution are hidden inside independent modules. After all, nobody really wants command-line calls scattered all over the codebase.
Core Capability 1: Local Global Management
Section titled “Core Capability 1: Local Global Management”Local global management is the most basic module. It is responsible for listing installed skills and supporting uninstall operations. There is nothing overly complicated here; it is mostly about doing the basics well.
Technical Approach
Section titled “Technical Approach”The implementation lives in LocalSkillsTab.tsx and LocalSkillCommandAdapter.cs. The core idea is to wrap the npx skills command, parse its JSON output, and convert it into internal data structures. It sounds simple, and in practice it mostly is.
public async Task<IReadOnlyList<LocalSkillInventoryResponseDto>> GetLocalSkillsAsync( CancellationToken cancellationToken = default){ var result = await _commandAdapter.ListGlobalSkillsAsync(cancellationToken); return result.Skills.Select(skill => new LocalSkillInventoryResponseDto { Name = skill.Name, Version = skill.Version, Source = skill.Source, InstalledPath = skill.InstalledPath, Description = skill.Description }).ToList();}The data flow is very clear: the frontend sends a request -> SkillGalleryAppService receives it -> LocalSkillCommandAdapter executes the npx command -> the JSON result is parsed -> a DTO is returned. Each step follows naturally from the previous one.
Skill uninstallation uses the npx skills remove -g <skillName> -y command, and the system automatically handles dependencies and cleanup. Installation metadata is stored in managed-install.json inside the skill directory, recording information such as install time and source version for later updates and auditing. Some things are simply worth recording.
Installation Flow in Detail
Section titled “Installation Flow in Detail”Skill installation requires several coordinated steps. In truth, it is not especially complicated:
public async Task<SkillInstallResultDto> InstallAsync( SkillInstallRequestDto request, CancellationToken cancellationToken = default){ // 1. Normalize the installation reference var normalized = _referenceNormalizer.Normalize( request.SkillId, request.Source, request.SkillSlug, request.Version);
// 2. Check prerequisites await _prerequisiteChecker.CheckAsync(cancellationToken);
// 3. Acquire installation lock using var installLock = await _lockProvider.AcquireAsync(normalized.SkillId);
// 4. Execute installation command var result = await _installCommandRunner.ExecuteAsync( new SkillInstallCommandExecutionRequest { Command = $"npx skills add {normalized.FullReference} -g -y", Timeout = TimeSpan.FromMinutes(4) }, cancellationToken);
// 5. Persist installation metadata await _metadataStore.WriteAsync(normalized.SkillPath, request);
return new SkillInstallResultDto { Success = result.Success };}Several key design patterns are used here: the reference normalizer converts different input formats, such as tanweai/pua and @opencode/docker-skill, into a unified internal representation; the installation lock mechanism ensures only one installation operation can run for the same skill at a time; and streaming output pushes installation progress to the frontend in real time through Server-Sent Events, so users can watch terminal-like logs as they happen.
In the end, all of these patterns are there for one purpose: to keep the system simpler to use and maintain.
Core Capability 2: Marketplace Search
Section titled “Core Capability 2: Marketplace Search”Marketplace search lets users discover and install skills from the community. One person’s ability is always limited; collective knowledge goes much further.
Technical Approach
Section titled “Technical Approach”The search feature relies on the online API https://api.hagicode.com/v1/skills/search. To improve response speed, the system implements caching. Cache is a bit like memory: if you keep useful things around, you do not have to think so hard the next time.
private async Task<IReadOnlyList<SkillGallerySkillDto>> SearchCatalogAsync( string query, CancellationToken cancellationToken, IReadOnlySet<string>? allowedSources = null){ var cacheKey = $"skill_search:{query}:{string.Join(",", allowedSources ?? Array.Empty<string>())}";
if (_memoryCache.TryGetValue(cacheKey, out var cached)) return (IReadOnlyList<SkillGallerySkillDto>)cached!;
var response = await _onlineApiClient.SearchAsync( new SearchSkillsRequest { Query = query, Limit = _options.LimitPerQuery, }, cancellationToken);
var results = response.Skills .Where(skill => allowedSources is null || allowedSources.Contains(skill.Source)) .Select(skill => new SkillGallerySkillDto { ... }) .ToList();
_memoryCache.Set(cacheKey, results, TimeSpan.FromMinutes(10)); return results;}Search results support filtering by trusted sources, so users only see skill sources they trust. Seed queries such as popular and recent are used to initialize the catalog, allowing users to see recommended popular skills the first time they open it. First impressions still matter.
Core Capability 3: Intelligent Recommendations
Section titled “Core Capability 3: Intelligent Recommendations”Intelligent recommendations are the most complex part of the system. They can automatically recommend the most suitable skills based on the current project context. Complex as it is, it is still worth building.
Recommendation Flow
Section titled “Recommendation Flow”The full recommendation flow is divided into five stages:
1. Build project context ↓2. AI generates search queries ↓3. Search the online catalog in parallel ↓4. AI ranks the candidates ↓5. Return the recommendation listFirst, the system analyzes characteristics such as the project’s technology stack, programming languages, and domain structure to build a “project profile.” That profile is a bit like a resume, recording the key traits of the project.
Then an AI Grain is used to generate targeted search queries. This design is actually quite interesting: instead of directly asking the AI, “What skills should I recommend?”, we first ask it to think about “What search terms are likely to find relevant skills?” Sometimes the way you ask the question matters more than the answer itself:
var queryGeneration = await aiGrain.GenerateSkillRecommendationQueriesAsync( projectContext, // Project context locale, // User language preference maxQueries, // Maximum number of queries effectiveSearchHero); // AI model selectionNext, those search queries are executed in parallel to gather a candidate skill list. Parallel processing is, at the end of the day, just a way to save time.
Finally, another AI Grain ranks the candidate skills. This step considers factors such as skill relevance to the project, trust status, and user historical preferences:
var ranking = await aiGrain.RankSkillRecommendationsAsync( projectContext, candidates, installedSkillNames, locale, maxRecommendations, effectiveRankingHero);
response.Items = MergeRecommendations(projectContext, candidates, ranking, maxRecommendations);Fallback Mechanism
Section titled “Fallback Mechanism”AI models can respond slowly or become temporarily unavailable. Even the best systems stumble sometimes. For that reason, the system includes a deterministic fallback mechanism: when the AI service is unavailable, it uses a rule-based heuristic algorithm to generate recommendations, such as inferring likely required skills from dependencies in package.json.
Put plainly, this fallback mechanism is simply a backup plan for the system.
Core Capability 4: Trusted Provider Management
Section titled “Core Capability 4: Trusted Provider Management”Trusted provider management allows users to control which skill sources are considered trustworthy. Trust is still something users should be able to define for themselves.
Matching Rules
Section titled “Matching Rules”Trusted providers support two matching rules: exact match (exact) and prefix match (prefix).
public static TrustedSkillProviderResolutionSnapshot Resolve( TrustedSkillProviderSnapshot snapshot, string source){ var normalizedSource = Normalize(source);
foreach (var entry in snapshot.Entries.OrderBy(e => e.SortOrder)) { if (!entry.IsEnabled) continue;
foreach (var rule in entry.MatchRules) { bool isMatch = rule.MatchType switch { TrustedSkillProviderMatchRuleType.Exact => string.Equals(normalizedSource, Normalize(rule.Value), StringComparison.OrdinalIgnoreCase), TrustedSkillProviderMatchRuleType.Prefix => normalizedSource.StartsWith(Normalize(rule.Value) + "/", StringComparison.OrdinalIgnoreCase), _ => false };
if (isMatch) return new TrustedSkillProviderResolutionSnapshot { IsTrustedSource = true, ProviderId = entry.ProviderId, DisplayName = entry.DisplayName }; } }
return new TrustedSkillProviderResolutionSnapshot { IsTrustedSource = false };}Built-in trusted providers include well-known organizations and projects such as Vercel, Azure, anthropics, Microsoft, and browser-use. Custom providers can be added through configuration files by specifying a provider ID, display name, badge label, matching rules, and more. The world is large enough that only trusting a few built-ins would never be enough.
Persistence Implementation
Section titled “Persistence Implementation”Trusted configuration is persisted using an Orleans Grain:
public class TrustedSkillProviderGrain : Grain<TrustedSkillProviderState>, ITrustedSkillProviderGrain{ public async Task UpdateConfigurationAsync(TrustedSkillProviderSnapshot snapshot) { State.Snapshot = snapshot; await WriteStateAsync(); }
public Task<TrustedSkillProviderSnapshot> GetConfigurationAsync() { return Task.FromResult(State.Snapshot); }}The benefit of this approach is that configuration changes are automatically synchronized across all nodes, without any need to refresh caches manually. Automation is, ultimately, about letting people worry less.
Key Technical Design
Section titled “Key Technical Design”Command Execution Adapter Pattern
Section titled “Command Execution Adapter Pattern”The Skill system needs to execute various npx commands. If that logic were scattered everywhere, the code would quickly become difficult to maintain. That is why we designed an adapter interface. Design patterns, in the end, exist to make code easier to maintain:
public interface ISkillInstallCommandRunner{ Task<SkillInstallCommandExecutionResult> ExecuteAsync( SkillInstallCommandExecutionRequest request, CancellationToken cancellationToken = default);}Different commands have different executor implementations, but all of them implement the same interface, making testing and replacement straightforward.
SSE Streaming Output
Section titled “SSE Streaming Output”Installation progress is pushed to the frontend in real time through Server-Sent Events:
public async Task InstallWithProgressAsync( SkillInstallRequestDto request, IServerStreamWriter<SkillInstallProgressEventDto> stream, CancellationToken cancellationToken){ var process = new Process { StartInfo = new ProcessStartInfo { FileName = "npx", Arguments = $"skills add {request.FullReference} -g -y", RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false } };
process.OutputDataReceived += async (sender, e) => { await stream.WriteAsync(new SkillInstallProgressEventDto { EventType = "output", Data = e.Data ?? string.Empty }); };
process.Start(); process.BeginOutputReadLine(); await process.WaitForExitAsync(cancellationToken);}On the frontend, users can see terminal-like output in real time, which makes the experience very intuitive. Real-time feedback helps people feel at ease.
Practical Guide
Section titled “Practical Guide”Installing a Community Skill
Section titled “Installing a Community Skill”Take installing the pua skill as an example (it is a popular community skill):
- Open the Skills drawer and switch to the
Skill Gallerytab - Enter
puain the search box - Click the search result to view the skill details
- Click the
Installbutton - Switch to the
Local Skillstab to confirm the installation succeeded
The installation command is npx skills add tanweai/pua -g -y, and the system handles all the details automatically. There are not really that many steps once you take them one by one.
Adding a Custom Trusted Source
Section titled “Adding a Custom Trusted Source”If your team has its own skill repository, you can add it as a trusted source:
providerId: "my-team"displayName: "My Team Skills"badgeLabel: "MyTeam"isEnabled: truesortOrder: 100matchRules: - matchType: "prefix" value: "my-team/" - matchType: "exact" value: "my-team/special-skill"This way, all skills from your team will display a trusted badge, making users more comfortable installing them. Labels and signals do help people feel more confident.
Skill Development Basics
Section titled “Skill Development Basics”Creating a custom skill requires the following structure:
my-skill/├── SKILL.md # Skill metadata (YAML front matter)├── index.ts # Skill entry point├── agents/ # Supported agent configuration└── references/ # Reference resourcesAn example SKILL.md format:
---name: my-skilldescription: A brief description of what this skill does---
# My Skill
Detailed documentation...- Network requirements: skill search and installation require access to
api.hagicode.comand the npm registry - Node.js version: Node.js 18 or later is recommended
- Permission requirements: global npm installation permissions are required
- Concurrency control: only one install or uninstall operation can run for the same skill at a time
- Timeout settings: the default timeout for installation is 4 minutes, but complex scenarios may require adjustment
These notes exist, ultimately, to help things go smoothly.
Conclusion
Section titled “Conclusion”This article introduced the complete implementation of the Skill management system in the HagiCode project. Through a frontend-backend separated architecture, the adapter pattern, Orleans-based distributed state management, and related techniques, the system delivers:
- Local global management: a unified skill management interface built by wrapping
npx skillscommands - Marketplace search: rapid discovery of community skills through the online API and caching mechanisms
- Intelligent recommendations: AI-powered skill recommendations based on project context
- Trust management: a flexible configuration system that lets users control trust boundaries
This design approach is not only applicable to Skill management. It is also useful as a reference for any scenario that needs to integrate command-line tools while balancing local storage and online services.
If this article helped you, feel free to give us a Star on GitHub: github.com/HagiCode-org/site. You can also visit the official site to learn more: hagicode.com.
You may think this system is well designed, or you may not. Either way, that is fine. Once code is written, someone will use it, and someone will not.
References
Section titled “References”- HagiCode project repository: github.com/HagiCode-org/site
- HagiCode official site: hagicode.com
- Claude Code official Skill documentation: docs.anthropic.com
- Orleans framework documentation: dotnet.github.io/orleans
- TanStack Start: tanstack.com/start
Copyright Notice
Section titled “Copyright Notice”Thank you for reading. If you found this article useful, feel free to like, bookmark, and share it. This content was produced with AI-assisted collaboration, and the final content was reviewed and approved by the author.
- Author: newbe36524
- Original link: https://docs.hagicode.com/blog/2026-03-24-hagicode-skill-system-technical-analysis/
- Copyright notice: Unless otherwise stated, all blog posts on this site are licensed under BY-NC-SA. Please include the source when reposting.