> ## Documentation Index
> Fetch the complete documentation index at: https://veryfront.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Project Skill

> Project Skill query.

export const GraphQLOperationPlayground = ({operationName, query, variables}) => {
  const endpoint = "https://api.veryfront.com/graphql";
  const tokenStorageKey = 'veryfront.docs.mcpBearerToken';
  const formatGraphql = source => {
    const compact = source.replace(/\s+/g, ' ').trim();
    let depth = 0;
    let result = '';
    for (let index = 0; index < compact.length; index += 1) {
      const char = compact[index];
      if (char === '{') {
        const previous = result.trimEnd();
        result = previous + ' {\n';
        depth += 1;
        result += ('  ').repeat(depth);
        continue;
      }
      if (char === '}') {
        depth = Math.max(0, depth - 1);
        result = result.trimEnd() + '\n' + ('  ').repeat(depth) + '}';
        const next = compact[index + 1];
        if (next && next !== '}') {
          result += '\n' + ('  ').repeat(depth);
        }
        continue;
      }
      result += char;
    }
    return result.replace(/\n{3,}/g, '\n\n').trim();
  };
  const escapeHtml = value => value.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');
  const highlightJson = value => {
    const escaped = escapeHtml(value);
    return escaped.replace(/("(?:\u[a-fA-F0-9]{4}|\[^u]|[^\"])*"(\s*:)?|\btrue\b|\bfalse\b|\bnull\b|-?\d+(?:\.\d+)?(?:[eE][+\-]?\d+)?)/g, match => {
      let color = '#f3f4f6';
      if (match.endsWith(':')) color = '#7dd3fc'; else if (match.startsWith('"')) color = '#86efac'; else if ((/true|false/).test(match)) color = '#c4b5fd'; else if ((/null/).test(match)) color = '#fcd34d'; else color = '#67e8f9';
      return `<span style="color: ${color}">${match}</span>`;
    });
  };
  const formatJson = value => {
    try {
      return JSON.stringify(value, null, 2);
    } catch {
      return String(value);
    }
  };
  const readStoredToken = () => {
    if (typeof window === 'undefined') return '';
    try {
      return window.sessionStorage.getItem(tokenStorageKey) || '';
    } catch {
      return '';
    }
  };
  const writeStoredToken = value => {
    if (typeof window === 'undefined') return;
    try {
      if (value) window.sessionStorage.setItem(tokenStorageKey, value); else window.sessionStorage.removeItem(tokenStorageKey);
    } catch {}
  };
  const [token, setToken] = useState(readStoredToken);
  const [queryText, setQueryText] = useState(formatGraphql(query));
  const [variablesText, setVariablesText] = useState(variables);
  const [status, setStatus] = useState('Ready');
  const [response, setResponse] = useState('No response yet.');
  const [copied, setCopied] = useState(false);
  const runOperation = async () => {
    let parsedVariables;
    try {
      parsedVariables = variablesText.trim() ? JSON.parse(variablesText) : {};
    } catch {
      setStatus('Variables must be valid JSON.');
      return;
    }
    setStatus('Running operation...');
    try {
      const result = await fetch(endpoint, {
        method: 'POST',
        headers: {
          accept: 'application/json',
          'content-type': 'application/json',
          ...token.trim() ? {
            authorization: `Bearer ${token.trim()}`
          } : {},
          'x-veryfront-origin': 'docs-graphql-operation-page'
        },
        body: JSON.stringify({
          operationName,
          query: queryText,
          variables: parsedVariables
        })
      });
      const text = await result.text();
      setStatus(result.ok ? 'Response received.' : `Request failed with HTTP ${result.status}.`);
      try {
        setResponse(formatJson(JSON.parse(text)));
      } catch {
        setResponse(text || 'No response body.');
      }
    } catch (error) {
      setStatus('Request failed.');
      setResponse(error instanceof Error ? error.message : String(error));
    }
  };
  const copyResponse = async () => {
    try {
      await navigator.clipboard.writeText(response);
      setCopied(true);
      setTimeout(() => setCopied(false), 1500);
    } catch {
      setStatus('Copy failed.');
    }
  };
  return <div className="not-prose my-6 rounded-xl border border-gray-200 bg-white p-4 dark:border-gray-800 dark:bg-gray-950">
      <div className="mb-4 text-sm font-semibold text-gray-900 dark:text-gray-100">GraphQL operation</div>

      <label className="mb-2 block text-sm font-medium text-gray-900 dark:text-gray-100" htmlFor={`${operationName}-token`}>
        Bearer token
      </label>
      <input id={`${operationName}-token`} className="mb-4 w-full rounded-md border border-gray-300 bg-white px-3 py-2 text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100" type="password" value={token} onChange={event => {
    const value = event.target.value;
    setToken(value);
    writeStoredToken(value);
  }} placeholder="Paste API key or JWT" />

      <label className="mb-2 block text-sm font-medium text-gray-900 dark:text-gray-100" htmlFor={`${operationName}-query`}>
        Query
      </label>
      <textarea id={`${operationName}-query`} className="mb-4 min-h-48 w-full rounded-md border border-gray-300 bg-white px-3 py-2 font-mono text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100" value={queryText} onChange={event => setQueryText(event.target.value)} spellCheck={false} />

      <label className="mb-2 block text-sm font-medium text-gray-900 dark:text-gray-100" htmlFor={`${operationName}-variables`}>
        Variables JSON
      </label>
      <textarea id={`${operationName}-variables`} className="mb-4 min-h-32 w-full rounded-md border border-gray-300 bg-white px-3 py-2 font-mono text-sm text-gray-900 dark:border-gray-700 dark:bg-gray-900 dark:text-gray-100" value={variablesText} onChange={event => setVariablesText(event.target.value)} spellCheck={false} />

      <button className="rounded-md bg-gray-900 px-3 py-2 text-sm font-medium text-white hover:bg-gray-700 dark:bg-gray-100 dark:text-gray-950 dark:hover:bg-gray-300" type="button" onClick={runOperation}>
        Run query
      </button>

      <div className="mt-4 text-sm font-medium text-gray-900 dark:text-gray-100">{status}</div>
      <div className="mt-3 overflow-hidden rounded-md border border-gray-300 dark:border-gray-700">
        <div className="flex items-center justify-between bg-gray-100 px-3 py-2 text-sm font-medium text-gray-900 dark:bg-gray-900 dark:text-gray-100">
          <span>Output JSON</span>
          <button className="rounded border border-gray-300 bg-white px-2 py-1 text-xs text-gray-900 hover:bg-gray-50 dark:border-gray-700 dark:bg-gray-950 dark:text-gray-100 dark:hover:bg-gray-800" type="button" onClick={copyResponse}>
            {copied ? 'Copied' : 'Copy'}
          </button>
        </div>
        <pre className="max-h-96 overflow-auto whitespace-pre-wrap break-words bg-gray-950 p-4 text-sm text-gray-100">
          <code dangerouslySetInnerHTML={{
    __html: highlightJson(response)
  }} />
        </pre>
      </div>
    </div>;
};

## Operation details

| Field     | Value                                                   |
| --------- | ------------------------------------------------------- |
| Name      | `projectSkill`                                          |
| Group     | Project Primitives                                      |
| Type      | Query                                                   |
| Signature | `projectSkill(input: ProjectSkillInput!): ProjectSkill` |

## Playground

<GraphQLOperationPlayground operationName="ProjectSkill" query={"query ProjectSkill($input: ProjectSkillInput!) { projectSkill(input: $input) { id name description allowedTools editMode sourcePath } }"} variables={"{ \"input\": { \"projectId\": \"\", \"skillId\": \"\" } }"} />

## Query

```graphql title="Query" theme={null}
query ProjectSkill($input: ProjectSkillInput!) {
  projectSkill(input: $input) {
    id
    name
    description
    allowedTools
    editMode
    sourcePath
  }
}
```

## Variables

```json title="Variables" theme={null}
{
  "input": {
    "projectId": "",
    "skillId": ""
  }
}
```
