ThinkRail's Agent Skill System: How JetBrains Built Self-Extending IDE Capabilities Around Living Specs JetBrains shipped ThinkRail, an IDE built around a self-extending agent skill system in which the pi coding agent writes, tests, and registers its own tools. Each skill is generated against "living specs" that carry real tool contracts, tested inside a disposable git worktree before registration, and gated by workspace compatibility and privilege boundaries so the agent cannot self-approve network access. The TypeScript project reached 5,016 GitHub stars and the top of GitHub Trending. JetBrains shipped ThinkRail as an IDE where agents can write their own capabilities instead of waiting for plugin updates. The project hit 5,016 stars and 1 on GitHub Trending TypeScript by combining isolated workspaces, living specs as durable project knowledge, and a skill system that lets the pi coding agent extend itself based on how you actually work. This is not a wrapper around an LLM chat interface. ThinkRail is a full IDE built around agent-extensibility as a core feature. The agent can create tools, register them as reusable skills, and invoke them across workspace boundaries without breaking existing state. ThinkRail runs on three layers: The pi coding agent sits at the center. It decides when to invoke an existing skill versus writing a new one based on the task context and available specs. Each workspace is a separate git worktree. The agent can: This prevents a newly-created skill from corrupting the main branch or interfering with other active workspaces. If a skill fails, the worktree is disposable. You lose the experiment, not the project. Traditional documentation goes stale. Living specs are different: When the agent needs to create a new skill, it queries the spec registry for relevant context. The spec provides: This makes specs a durable knowledge substrate instead of a brittle reference. The agent does not hallucinate tool signatures because the spec includes the actual contract. The skill registry is a lookup table mapping task patterns to executable capabilities. When the agent receives a request, it: | Condition | Action | Rationale | |---|---|---| | Exact skill match | Invoke existing skill | Reuse proven capability | | Partial match + simple delta | Compose existing skills | Avoid redundant code | | No match + spec exists | Generate new skill from spec | Leverage durable knowledge | | No match + no spec | Prompt user for clarification | Prevent hallucinated tools | | Skill fails in test | Rollback and log | Protect workspace state | The registry does not blindly invoke. It checks workspace compatibility first. A skill written for a Node.js project will not run in a Python workspace, even if the task description matches. Here is how the agent creates a new skill: // Simplified skill generation flow async function generateSkill intent: string, workspace: Workspace : Promise