Metadata-Version: 2.4
Name: workmap
Version: 0.1.0
Summary: A desk map for the Terminal windows you already have: projects, RAM, and one key to clean up.
Project-URL: Homepage, https://github.com/athledev-labs/workmap
Project-URL: Issues, https://github.com/athledev-labs/workmap/issues
Project-URL: Source, https://github.com/athledev-labs/workmap
License: MIT License
        
        Copyright (c) 2026 athledev-labs
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: developer-tools,macos,memory,terminal,tui
Classifier: Environment :: Console
Classifier: Environment :: MacOS X
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS :: MacOS X
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Utilities
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# workmap

**Manage your coding agents across projects, in Terminal.**

`macOS` · `Terminal.app` · `Python 3.9+, no dependencies to run`

Two commands.

### `work` starts a session

Pick a project from the list, or name one: `work myproject`. Either way it
puts you in that directory, colours and titles the tab, and launches the agent
you pick.

<img src="docs/work.gif" alt="running work, picking a project and an agent from a numbered list" width="367">

### `workmap` shows you everything you have open

Grouped by project, with what each one is using in RAM.

<img src="docs/desk.gif" alt="the workmap desk: sessions grouped by project, selecting one, quitting its orphaned processes and watching the memory come back" width="611">

Rows marked **orphaned** are dev servers and agents still running with no
Terminal window left to close. `k` quits them, and names them before it does,
five at a time; `workmap kill -n` lists them all without quitting anything:

<img src="docs/confirm.svg" alt="the confirmation prompt naming the processes it will quit, by pid" width="592">

It doesn't own your sessions. No tmux, no wrapper, no new way to open a
terminal. It reads the windows you already have.

## Install

```sh
git clone https://github.com/athledev-labs/workmap.git
cd workmap
./install.sh
```

That is the whole thing, and it works on a Mac with nothing installed on it
beyond what Apple ships.

If the last line says `permission denied`, run `sh install.sh` instead. That
happens when the files arrived as a downloaded ZIP rather than a clone, which
drops the flag that marks a script runnable.

If you already have `uv` or `pipx`, either does it in one line without a
clone:

```sh
uv tool install git+https://github.com/athledev-labs/workmap.git
pipx install git+https://github.com/athledev-labs/workmap.git
```

Those two are offered rather than led with, because neither `uv` nor `pipx` is
on a Mac until you put it there, and installing a package manager in order to
install a package manager's package is a worse first step than cloning.

You need a Mac with the Xcode command line tools, which is what gives you
`git` and `python3`, and a working connection to `pypi.org` for the length of
the install. workmap itself downloads nothing and depends on nothing, but pip
fetches the package it builds the wheel with, so an offline machine cannot
install it. Nothing else is needed and no version of anything has to be
matched.

`install.sh` uses `uv` or `pipx` when either is on PATH, and otherwise a
private virtualenv under `~/.local/share/workmap/venv`. To try a prefix
without touching the real install:

```sh
WORKMAP_PREFIX=/tmp/workmap-prefix ./install.sh
/tmp/workmap-prefix/bin/workmap --version
```

Then:

```sh
workmap setup
```

It asks where your projects are, shows which agents you actually have
installed, and offers to add one line to your shell. Nothing is written
without asking, and it's safe to re-run. `workmap demo` runs that same first
run against a fake machine in a temp directory if you'd rather look first.

If `~/.local/bin` isn't on your PATH yet, `python3 -m workmap` runs the same
thing until you've added it.

The first launch asks for Automation permission, because reading your windows
means talking to Terminal. Decline it and workmap says so rather than showing
you an empty desk.

The first time it names a window, it also turns "custom title" on for each of
Terminal's built-in profiles, and turns off the two bits Terminal adds around
it, "window size" and "shell path". Otherwise the name workmap gives a window
is either not shown at all or lost between the shell path and `80x24`. It's
the one thing workmap changes outside its own files, it happens once per run,
and any of it goes back in Terminal > Settings > Profiles > Window. workmap
says so on screen the first time it does it, so you do not have to have read
this paragraph to find out.

## Use

```sh
workmap                 # the map above
workmap list            # the same thing as text
workmap kill -n         # name what it would quit, without quitting it
workmap kill            # quit them
workmap log             # the last 20 things workmap quit
workmap log 100         # more of them
```

`workmap --help` has the rest, with your own project names in the examples.

Every signal is written to `~/.local/state/workmap/kills.jsonl` before it's
sent and the outcome after, so a kill that surprises you can be read back. The
file is trimmed to the newest 5000 records once it passes 4 MB, so it is a
long memory rather than a permanent one.

## `work`

```sh
work                       # pick a project, then an agent
work <project>             # that project, ask which agent
work <project> claude      # no questions
work <project> "npm test"  # anything unrecognised is run literally
```

Only your own shell can change its own directory, so `work` is a shell
function workmap prints and your shell evaluates, the same arrangement
`zoxide init` and `direnv hook` use. `workmap setup` offers to add it:

```sh
eval "$(workmap shell-init zsh)"    # ~/.zshrc, or bash in ~/.bashrc
```

Already have a `work` command? `workmap setup` notices and calls its one `wm`
instead, leaving yours alone. `--name proj` picks any other name yourself.

## Configure

**A project is the first directory _under_ a root**, so a root is the
directory that *contains* your projects. If your work is in
`~/dev/Company/api` and `~/dev/Company/web`, the root is `~/dev/Company`;
pointing at `~/dev` would name every project "Company". It's the one setting
worth getting right, and `workmap setup` asks about it.

To edit directly, `~/.config/workmap/projects.json`:

```json
{
  "roots": ["~/dev/Company", "~/oss"],
  "profiles": { "api": "Ocean", "web": "Grass" },
  "agents": { "claude": "claude --dangerously-skip-permissions" },
  "default_agent": "claude"
}
```

`profiles` gives a project a Terminal colour so its windows are recognisable
at a glance; `c` in the map changes it, and anything you haven't picked gets a
colour derived from its name. Set an agent to `""` to take it off the list.
`WORKMAP_ROOTS="$HOME/dev/Company:$HOME/oss"` overrides the file.

## Known limits

- **macOS only, and not by accident.** Three separate dependencies: the
  AppleScript that reads Terminal, the memory figures (`top -l 1` for
  phys_footprint, `vm_stat`, `sysctl vm.swapusage`), and the `.app` bundle
  rule that stops the sweep force-quitting a running application. Only the
  first is behind a seam. Elsewhere, workmap says so and exits rather than
  reporting an empty desk.
- Terminal.app only, within macOS. Drivers are pluggable and the contract has
  a conformance suite, but one driver exists, so the seam is untested.
- Some background processes are not classified, `node .../bin/daemon.mjs`
  among them. Naming them from their path is what once had workmap SIGKILLing
  a running app's helpers in a loop, so it's deliberately left alone. The cost
  is a missed orphan.
- A process whose executable is inside a `.app` bundle is assumed to belong to
  a running application and is never swept, unless it's an interpreter (every
  macOS Python lives inside a `Python.app`).
- `w` can't close a window whose foreground process has already exited, the
  ones showing `[Process completed]`; Terminal ignores the request without
  reporting an error. workmap counts what actually closed and tells you the
  difference rather than claiming them.
- `o`, `O` and `organize` can't move a window macOS is tiling. Dragging a
  window to the edge of the screen puts it in a tile group, and after that
  Terminal accepts the request to move it and discards it, again without an
  error. Measured on a real desk: the window reported the same position before
  and after. workmap counts what actually moved and names tiling as the
  reason, rather than reporting a layout that did not happen. Drag the window
  out of its tile, or turn tiling off in System Settings, under Desktop and
  Dock.
- Of the eight agents offered, only claude, codex and cursor-agent have been
  confirmed to exist under those names. `shutil.which` gates all of them.
- A pane inside `tmux` or `screen` is a live session the emulator cannot see.
  workmap asks tmux which panes it has and leaves those alone, attached or
  not, so a session you can still `tmux attach` to is never on the kill list.
  Anything it cannot ask keeps everything under it: `screen` always, because
  the version macOS ships cannot answer, and tmux when the query fails. Either
  way the desk says so instead of looking like a quiet machine.
- `s` asks a separate tool called `devstack` to bring a project's servers
  down before quitting its orphans. workmap does not ship it and does not
  need it: without it, `s` quits the orphans and says so.
- Verified against one machine: ~1000 processes, one roots layout, one user.

## Contributing

[ARCHITECTURE.md](ARCHITECTURE.md) has the layering, the rules worth knowing
before changing anything, the contract a second terminal driver has to meet,
and how to run the tests. The pictures above are composed from real frames by
`tools/render_svg.py` and `tools/render_gif.py`, so none of them can show a
layout the tool does not have. A test regenerates the still and fails if it has
drifted; the animations go through Chrome and ffmpeg, whose output is not
byte-stable, so those are re-run by hand.

## Licence

MIT
