Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "intility",
"description": "Claude Code plugins from Intility — tools for the Intility Developer Platform.",
"owner": {
"name": "Intility",
"email": "devinfra@intility.no"
},
"plugins": [
{
"name": "cust-devplatform-plugin",
"source": "./",
"description": "A friendly companion for getting an app running on the Intility Developer Platform. Helps you create a cluster, deploy a containerized app, expose it on a URL, and update it later — without needing prior Kubernetes experience."
}
]
}
1 change: 1 addition & 0 deletions .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"name": "cust-devplatform-plugin",
"displayName": "Intility Developer Platform",
"version": "0.1.0",
"description": "A friendly companion for getting an app running on the Intility Developer Platform. Helps you create a cluster, deploy a containerized app, expose it on a URL, and update it later — without needing prior Kubernetes experience.",
"author": {
Expand Down
6 changes: 6 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
18 changes: 18 additions & 0 deletions .github/workflows/release-please.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: release-please

on:
push:
branches: [main]

permissions:
contents: write
pull-requests: write

jobs:
release-please:
runs-on: ubuntu-latest
steps:
- uses: googleapis/release-please-action@45996ed1f6d02564a971a2fa1b5860e934307cf7 # v5.0.0
with:
config-file: .release-please-config.json
manifest-file: .release-please-manifest.json
19 changes: 19 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
name: validate

on:
pull_request:
push:
branches: [main]

jobs:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: 22
- name: Install Claude Code
run: npm install -g @anthropic-ai/claude-code
- name: Validate plugin
run: claude plugin validate . --strict
16 changes: 16 additions & 0 deletions .release-please-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json",
"release-type": "simple",
"include-component-in-tag": false,
"packages": {
".": {
"extra-files": [
{
"type": "json",
"path": ".claude-plugin/plugin.json",
"jsonpath": "$.version"
}
]
}
}
}
3 changes: 3 additions & 0 deletions .release-please-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
".": "0.1.0"
}
36 changes: 36 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# AGENTS.md

Guidance for AI coding agents (and humans) working on this repository.

## What this is

A Claude Code plugin: eight markdown skills that guide a customer from zero to a running, exposed app on the Intility Developer Platform. There is no application code — the "source" is SKILL.md prompts, YAML/JSON manifests, and reference docs.

## Layout

```
.claude-plugin/plugin.json plugin manifest (version is bumped by Release Please — don't edit by hand)
.claude-plugin/marketplace.json lets this repo serve as its own marketplace
skills/<name>/SKILL.md one skill per directory
skills/<name>/references/ templates and example conversations, loaded on demand
```

## Conventions

- **Keep SKILL.md under 500 lines.** Move templates, long examples, and walkthroughs to `references/` and link them — they're loaded only when needed.
- **Frontmatter:** `description` is written in third person and includes concrete trigger phrases. `allowed-tools` is the minimum the skill needs — prefer scoped patterns (`Bash(oc delete httproute*)`) over broad ones (`Bash(oc delete*)`); never pre-approve `find`, unscoped `curl`, or `sed` (use Glob/Read/Edit tools instead).
- **Skills detect state, they don't assume it.** Every skill starts by querying (`oc whoami`, `indev cluster list`) rather than trusting conversation memory. Keep it that way.
- **Tone:** plain language for Kubernetes beginners. One command at a time. Introduce a term after showing what it does.
- **Safety rails stay:** `internal` gateway by default, two-step confirmation before `public`, `status` stays read-only, never create a second cluster without explicit double confirmation.

## Before committing

```bash
claude plugin validate . --strict
```

This is also enforced by CI on every PR.

## Commits

Conventional Commits (`fix:`, `feat:`, `docs:`, …) — Release Please derives versions from them. See [CONTRIBUTING.md](CONTRIBUTING.md).
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Changelog

## 0.1.0

First alpha. Eight skills covering the full journey: `getting-started`, `status`,
`create-cluster`, `login`, `prepare-app`, `deploy-app`, `expose-app`, `update-image`.
40 changes: 40 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Contributing

Thanks for helping make the Developer Platform plugin better. It's an early alpha — feedback and small fixes are exactly what it needs.

## Found a bug? Have a wish?

Open an [issue](https://github.com/intility/cust-devplatform-plugin/issues). Include what you asked Claude to do, what it tried (the failing command is the best clue), and the cluster name if relevant.

## Making changes

1. The plugin is markdown and JSON — skills live in `skills/<name>/SKILL.md`, with longer material in `skills/<name>/references/`.
2. Validate before committing:

```bash
claude plugin validate . --strict
```

3. To try your changes live, add your local checkout as a marketplace in Claude Code:

```
/plugin marketplace add /path/to/cust-devplatform-plugin
/plugin install cust-devplatform-plugin@intility
```

4. Open a PR against `main`. The `validate` check must pass before merging.

## Commit messages

Use [Conventional Commits](https://www.conventionalcommits.org/) — releases are automated with Release Please, which derives the next version from commit messages:

- `fix: …` → patch release
- `feat: …` → minor release
- `feat!: …` or `BREAKING CHANGE:` → major release
- `docs:`, `chore:`, `ci:` → no release

## Releases

Release Please opens (and keeps updating) a release PR as changes land on `main`. Merging that PR bumps `version` in `.claude-plugin/plugin.json`, updates `CHANGELOG.md`, and tags a GitHub Release.

**Why the version bump matters:** installed users only receive plugin updates when the `version` field changes — merging the release PR is what actually ships your change. Don't edit the version by hand.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,14 @@
**1. Install this plugin**

```bash
/plugin marketplace add intility
/plugin marketplace add intility/cust-devplatform-plugin
/plugin install cust-devplatform-plugin@intility

```

**2. Tell Claude what you want**

```
help me ship my app on Intility Developer PLatform
help me ship my app on Intility Developer Platform
```

That's the whole thing. The plugin detects where you are in the journey and walks you through the rest.
Expand Down Expand Up @@ -93,6 +92,7 @@ A few things that aren't obvious up front:
- **Tokens expire.** Both `indev` and `oc` log out after a few hours. If something fails with "Unauthorized", just say *"log me back in"*.
- **Different repo, different view.** Claude only sees the manifests in the directory you're working from. Switching repos means switching scope.
- **`update-image` keeps the local file in sync** — but only if you run it from the repo that contains the manifests. Otherwise, the YAML on disk will drift from the cluster.
- **macOS / Linux only for now.** The skills assume a POSIX shell. On Windows, use WSL.

## Found a bug? Have a wish?

Expand Down
12 changes: 11 additions & 1 deletion skills/create-cluster/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
name: create-cluster
description: Creates a single cluster on the Intility Developer Platform for a customer. Use when the user asks to "create a cluster", "get me a cluster", "set up a cluster", or is being routed here by the getting-started skill. Creates ONE cluster with sensible defaults unless the user explicitly asks for more, since this plugin assumes a many-apps-on-one-cluster model.
user-invocable: true
allowed-tools:
- AskUserQuestion
- Bash(indev account show)
Expand All @@ -10,6 +9,7 @@ allowed-tools:
- Bash(indev cluster status*)
- Bash(indev cluster get*)
- Bash(indev login)
- Bash(oc whoami*)
- Bash(sleep *)
---

Expand All @@ -27,6 +27,7 @@ The `indev` token has expired. Don't retry the failing command. Run `indev login

```bash
indev cluster list
oc whoami --show-server 2>/dev/null
```

If there is already at least one cluster, **do not create another**. Show what's there and ask:
Expand All @@ -38,6 +39,15 @@ Q: "You already have a cluster (<name>). Use that one?"
- "No, I really need another" → continue
```

**Also check `oc whoami --show-server`** — clusters provisioned by platform admins or a colleague won't appear in this user's `indev cluster list`, but a working kubeconfig means a cluster exists. If `indev cluster list` is empty but `oc whoami --show-server` returns a server, ask:

```
Q: "You're already connected to a cluster (<server> — maybe set up by someone else?). Use that instead of creating a new one?"
Options:
- "Yes, use it" — stop here; they're already logged in, continue the journey on that cluster
- "No, create my own" → continue
```

This plugin assumes one cluster, many apps in their own namespaces. Only create a second cluster if the user is sure.

## Step 2 — Authenticate
Expand Down
2 changes: 0 additions & 2 deletions skills/deploy-app/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
name: deploy-app
description: Generates Kubernetes manifests (Namespace, Deployment, Service) for a containerized app and deploys them to the cluster with oc apply. Use when the user wants to "deploy my app", "ship my app", "run my app on the cluster", or after prepare-app has confirmed they have a containerized image. Defaults to a one-app-per-namespace layout so the same cluster can host many apps cleanly.
user-invocable: true
allowed-tools:
- AskUserQuestion
- Bash(oc whoami*)
Expand All @@ -11,7 +10,6 @@ allowed-tools:
- Bash(oc rollout*)
- Bash(oc describe*)
- Bash(oc logs*)
- Bash(oc delete*)
- Bash(mkdir *)
- Read
- Write
Expand Down
4 changes: 1 addition & 3 deletions skills/expose-app/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,16 +1,14 @@
---
name: expose-app
description: Gives a deployed app a public or internal URL by creating an HTTPRoute on the Intility Developer Platform. Use when the user says "expose my app", "give my app a URL", "make my app accessible", "set up ingress", "create a route", or after deploy-app finishes and the user wants the app reachable.
user-invocable: true
allowed-tools:
- AskUserQuestion
- Bash(oc whoami*)
- Bash(oc get*)
- Bash(oc apply*)
- Bash(oc describe*)
- Bash(oc delete httproute*)
- Bash(sed *)
- Bash(curl *)
- Bash(curl -s -o /dev/null*)
- Read
- Write
- Edit
Expand Down
5 changes: 3 additions & 2 deletions skills/getting-started/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
name: getting-started
description: Entry point for getting an app running on the Intility Developer Platform. Use when the user says things like "help me deploy", "get me started with Intility", "I want to run my app on the platform", "I'm new to Kubernetes and need to ship something", or "what do I do next?". Figures out where the user is in the journey (no cluster yet → cluster but no app → app deployed but no URL → ready to update) and routes to the right skill.
user-invocable: true
allowed-tools:
- AskUserQuestion
- Bash(command -v *)
Expand Down Expand Up @@ -55,12 +54,14 @@ From the results, classify the situation:
| Situation | Signal |
|---|---|
| Not logged in to `indev` | `indev account show` fails |
| No cluster yet | `indev cluster list` returns empty / no clusters |
| No cluster yet | `indev cluster list` returns empty / no clusters **and** `oc whoami` fails |
| Has a cluster, not logged in | Cluster exists, `oc whoami` fails |
| Logged in, no app deployed | `oc whoami` works, but the user hasn't mentioned an app namespace |
| Has an app, needs a URL | User says it's deployed but not reachable |
| Wants to update | User mentions a new image / new version |

**`oc whoami` working beats an empty `indev cluster list`.** Clusters are sometimes provisioned by platform admins or a colleague, so they don't show up in *this user's* `indev cluster list`. If `oc whoami` succeeds, the user has a cluster — treat the situation as "has a cluster, logged in" and never route to `create-cluster`. Use `oc whoami --show-server` to tell them which cluster they're connected to.

## Step 2 — Confirm where they want to go

If the situation is obvious from the user's message, just continue. Otherwise ask one short question:
Expand Down
1 change: 0 additions & 1 deletion skills/login/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
---
name: login
description: Logs the user into their Intility Developer Platform cluster so they can run kubectl/oc commands against it. Use when the user asks to "log in", "log into the cluster", "connect to my cluster", "oc login", or when another skill needs cluster access and the user is not authenticated.
user-invocable: true
allowed-tools:
- AskUserQuestion
- Bash(indev cluster list*)
Expand Down
10 changes: 4 additions & 6 deletions skills/prepare-app/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
---
name: prepare-app
description: Verifies that the user's app is containerized and that an image exists in a registry the cluster can pull from, before deploying. Use when the user wants to deploy something but you don't yet know if they have a Dockerfile or a pushed image, or when the deploy-app skill needs an image reference and doesn't have one yet.
user-invocable: true
allowed-tools:
- AskUserQuestion
- Bash(ls *)
- Bash(find *)
- Bash(docker images*)
- Bash(docker manifest inspect*)
- Glob
- Read
---

Expand All @@ -23,10 +21,10 @@ If both are true, hand off to `deploy-app`. Otherwise, tell the user the smalles

## Step 1 — Look for a Dockerfile

Search the project root and one level down:
Search the project root and one level down using the Glob tool:

```bash
find . -maxdepth 2 \( -name Dockerfile -o -name Containerfile \) 2>/dev/null
```
Glob: {Dockerfile,Containerfile,*/Dockerfile,*/Containerfile}
```

If found, note the path. If not:
Expand Down
6 changes: 3 additions & 3 deletions skills/status/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
---
name: status
description: Shows a summary of what the user has on the Intility Developer Platform — their cluster, deployed apps, and the URLs those apps are exposed on. Use when the user asks "what's deployed?", "what do I have running?", "what apps are on my cluster?", "what's the URL for X?", "show me my cluster", or comes back after a break and needs a refresher.
user-invocable: true
allowed-tools:
- Bash(indev cluster list*)
- Bash(oc whoami*)
- Bash(oc get*)
- Bash(grep *)
- Bash(sed *)
---

# Status
Expand Down Expand Up @@ -43,9 +41,11 @@ If it errors, tell the user and suggest the `login` skill. Show the cluster name
If it works, also grab the cluster name from the API URL — useful for showing hostnames:

```bash
oc whoami --show-server | sed 's|https://api[-.]||' | sed 's|[.:].*||'
oc whoami --show-server
```

The server URL looks like `https://api.<cluster-name>.<domain>:6443` — read the cluster name out of it yourself; no text-processing pipeline needed.

## Step 3 — Deployments

List all deployments excluding platform/system namespaces:
Expand Down
2 changes: 1 addition & 1 deletion skills/update-image/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
name: update-image
description: Updates the container image on an already-deployed app to a new version. Use when the user says "update my app", "deploy a new version", "ship v2", "bump the image to X", or otherwise wants to roll out a new build of something already running on the cluster.
user-invocable: true
argument-hint: "[app] [new-image-or-tag]"
allowed-tools:
- AskUserQuestion
- Bash(oc whoami*)
Expand Down