This Skill only reads: searches code, reads files and directories, and queries commit history; it does not modify anything. To find out which PR brought in a given commit, use repos-pull-request-review(rule 3, "find the PR from a commit").
Project selection
-
If the user has provided a project name (for example "Contoso project"), use it directly and do not call the project list API.
-
When the user wants to search code in the "entire organization" or "all projects", for rule 1 use a URL without a project; there is no need to select a project.
-
In other cases, if it is not provided, ask the user to provide it once.
-
If it is still not provided, list the projects for the user to choose:
curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/_apis/projects?%24top=500&api-version=7.1" -
Do not continue until the user provides or selects a project.
Repository selection
The repository in rule 1 is optional (omitting it means the entire project); rules 2 through 4 must specify a repository.
-
If the user has provided a repository name, use it directly.
-
If none is specified, ask once for the repository name.
-
If it is still not provided, list the repositories in the project for the user to choose:
curl -sS -u ":$AZURE_DEVOPS_PAT" \ "https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories?api-version=7.1"Show
value[].name;isDisabledastrueMark repositories that are disabled as disabled.defaultBranchis the default branch (for examplerefs/heads/main),webUrlis used to compose web links.
Connection and authentication
Always use curl to call the Azure DevOps REST API directly; each command carries its own authentication parameters.
- Organization: read the environment variable
AZURE_DEVOPS_ORG(organization name, for examplecontoso). If it is not set, ask the user once; if what the user gives is a URL, extract the organization name fromhttps://dev.azure.com/{org}orhttps://{org}.visualstudio.com. - Host: in addition to
dev.azure.com, the host for the code search API isalmsearch.dev.azure.com。 - Token: the PAT is sent with Basic authentication:
-u ":$AZURE_DEVOPS_PAT"; if onlyAZURE_DEVOPS_EXT_PATis set (the variable used by the Azure CLI azure-devops extension), use it instead. When using a Microsoft Entra ID token instead, replace it with-H "Authorization: Bearer $AZURE_DEVOPS_TOKEN". If neither is set, ask the user to setAZURE_DEVOPS_PATin their own terminal and retry, then stop. Read the token only from environment variables: do not ask the user to paste the token into the conversation, and do not print it or write it to a file. - PAT permission scope: Code (Read) (which already includes code search).
- Encoding: URL-encode project and repository names in the path, and file paths, branch names, and authors in the query string (write spaces as
%20, and encode Chinese as well); in the query string, write$as%24(for example%24top), to avoid shell expansion. Names in the JSON body do not need encoding. - Errors: HTTP 401, 403, 203, or a response that is an HTML login page means the token is invalid, expired, or has insufficient permissions; report it and stop; HTTP 404 means the organization, project, repository, or file path is wrong (when the file does not exist,
messagecontainsTF401174, and when the branch or commit does not exist, it containsTF401175)。 - Windows PowerShell: call
curl.exe(instead ofcurlalias), write the environment variable as$env:AZURE_DEVOPS_PAT; PowerShell does not support<<'EOF', first write the JSON body to a temporary file, then send it with--data-binary "@body.json".
Search syntax
searchText uses the same syntax as web Code Search, and is always case-insensitive.
| Feature | Syntax | Description |
|---|---|---|
| Keywords | validate revisit |
Multiple keywords are by default AND |
| Boolean operators | A AND B、A OR B、A NOT B、(A NOT B) OR "c d" |
Operators must be uppercase; parentheses can be used for grouping |
| Exact phrase | "Client not found" |
Enclose in double quotes |
| Wildcards | Browser*、alpha?version |
* any number of characters,? single character |
| Proximity | A NEAR B、A BEFORE B、A AFTER B |
Default distance is 5 tokens; operators must be uppercase |
| Special characters | "flatten()"、"\"react-redux\"" |
( ) [ ] : * ? put into a double-quoted phrase; within a phrase, " is written as \" |
| Path | proj:Contoso、repo:MyApp、path:src/Services、file:Program*、ext:cs |
path: includes subdirectories, can use ** for cross-level matching; use double quotes when the value contains spaces |
| Code type | class:、def:、ref:、method:、interface:、enum:、field:、prop:、namespace:、type:、comment:、strlit:、basetype:、decl:、macro: |
Only C#, C, C++, Java, Visual Basic.NET are supported; for example def:Main、comment:todo |
func:、ctor:、methoddef: etc. have been merged into method:,struct:、typedef: has been merged into type:,classdef:、classdecl: has been merged into class:。
Rules
1. Search code
curl -sS -u ":$AZURE_DEVOPS_PAT" -X POST -H "Content-Type: application/json" \
"https://almsearch.dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/search/codesearchresults?api-version=7.1" \
--data-binary @- <<'EOF'
{
"searchText": "def:GetOrder ext:cs",
"$skip": 0,
"$top": 50,
"filters": {"Project": ["Contoso"], "Repository": ["MyApp"], "Path": ["/src"], "Branch": ["main"]},
"includeFacets": false
}
EOF
filtersvalue is an array of names:Project、Repository、Path(includes subdirectories, case-insensitive),Branch. Omit any unwanted filter entirely. Supplying onlyRepositorywithoutProjectreturns HTTP 400.- When searching the entire organization, remove
/{project},filtersfrom the URL and do not includeProject。 - Specify the code type in
searchText(for exampleclass:Order). Testing showsfilters.CodeElementdoes not narrow the results, it only returns moreCodeElementfacet。 $topmust be between 1 and 1000;countis the total number of matching files, and when it is greater than the number already retrieved, use$skipto get the next page.- Branch: only indexed branches can be searched, and by default only the default branch; for other branches, go to Project settings > Repositories > the repository's Options to add searchable branches. Specifying a non-indexed branch returns HTTP 200,
countis 0, and no error is reported: first search with"includeFacets": true,facets.Branch[].nameis the indexed branch. infoCode:0is normal;1、2、6、7、9means the organization or branch is still being indexed, results may be incomplete, and the user must be informed;8means$topwas truncated.- Code Search not installed: code search requires the organization to install the Code Search extension (Marketplace's
ms.vss-code-search). If the response is not HTTP 200, ormessagementions that the search service or extension is unavailable, report the original message, ask the organization administrator to install it, and switch to Rule 3 to list directories, Rule 2 to read files one by one, or clone locally and usegit grep。 - Each result:
fileName、path、repository.name、project.name、versions[].branchNameandversions[].changeId(the commit of that branch),matches.content[](matching location),matches.fileName[](filename matches). matches.content[]what is available incharOffset、lengthandtype(content、class、ref、comment、strlitetc.);lineandcolumnare always0,codeSnippeteven if setincludeSnippet: trueis alsonull. To display matching code lines, use rule 2 to read the file withversions[0].changeId, and use the number of newlines beforecharOffsetplus 1 as the line number (offsets are counted in characters, excluding a BOM at the start of the file). Display at most the first 3 matches per file.
Examples: "Find the definition of GetOrder in the Contoso project", "Where is ConnectionStringused across the organization?", "What TODO comments are under src in MyApp?"
2. Read file
curl -sS -u ":$AZURE_DEVOPS_PAT" \
"https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repository}/items?path={filePath}&versionDescriptor.version={branch}&versionDescriptor.versionType=branch&api-version=7.1"
- Without
%24format, returns the file's raw content (plain text). - Omitting
versionDescriptor.*means the default branch; when reading a specific commit or tag, replaceversionTypewithcommitortag。 - If the file does not exist, return HTTP 404 (
TF401174); for binary files, only report the file type, do not display the content. For large files, use-oto save to a temporary directory, display only the sections the user needs, and delete them after use.
Example: "Read /src/appsettings.jsonin MyApp (release branch)"
3. List directory
curl -sS -u ":$AZURE_DEVOPS_PAT" \
"https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repository}/items?scopePath={folderPath}&recursionLevel=OneLevel&versionDescriptor.version={branch}&versionDescriptor.versionType=branch&api-version=7.1"
value[0]is the directory itself, and the rest are child items. Each entry haspath、isFolder(files do not have this field) andgitObjectType:treeis a directory,blobis a file, andcommitis a submodule.- To list the entire subtree, use
recursionLevel=Fullinstead; when there are many items, first state the count and list only the parts relevant to the user's question.
Example: "What files are in the root directory of MyApp?"
4. Query commit history
curl -sS -u ":$AZURE_DEVOPS_PAT" \
"https://dev.azure.com/$AZURE_DEVOPS_ORG/{project}/_apis/git/repositories/{repository}/commits?searchCriteria.itemVersion.version={branch}&searchCriteria.author={author}&searchCriteria.itemPath={path}&searchCriteria.fromDate=2025-01-01T00:00:00Z&searchCriteria.toDate=2025-02-01T00:00:00Z&searchCriteria.%24top=50&api-version=7.1"
| Parameter | Description |
|---|---|
searchCriteria.itemVersion.version |
Branch name; omitted means the default branch |
searchCriteria.author |
Author name or email; partial strings are also matched |
searchCriteria.itemPath |
File or directory path; returns only commits that modified it |
searchCriteria.fromDate、searchCriteria.toDate |
ISO 8601 date-time; when the user gives a local date, convert it to UTC first |
searchCriteria.%24top、searchCriteria.%24skip |
Pagination; by default at most 100 entries; when the number returned equals %24top , fetch the next page |
- Omit unnecessary conditions entirely.
- Pitfall:
searchCriteria.fromCommitIdandsearchCriteria.toCommitIdare lower and upper bounds filtered by commit ID alphabetical order, not "the history between two commits". To compare commits between two versions, clone locally and usegit log {from}..{to}。 - This API cannot search by commit message: to find a keyword in a message, first narrow the scope by date, author, or path, then compare
comment。commentTruncatedwhentrueisGET .../commits/{commitId}?api-version=7.1to get the full message. - Each entry has
commitId、author.name、author.email、author.date、comment、changeCounts(Add、Edit、Deletecount).
Examples: "Who recently modified /src/Services/OrderService.cs?", "List commits by someone@contoso.com on main last month"
Present results
Display the date as YYYY/MM/DD, convert the time to the user's local time zone, and mark it as UTC when it cannot be determined.
- Code search: first explain the search conditions (syntax, project, repository, branch) and the total number of matching files. Present as a table: file path (clickable, link
https://dev.azure.com/{organization}/{project}/_git/{repository}?path={path}&version=GB{branch}), repository, branch, number of matches. When reading files, list the line numbers and that line of code file by file below the table. If there is a next page, state the remaining count; if there are no results, say so clearly, and note that the branch may not be indexed orinfoCodesituation. - File contents: presented as a code block, with the language indicated by file extension, and note the branch or commit.
- Directory: list directories first, then files; add
/after directory names, and mark submodules as "submodule". - commit history: present in a table the short SHA (first 7 characters, link
https://dev.azure.com/{organization}/{project}/_git/{repository}/commit/{commitId}), author, date, first line of the message, and number of changed files. If there are no commits, say so clearly.