Shared skills + credential-blind data adapter so a cheap Copilot model can run several large projects at once without hand-maintained AGENTS.md sprawl.
Two pieces, installed separately, and both must move together: the ad-* CLI (pip, from GitHub) and the skills
(gh skill install, into ~/.copilot/skills). Updating one and not the other is the most common breakage — a skill
tells Luna to run a command the CLI does not have yet.
ad-update # reinstall the CLI from GitHub + reinstall every skill, then tell you what changed
ad-update --check # what you have right now: version, commit, skills dir, whether the skills look stale. Runs nothing.Then start a new Copilot chat (skills are read when a chat starts) and run ad-doctor — followed by
ad-setup --patch if it reports anything. CHANGELOG.md says what changed and whether an
update needs anything beyond these two commands.
If ad-update does not exist yet — you are on a build from before it was added — run the two commands by hand, once:
python -m pip install --force-reinstall --no-deps "agentdata @ git+https://github.com/agentchieflou/this-next-please.git"
gh skill install agentchieflou/this-next-please --all --scope user--force-reinstall is not optional: pip will not reinstall a git URL whose version has not changed, and the
version does not change on every commit, so a plain pip install prints "Requirement already satisfied" and you
keep the old code. --no-deps stops the update from re-downloading teradatasql and friends every time; use the
extras form instead when the release notes say a new optional dependency is needed:
python -m pip install --force-reinstall "agentdata[teradata] @ git+https://github.com/agentchieflou/this-next-please.git".
ad-update --checkversion/commit— the exact commit pip recorded for this install (from thedirect_url.jsonmetadata pip writes for git installs). Compare it with the newest commit onmain.ad-doctorprints both in itsmetatoo, so every session shows what it is running.python— the interpreter that owns the install. If that is not the Python you typepythonfor, that mismatch is why an update "did not take": run the update with that interpreter, or usepython -m agentdata <command>.install— how this copy got here: a git install (what a laptop should have), an editable install, or running from a checkout. For the last two,ad-updateupdates the skills and skips the CLI half: pip must not fight a clone you are editing. That is a skip, not a failure —skipped[1]: cli, and the row says what to run.ad-update --pulldoesgit pull --ff-onlyin that clone instead;ad-update --from-gitleaves the clone behind and installs the published version over it.skills/skills_newest/stale_skills: true— the skills are older than the CLI; run thegh skill installline and start a new chat.gh skill installrefusing because a skill is already installed → nothing to do by hand.ad-updatereads the names out of that message, deletes only the folders it recognises as its own (aSKILL.mdwhose frontmatternamematches the folder — a skill someone else put there is never touched), and installs once more, reportingreinstalled.- A failing half now prints the real error, not the last line of pip's chatter, plus a hint for the signature: an
all-users install a non-elevated pip cannot uninstall, the
ad-update.exelauncher locking itself (it re-execs throughpython -m agentdata updateto avoid this), a--usercopy shadowing the all-users one, apythonbelow the 3.14 floor, or a proxy.ad-update --checklists every installedagentdataand everypythonon PATH, so a shadowed install is visible before it wastes an afternoon, and the report says which shell it came from.
See docs/shells.md for which command runs in which shell (and which belong to the Copilot chat
window rather than a terminal), and how to quote arguments in pwsh 7, Git Bash and cmd.
The CLI needs Python 3.14 or newer (python --version). On an older interpreter pip
refuses the install with "requires a different Python" -- run the command below with the newer python.
# 1. toil, used directly for Jira, Confluence and Bitbucket (docs/toil-parts.md); needs Node 24.14+
npm install -g @imagile-dev/toil # lands as toil.cmd -- there is no toil.exe
toil # a menu: add your Jira, Confluence and Bitbucket connections (tokens go to the
# OS credential store, never a file); writes stay off until you turn them on
# 2. the skills -> ~/.copilot/skills, for every repo you work in
gh skill install agentchieflou/this-next-please --all --scope user
# 3. the ad-* CLI -> a normal Python tool, installed straight from GitHub (no clone needed)
pip install "agentdata @ git+https://github.com/agentchieflou/this-next-please.git"
# with the extras you actually use:
# pip install "agentdata[teradata,impala,oracle,pbi,uat,test] @ git+https://github.com/agentchieflou/this-next-please.git"
tnp # the menu: data connections (paste a JDBC URL), Power BI, each repo's settings, toil's
# connections, health, the fleet desk, and every ad-* command to browse, search and run
# (docs/tnp.md); says where every answer is written
ad-setup # guided: toil (its launcher, and which connection each service uses), data sources,
# Power BI tools/workspaces; without toil, `ad-setup --only jira` keeps a token in the keyring
# ad-setup --quick # fast path: auto-accepts unambiguous detected facts (single DSN, found tools)
# ad-setup --export-defaults team.json / ad-setup --import team.json # share non-secret team defaults
ad-theme gallery # preview terminal themes (greens, dark, eye-relief, matrix, ...)
# ad-setup --only theme # customize theme, directory hook, WT fragment, or Oh My Posh
ad-doctor # any time: offline health check (session-bootstrap runs it)
ad-setup --patch # after any fail row: re-asks ONLY the settings behind it, nothing elseSkip the skill picker. Without --all, gh skill install opens an interactive list whose first row is a
search box: pressing Enter there re-enters search instead of paging, so you have to arrow down one row before the
list will move. --all installs every skill and never shows the picker. --scope user puts them in your home
directory so they apply in every project repo (--scope project, the default, writes only into the current repo).
--all needs a recent gh (check with gh --version; it landed in cli/cli#13471). On an older CLI, either update it
or name the skills you want: gh skill install agentchieflou/this-next-please router --scope user, repeated per skill.
Project repos install nothing. rdsd-pbi-reporting and friends hold PBIP folders, TMDL and SQL — not Python.
Running pip install -e ".[dev]" there fails with "neither 'setup.py' nor 'pyproject.toml' found", and that is
correct: the CLI is laptop-wide, like git. Per project you only run ad-setup inside it (or ad-setup --repo <name>
from the folder that holds your repos): that writes only the repo's AGENTS.md, i.e. which environment of each source it
reads and the Power BI models and reports it changes.
If ad-setup is "not recognized as the name of a cmdlet", pip printed Defaulting to user installation and put the
console scripts in a folder Windows does not have on PATH. Either add it —
python -c "import sysconfig;print(sysconfig.get_path('scripts','nt_user'))" — or use the module form, which always
works and takes the same arguments: python -m agentdata update, python -m agentdata setup,
python -m agentdata doctor, python -m agentdata pbip check, python -m agentdata --help.
Subcommands, flags, and the values of flags that take a fixed set. No extra to install and nothing has to be on PATH: the script bakes in the interpreter that generated it, and asks it for the candidates. One line per shell, once:
ad-setup --print-completion bash --install # adds one line to ~/.bashrcad-setup --print-completion powershell --install # adds one line to your $PROFILEOpen a new shell and press Tab. --install is idempotent — run it again after moving Python and
it replaces the line rather than adding a second. To see the script instead of installing it, drop
--install; to load it for this session only, eval "$(ad-setup --print-completion bash)" or
ad-setup --print-completion powershell | Out-String | Invoke-Expression.
ad-doctor has a console/completion row saying which startup files carry the line.
| Shell | Works | Proven by |
|---|---|---|
| Git Bash (bash 4.4+) | yes | CI drives _agentdata_complete with COMP_LINE/COMP_POINT |
| bash on Linux | yes | the same step on the Ubuntu jobs |
| zsh | yes, through bashcompinit |
zsh -n where the runner has zsh |
PowerShell 7 (pwsh) |
yes | CI calls TabExpansion2, which is what a Tab press calls |
| Windows PowerShell 5.1 | yes | the same, in the one 5.1 step |
Two honest limits. PowerShell does not invoke a native argument completer for a bare --, so type
at least --s before Tab; and a value that would need the network (a workspace name) is not
completed, only the fixed choices a flag declares.
Windows PowerShell 5.1 is not a supported shell for running
ad-*— seedocs/shells.md. Completion is written in 5.1-compatible syntax anyway, because it costs nothing and somebody on a locked-down laptop still gets Tab.
cd C:\repos\rdsd-pbi-reporting
ad-setup --project . # writes AGENTS.md + .agent/state.json from the packaged stub, fills the facts it knows
# Luna's form (no stdin): ad-setup --only project --non-interactive --offline --project . --set project.jira_project=RDSD
ad-state show # session state; `ad-state set phase=… active_ticket=…` is the only way state.json is written
ad-doctor # what is broken · ad-setup --patch re-asks ONLY the settings behind the fail rows
ad-setup --patch sources.oracle # or name a target: re-ask exactly that, without waiting for a check to failAGENTS.md— ~30 lines of project facts, points at the installed skills. Two families worth filling in:ticket_policy(optional, the default: a request may run without a ticket;required: every request needs a key or a new ticket) and thejira_*factsad-jira createbuilds a new ticket from (jira_issue_type,jira_components,jira_fieldssuch asPrimary Domain=Data,jira_labels,jira_parent,jira_assignee)..agent/state.json— machine-owned project state- Power BI:
ad-pbi auth --probeproves the XMLA sign-in Tabular Editor will use.az loginalone never signed Tabular Editor in (it has its own token cache); since 0.10 everyad-pbiverb hands it an access token and runsaz login --allow-no-subscriptionsitself when the CLI is signed out --docs/setup.md§The XMLA sign-in.
git clone https://github.com/agentchieflou/this-next-please.git
cd this-next-please
pip install -e ".[dev]" # only here does `pip install -e` make sense
python -m pytest -q -n auto -m "not browser and not measured and not scale and not slow"That last line is the inner loop: nearly the whole suite, on every core, while you work. Four tiers are
held out because they are expensive for four different reasons -- python -m pytest -q still runs all of
it serially, and docs/testing-this-repo.md says what each tier costs and why it is one.
| Path | Role |
|---|---|
AGENTS.md |
canonical rules (short). Read HANDOFF.md first if you are Claude Code. |
skills/*/SKILL.md |
one job each; router dispatches to exactly one. skills/*/references/ hold the long reference docs. |
agentdata/ |
connector adapter: sources -> AgentTable -> TOON / TSV / JSON |
agentdata/config.py |
global config + project facts; every CLI resolves settings flag → env var → config → AGENTS.md |
agentdata/textio.py |
reads files other tools wrote (BOM, UTF-16, cp1252, cmd's OEM code page — Notepad, other teams, older scripts); writes UTF-8 without BOM, LF, atomically, and copes with a locked target, a >260-character path and a reserved filename |
agentdata/proc.py |
starts other programs on Windows: PATHEXT + npm global prefix resolution, npm .cmd shims run as node <script> (no cmd.exe re-parsing) |
agentdata/update.py |
ad-update: reinstall the CLI + skills, and report the exact commit installed |
CHANGELOG.md |
what each version changed, and whether picking it up needs more than the two update commands |
agentdata/state.py |
ad-state: the only writer of .agent/state.json (validated keys and phases, clean encoding) |
agentdata/setup/ |
ad-setup wizard and ad-doctor (step registry: toil, jira (the fallback without toil), sources, powerbi, content_understanding, project) |
agentdata/connectors/ |
teradata / hive / impala / oracle (native or ODBC DSN), jira_api (Jira REST for the ad-jira extensions: through toil's connection, or a token from the environment or the keyring), toil (toil as a library: the read/write split the fleet's shim gates on, the envelope, in-process reads, the REST transport through toil jira api), content_understanding (Azure AI / Microsoft Foundry document field extraction, ad-foundry), keyring wrapper, probes |
agentdata/sqlcheck/ |
dialect pre-flight lint (ad-sql-check, auto inside the query commands) |
agentdata/pbip/ |
PBIP tooling: TMDL parser/lint/editor, PBIR loader, projection, model↔report validator, Desktop discovery, DAX runner (ad-pbip) |
agentdata/fleet/ |
ad-fleet: several headless agents, one per repository, watched from one page — supervisor, normalized event stream, approval gate, the toil shim that refuses a toil write (toil_gate.py), notifications, Jira intake, dashboard (docs/fleet.md) |
agentdata/fleet/settings.py |
the enumerated table of what the /settings page may change: type, default and when a change takes effect. An allow-list, so a key nobody named is refused rather than written |
ide/ |
two thin shells that host that page — a JetBrains tool window and a VS Code view. Not part of the Python wheel; built by CI |
agentdata/ui.py |
how the CLI looks to a person: panels, tables and status glyphs via rich, and off whenever a machine might be reading |
agentdata/confluence.py |
ad-confluence: Markdown → Confluence storage format (XHTML, code macro, entities), XML-validated before it is published |
agentdata/jira_workflow.py |
ad-jira transition: resolves "review"/"done" against the transitions Jira offers THIS issue — a Task and a Story have different workflows |
agentdata/uat/ |
sprint replay, expected-value loader, tiered reconciliation (ad-jira sprint-replay, ad-uat) |
agentdata/jira_cache.py |
the changelog cache (ad-jira cache): one SQLite file per project, keyed on each issue's updated stamp, so the second pull of a long JQL costs one search |
agentdata/dpm/ |
DPM → consumer handoff contract: read-only run root, reference resolution, versioned refusals, job manifest with lineage (ad-dpm) |
agentdata/graph/ |
code graph extraction, queries, human-approval gate, findings, and guard (ad-graph) |
agentdata/context.py |
ad-context: what a repository is, read in seconds without a model -- inventory, entrypoints, tests, reports and SQL, docs, git, the AGENTS.md facts it can propose -- for the first session that sees it (docs/project-context.md) |
agentdata/sorting/ |
ad-sort: organizing a folder of files into a structure — a plan an agent writes and a person applies, by name only, copying and never moving (docs/sorting.md) |
agentdata/dpm/extract.py |
field extraction over DPM-routed text: the field list is an input, and the engine is a seam (simple label matching, or an Azure Content Understanding analyzer) that downstream output does not see |
docs/pbi-tools-parts.md |
what was learned from pbi-tools (AGPL) and re-implemented as behaviour |
docs/toil-parts.md |
toil, the service backend: what we use as it is, what we extend and where, the behavioural differences from pncli, and what was retired |
docs/fleet-skills.md |
the skills marketplace on /settings: every installed skill, how often it ran, in which repositories, and the source it syncs from |
docs/npm.md |
the root package.json: a dev-only manifest and one lockfile (the vetting list) pinning the desk's TypeScript and the npm package the vendored three.js is copied from; npm run types, npm run vendor:check; nothing ships |
docs/fleet-worklog.md |
the fleet's worklog: one page per checkout per day folded from the event stream, laid out like the fleet map (project → checkout → month → day), mirrored under the fleet directory by ad-fleet worklog, previewed by the wrap-up's onenote row; the OneNote writers are not built yet |
docs/data-format-policy.md |
the determinant: which format, when |
docs/setup.md |
what the wizard configures, env overrides, Windows notes |
docs/windows-verification.md |
laptop-only verification runbook (toil, Jira, drivers, TE2, dscmd, Desktop) with paste-back instructions |
docs/copilot-personalization.md |
the Microsoft 365 Copilot custom-instructions block, and why repo rules belong in AGENTS.md instead |
docs/plan-luna-pipeline.md |
approved design for the Power BI / UAT / SQL-guardrail phase (implemented) |
docs/plan-m365-bridge.md |
proposed (2026-10-09): the Microsoft 365 lane — Power Automate as the second relay, SharePoint and OneDrive as sources ("on the fly RAG" into the ticket's folder), results out behind the gate, and the loop between triggered Microsoft agents and the fleet's Copilot agents |
docs/spike-onenote.md |
research spike (2026-10-09): what the fleet can do with OneNote — a project notebook as ticket context, the fleet's log as an appended page, an Agent inbox section as intake, Copilot Notebooks as the reasoning surface; the direct and relayed paths and their limits |
docs/plan-onenote-worklog.md |
proposed (2026-10-09): the fleet's worklog in OneNote, a notebook laid out like the fleet map (project → checkout → month → day), mirrored from a local worklog folded from the event stream, written by the wrapup |
docs/spike-tools-and-fleet-improvements.md |
research spike (2026-10-10): open-source tools for what we use most and design ideas for the fleet, engineering performance first (coverage sysmon, Copilot CLI telemetry, ruff, testmon, Playwright traces), then UI, then UX; what not to adopt and why |
docs/plan-cli-theming.md |
planned design for CLI theming (epic #135): the palette model, the host matrix, one theme per project |
docs/plan-desk-refactor.md |
planned refactor of the fleet dashboard on Windows: the run you are in, movable tiles, HIG chrome, and one palette shared with the terminal |
docs/desk-components.md |
the fleet desk's component inventory and the render contract every one of them keeps: created once, patched forever, one owner per property; and where a component's reasoning lives, the tagalong <file>.md beside each served file (#523) |
docs/desk-window.md |
the row of panes: the tiers and the widths they change at (CI's and the laptop's, set as fleet.tiers.*), a window's widths, the gutters and their snaps, the presets, the pointer drag, the keys |
docs/desk-rendering.md |
the rules a canvas on the desk keeps, the activity trace (an hour in sixty numbers) and the glass ground that drifts |
docs/desk-engines.md |
what each engine does with the platform features the desk uses, what happens on the ones that have not got them, and the numbers measured here |
docs/desk-ink.md |
the ink layer (#248): one three.js canvas behind the desk, a lane of drawing per agent, marks derived from the page's own classes and drawn by pencil, pen, marker and highlighter, the gate a shell's WebGL probe sets, and the plain CSS fallback — built, and drawn with by the notebook |
docs/skin-notebook.md |
the notebook and the night notebook (#249, #250): the first skin drawn with ink — the state grammar's reference marks, a ruled paper, gel inks by night, and the same table plain where WebGL is off |
docs/desk-instant.md |
paint, post, reconcile: the optimistic arrangement and its way back, one round trip per action, the stale desk while the new one loads, and the 50ms budget |
docs/desk-motion.md |
the desk's motion budget — three duration tokens, one arrival pattern, one door for a layout change, and what is asserted about all of it |
docs/desk-types.md |
the desk's types without a build: tsc --noEmit over JSDoc in common.js and app.js, what is typed and why the whole of both files is read, and what the check found (#236) |
docs/plan-column.md |
implemented: the column (epic #200) — one tile open, every other session a band in a column that fills the page; hide, refresh and the model on every band and tile; one session control where the strip was |
docs/plan-meter.md |
implemented: the meter (epic #201) — spend, budget and model on every tile, a fleet total, one arithmetic, a ledger that survives the log rolling; the caps deferred and named |
docs/plan-fresh.md |
planned: fresh (epic #238) — every session records the install it started on, staleness shows on every tile at every turn, and ad-fleet renew starts fresh sessions for the stale agents when they are idle, previewed first |
docs/plan-panes.md |
planned: panes — the snap-back and the stale questions fixed first, then one arrangement where every agent is its own full-height column, drawn by its width (rail, compact, full) and resized by dragging the gutter between any two |
docs/plan-ink.md |
planned: ink (epic #246) — three.js draws every skin: a notebook, its dark twin, a legal pad, napkin notes and graph paper drawn live by pencil, pen, highlighter and marker, then glass, farmstead and voxel moved onto it, with one plain fallback where WebGL is missing |
docs/plan-ownership.md |
implemented: ownership (epic #202) — every desk component named and owned, a render that patches and never rebuilds, motion with a budget, the tile as a window, rendering that earns its pixels, an instant feel |
docs/plan-command-center.md |
implemented: the Command Center (ad-fleet command, the desk's day → command center…) — every open ticket assigned to you that has acceptance criteria and a real description, seated at a free agent of its project, all started with one press; the rest shown with why they were not slated |
prompts/remediate-from-friction.prompt.md |
offline frontier-model repair loop |
agentdata/templates/project-stub/ |
the project stub ad-setup --project writes (ships in the wheel) |
pncli (@kolatts/pncli) is the fundamental inspiration for this repository: one CLI an agent could
run over Jira, Confluence and Bitbucket. ad-* grew out of using it, and its shape is all through this
code: the read/write split behind an approval gate, the npm shim handling, the column names a Jira read
answers with. toil (@imagile-dev/toil), its successor, is the service backend since 0.22.0: it is
used directly for everything it does, and this repository builds only what extends it -- history and
workflow writes in ad-jira (whose REST calls go through toil's connection), the gated page and PR
writes in ad-confluence publish and ad-git pr, the fleet's shim that refuses a toil write.
docs/toil-parts.md keeps the full account.
pbi-tools (AGPL) taught the PBIP side (docs/pbi-tools-parts.md), and Poly Haven's and MakeHuman's CC0
assets dressed the world before it moved to play-sports.
A changelog pull spends the human's Jira token — so every run has a ceiling of its own rather than a
rate limit to discover. --max-requests (2000) and --max-seconds (900) stop it; --bulk-issues (200) and
--bulk-page (500) size the bulkfetch calls; --stats prints what the run cost, in the TOON meta and one line on
stderr; --quiet silences the progress lines. Cloud's rate-limit headers are read on every response, so the last
requests before a limit are a pause instead of a refusal.
A partial pull is now a distinct outcome from a failure. A budget stop, a Ctrl-C, an unrecoverable HTTP error or
Data Center's truncated ?expand=changelog all keep what was fetched on disk and finish the TOON with
partial: true, the reason, the counts and a literal resume command. Rerunning that command is the resume:
rows are cached per issue and keyed on its updated stamp — an issue's changelog cannot change without that stamp
moving — so the second run asks Jira only for what is missing. ad-jira cache --stats and ad-jira cache --clear
manage the cache (.agent/out/.jira-changelog-cache/); --refresh refetches everything for the day the stamp lies,
--no-cache turns it off. ad-jira sprint-replay refuses a partial changelog outright unless --allow-partial
says otherwise, because a committed_points over half the histories looks exactly like a real number.
Full data always goes to disk (.agent/out/). Context gets TOON: inline if
small, header+sample+stats if medium, schema+sample if large. JSON only for
--raw debugging. See docs/data-format-policy.md.